
网络工程试验报告
端口扫描报告
09109146
王子龙
1.端口及端口扫描技术简介
根据提供服务类型的不同,端口分为两种,一种是TCP端口,一种是UDP端口。计算机之间相互通信的时候,分为两种方式:一种是发送信息以后,可以确认信息是否到达,也就是有应答的方式,这种方式大多采用TCP协议;一种是发送以后就不管了,不去确认信息是否到达,这种方式大多采用UDP协议。对应这两种协议的服务提供的端口,也就分为TCP端口和UDP端口。
一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等,这些服务完全可以通过1个IP地址来实现。主机不只是靠IP地址来区分网络服务,因为IP 地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的。
一个端口就是一个潜在的通信通道,也就是一个入侵通道。对目标计算机进行端口扫描,能得到许多有用的信息。进行扫描的方法很多,可以是手工进行扫描,也可以用端口扫描软件进行。
在手工进行扫描时,需要熟悉各种命令。对命令执行后的输出进行分析。用扫描软件进行扫描时,许多扫描器软件都有分析数据的功能。
通过端口扫描,可以得到许多有用的信息,从而发现系统的安全漏洞。
2.对现有端口扫描工具程序的理解
该程序是有C++编写的。C++是一种使用非常广泛的计算机编程语言。C++是一种静态数据类型检查的、支持多重编程范式的通用程序设计语言。它支持过程化程序设计、数据抽象、面向对象程序设计、制作图标等等泛型程序设计等多种程序设计风格。
该程序能够扫描主机IP的某一个端口,或者是扫描该主机IP某一范围内的端口。并且提供多次扫描功能。如果要扫描的端口很多,在扫描过程中可以暂停扫描。扫描结果在界面的下方显示。主要显示内容有IP地址、端口号、端口状态、连接次数及备注。
主界面
本机ip地址为169.254.103.168
用端口扫描工具扫描135端口,135端口处于打开状态
扫描处于某一范围内的端口号,比如80—90,任务进展将在界面下方显示,
并且提示当前扫描哪一个端口及尝试扫描次数。
最终的扫描结果可以通过txt文本导出
3.核心代码
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CPortScanView
IMPLEMENT_DYNCREATE(CPortScanView, CFormView)
BEGIN_MESSAGE_MAP(CPortScanView, CFormView)
//{{AFX_MSG_MAP(CPortScanView)
ON_WM_CTLCOLOR()
ON_WM_SHOWWINDOW()
ON_BN_CLICKED(IDC_RADIO_SINGLE, OnRadioSingle)
ON_BN_CLICKED(IDC_RADIO_RANGE, OnRadioRange)
ON_BN_CLICKED(IDC_BUTTON_SCAN, OnButtonScan)
ON_BN_CLICKED(IDC_BUTTON_STOP, OnButtonStop)
ON_COMMAND(ID_FILE_SAVE, OnFileSave)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPortScanView construction/destruction
CPortScanView::CPortScanView()
: CFormView(CPortScanView::IDD)
{
//{{AFX_DATA_INIT(CPortScanView)
//}}AFX_DATA_INIT
// TODO: add construction code here
m_pBrush = new CBrush;
ASSERT(m_pBrush);
//m_clrBk = RGB(0x00,0x00,0x77);
m_clrText = RGB(0xff,0xff,0x00);
//m_pBrush->CreateSolidBrush(m_clrBk);
m_pColumns = new CStringList;
ASSERT(m_pColumns);
m_bSinglePort = TRUE;
m_nMaxAttempts = 1; //default value, This value has been set on the window
m_pStatusList = new CPtrList;
ASSERT(m_pStatusList);
}
CPortScanView::~CPortScanView()
{
if (m_pStatusList)
{
//First Empty the port status list:
POSITION p = m_pStatusList->GetHeadPosition();
while (p)
{
POSITION temp = p;
DATA* pNode = (DATA*)m_pStatusList->GetNext(p);
m_pStatusList->RemoveAt(temp);
if (pNode)
delete pNode;
}
//Then remove it from heap:
delete m_pStatusList;
}
if (m_pBrush)
delete m_pBrush;
}
void CPortScanView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPortScanView)
DDX_Control(pDX, IDC_PROGRESS, m_cProgress);
DDX_Control(pDX, IDC_EDIT_ATTEMPTS, m_cAttempts);
DDX_Control(pDX, IDC_BUTTON_STOP, m_cBtnStop);
DDX_Control(pDX, IDC_LIST_RESULT, m_cResult);
DDX_Control(pDX, IDC_BUTTON_SCAN, m_cBtnScan);
DDX_Control(pDX, IDC_IP_ADDRESS, m_cIP);
DDX_Control(pDX, IDC_EDIT_SINGLE_PORT_TO, m_cPortTo);
DDX_Control(pDX, IDC_EDIT_SINGLE_PORT_FROM, m_cPortFrom);
DDX_Control(pDX, IDC_EDIT_SINGLE_PORT, m_cSinglePort);
//}}AFX_DATA_MAP
}
BOOL CPortScanView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CFormView::PreCreateWindow(cs);
}
void CPortScanView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit(FALSE);
ResizeParentToFit();
ShowHeaders();
CheckRadioButton(IDC_RADIO_SINGLE,IDC_RADIO_RANGE,IDC_RADIO_SINGLE);
m_cSinglePort.EnableWindow();
m_cPortFrom.EnableWindow(FALSE);
m_cPortTo.EnableWindow(FALSE);
m_parent = (CMainFrame*)GetParent();
ASSERT(m_parent);
// m_cBtnStop.EnableWindow(FALSE);
m_cAttempts.SetWindowText(_T("1"));
}
/////////////////////////////////////////////////////////////////////////////
// CPortScanView diagnostics
#ifdef _DEBUG
void CPortScanView::AssertValid() const
{
CFormView::AssertValid();
}
void CPortScanView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
CPortScanDoc* CPortScanView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPortScanDoc)));
return (CPortScanDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CPortScanView message handlers
HBRUSH CPortScanView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor);
//break statement must be ignored:
switch(nCtlColor)
{
case CTLCOLOR_BTN:
case CTLCOLOR_STATIC:
pDC->SetBkColor(m_clrBk);
pDC->SetTextColor(m_clrText);
case CTLCOLOR_DLG:
return static_cast } // TODO: Return a different brush if the default is not desired return CFormView::OnCtlColor(pDC,pWnd,nCtlColor); } BOOL CPortScanView::AddColumn(LPCTSTR strItem,int nItem,int nSubItem,int nMask,int nFmt) { LV_COLUMN lvc; lvc.mask = nMask; lvc.fmt = nFmt; lvc.pszText = (LPTSTR) strItem; lvc.cx = m_cResult.GetStringWidth(lvc.pszText) + 25; if(nMask & LVCF_SUBITEM) { if(nSubItem != -1) lvc.iSubItem = nSubItem; else lvc.iSubItem = nItem; } return m_cResult.InsertColumn(nItem,&lvc); } BOOL CPortScanView::AddItem(int nItem,int nSubItem,LPCTSTR strItem ,int nImageIndex) { LV_ITEM lvItem; lvItem.mask = LVIF_TEXT; lvItem.iItem = nItem; lvItem.iSubItem = nSubItem; lvItem.pszText = (LPTSTR) strItem; if(nImageIndex != -1) { lvItem.mask |= LVIF_IMAGE; lvItem.iImage |= LVIF_IMAGE; } if(nSubItem == 0) return m_cResult.InsertItem(&lvItem); return m_cResult.SetItem(&lvItem); } void CPortScanView::AddHeader(LPTSTR hdr) { if (m_pColumns) m_pColumns->AddTail(hdr); } void CPortScanView::ShowHeaders() { int nIndex = 0; POSITION pos = m_pColumns->GetHeadPosition(); while (pos) { CString hdr = (CString)m_pColumns->GetNext(pos); AddColumn(hdr,nIndex++); } } void CPortScanView::OnShowWindow(BOOL bShow, UINT nStatus) { CFormView::OnShowWindow(bShow, nStatus); AddHeader(_T("IP地址")); AddHeader(_T("端口号")); AddHeader(_T("端口状态")); AddHeader(_T("连接次数")); AddHeader(_T("备注")); } void CPortScanView::OnRadioSingle() { m_bSinglePort = TRUE; m_cSinglePort.EnableWindow(); m_cPortFrom.EnableWindow(FALSE); m_cPortTo.EnableWindow(FALSE); } void CPortScanView::OnRadioRange() { m_bSinglePort = FALSE; m_cSinglePort.EnableWindow(FALSE); m_cPortFrom.EnableWindow(); m_cPortTo.EnableWindow(); m_cBtnStop.EnableWindow(FALSE); } //开始扫描按钮处理程序 void CPortScanView::OnButtonScan() { CString btnTxt,IP; UINT nSinglePort; BYTE f1,f2,f3,f4; TCHAR temp[10] = "\\0"; m_cProgress.SetPos(0); m_cResult.DeleteAllItems(); //清空列表框 POSITION p = m_pStatusList->GetHeadPosition(); while (p) { POSITION temp = p; DATA* pNode = (DATA*)m_pStatusList->GetNext(p); m_pStatusList->RemoveAt(temp); //循环删除 if (pNode) delete pNode; } //验证IP地址是否为空 if (m_cIP.IsBlank()) { MessageBox(_T("请输入IP地址."), _T("Error"), MB_OK | MB_ICONEXCLAMATION); return; } //验证IP地址是否正确 if (m_cIP.GetAddress(f1,f2,f3,f4) < 4) { MessageBox(_T("请确认IP地址."), _T("Invalid IP address"),MB_OK | MB_ICONEXCLAMATION); return; } //进行IP地址转化 IP = _itoa(f1,temp,10); IP += _T('.'); IP += _itoa(f2,temp,10); IP += _T('.'); IP += _itoa(f3,temp,10); IP += _T('.'); IP += _itoa(f4,temp,10); m_cBtnStop.EnableWindow(); m_cBtnScan.EnableWindow(FALSE); //是否是单个端口扫描 if (m_bSinglePort) { CString port; m_cSinglePort.GetWindowText(port); m_minPort = m_maxPort = nSinglePort = atoi(port); } else { CString port1,port2; m_cPortFrom.GetWindowText(port1); m_cPortTo.GetWindowText(port2); m_minPort = atoi(port1); m_maxPort = atoi(port2); m_cProgress.SetRange32(0,m_maxPort-m_minPort+1); m_cProgress.SetStep(1); } if (!m_bSinglePort && m_maxPort < m_minPort) { MessageBox(_T("最大端口要大于最小端口."), _T("Caution"), MB_OK | MB_ICONINFORMATION); return; } UINT m_nMaxAttempts = GetDlgItemInt(IDC_EDIT_ATTEMPTS); for (m_nCounter = m_minPort; m_nCounter <= m_maxPort; m_nCounter++) { BOOL bIsOpen = FALSE; UINT nAttempt = 1; while(nAttempt <= m_nMaxAttempts && !bIsOpen) { TCHAR temp[10]="\\0"; CString str = _T("连接端口# "); #ifdef _UNICODE str += _itow(m_nCounter,temp,10); #else str += itoa(m_nCounter,temp,10); #endif str += _T(", IP地址="); str += IP; str += _T(", Attempt="); #ifdef _UNICODE str += _itow(nAttempt,temp,10); #else str += itoa(nAttempt,temp,10); #endif //设定状态栏 m_parent->SetStatusBarText(str); str.Empty(); //打开连接 bIsOpen = TestConnection(IP,m_nCounter); //判断是否打开 if (bIsOpen) { DATA* pNode = new DATA; ASSERT(pNode); strcpy(pNode->IPAddress,IP.GetBuffer(IP.GetLength())); strcpy(pNode->port,_itoa(m_nCounter,temp,10)); pNode->bStatus = 1; //open pNode->nAttempts = nAttempt; m_pStatusList->AddTail(pNode); } //试图连接次数 nAttempt++; } //如果还是无法扫描成功 if (!bIsOpen) { DATA* pNode = new DATA; ASSERT(pNode); strcpy(pNode->IPAddress,IP.GetBuffer(IP.GetLength())); strcpy(pNode->port,_itoa(m_nCounter,temp,10)); pNode->bStatus = 0; //关闭状态 pNode->nAttempts = nAttempt-1; m_pStatusList->AddTail(pNode); } MSG message; if (::PeekMessage(&message,NULL,0,0,PM_REMOVE)) { ::TranslateMessage(&message); ::DispatchMessage(&message); } m_cProgress.StepIt(); } //设定状态栏 m_parent->SetStatusBarText((CString)_T("完毕")); m_cBtnScan.EnableWindow(); m_cBtnStop.EnableWindow(FALSE); //填充报表视图 UINT nIndex = 0; POSITION pos = m_pStatusList->GetHeadPosition(); //循环插入扫描结果 while (pos) { DATA* pNode = (DATA*)m_pStatusList->GetNext(pos); AddItem(nIndex,0,pNode->IPAddress); AddItem(nIndex,1,pNode->port); if (pNode->bStatus) { AddItem(nIndex,2,_T("打开")); AddItem(nIndex,4,_T("*")); } else { AddItem(nIndex,2,_T("关闭")); AddItem(nIndex,4,_T(" ")); } AddItem(nIndex++,3,_itoa(pNode->nAttempts,temp,10)); } } //打开连接 BOOL CPortScanView::TestConnection(CString IP, UINT nPort) { CTheSocket* pSocket; pSocket = new CTheSocket; ASSERT(pSocket); //创建socket if (!pSocket->Create()) { //如果创建失败,则删除,返回 false delete pSocket; pSocket = NULL; return FALSE; } //连接被连接的主机地址和指定端口 while (!pSocket->Connect(IP , nPort)) { //如果失败返回false delete pSocket; pSocket = NULL; return FALSE; } //关闭socket pSocket->Close(); delete pSocket; return TRUE; } void CPortScanView::OnButtonStop() { m_nCounter = m_maxPort+1; m_cBtnStop.EnableWindow(FALSE); m_cBtnScan.EnableWindow(); m_parent->SetStatusBarText((CString)_T("Ready")); } //保存成文件 void CPortScanView::OnFileSave() { CFileDialog* pDlg = new CFileDialog(FALSE, _T("txt"),NULL, OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_LONGNAMES, _T("Scanned ports files (*.txt)"),this); ASSERT(pDlg); if (pDlg->DoModal() == IDOK) { int nHandle,retVal; nHandle = _open(pDlg->GetPathName(),_O_BINARY | _O_CREAT | _O_TRUNC | _O_RDWR); if (nHandle == -1) { MessageBox(_T("Unable to open output file to write."), _T("Error"), MB_OK | MB_ICONEXCLAMATION); delete pDlg; return; } POSITION pos = m_pStatusList->GetHeadPosition(); while (pos) { CString buffer; DATA* pNode = (DATA*)m_pStatusList->GetNext(pos); buffer = pNode->IPAddress; buffer += _T(','); buffer += pNode->port; buffer += _T(','); if (pNode->bStatus) buffer += _T("Open"); else buffer += _T("Close"); buffer += _T("\\r\\n\\0"); retVal = _write(nHandle, (void*)buffer.GetBuffer(buffer.GetLength()), buffer.GetLength()); if (retVal != buffer.GetLength()) { MessageBox(_T("An error occured while writing records."), _T("Error"),MB_OK | MB_ICONEXCLAMATION); delete pDlg; return; } buffer.Empty(); } _close(nHandle); } delete pDlg; } 4.个人总结 由于不熟悉C++语言,看这个端口扫描工具程序颇为吃力。因为时间和能力有限,对该程序代码只是略微了解。该程序仍然存在这一些不足之处,比如说在扫描一个端口后,扫描进度的状态仍然处于等待扫描状态。此处需要改进。
