1. 程式人生 > 其它 >c++ windows 埠複用例子及利弊

c++ windows 埠複用例子及利弊

技術標籤:c/c++

主要用到的函式:

intsetsockopt(SOCKETs,intlevel,intoptname,constcharFAR*optval,intoptlen);

s:標識一個套介面的描述字。

level:選項定義的層次;支援SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。

optname:需設定的選項。

optval:指標,指向存放選項待設定的新值的緩衝區

optlen:optval緩衝區長度。

第三個列表及意義:

注意:

地址監聽的時候地址的寫法有好幾種(只考慮獨立網絡卡):

serverAddr.sin_addr.S_un.S_addr=inet_addr("192.168.0.44");

serverAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");

serverAddr.sin_addr.S_un.S_addr=INADDR_ANY;

INADDR_ANY就是指定地址為0.0.0.0的地址,這個地址事實上表示不確定地址,或“所有地址”、“任意地址”。一來般說,在各個系統中均定義成為0值。監聽它時客戶端無論是連線127.0.0.1還是192.168.0.44都能正確的連線到。如果同時監聽了192.168.0.44和INADDR_ANY,連線(192.168.0.44)則先連線前者,前者不存在才會連線後者。

SO_REUSEADDR提供如下四個功能:

1.SO_REUSEADDR允許啟動一個監聽伺服器並捆綁其眾所周知埠,即使以前建立的將此埠用做他們的本地埠的連線仍存在。這通常是重啟監聽伺服器時出現,若不設定此選項,則bind時將出錯。

2.SO_REUSEADDR允許在同一埠上啟動同一伺服器的多個例項,只要每個例項捆綁一個不同的本地IP地址即可。對於TCP,我們根本不可能啟動捆綁相同IP地址和相同埠號的多個伺服器。

3.SO_REUSEADDR允許單個程序捆綁同一埠到多個套介面上,只要每個捆綁指定不同的本地IP地址即可。這一般不用於TCP伺服器。

4.SO_REUSEADDR允許完全重複的捆綁:當一個IP地址和埠繫結到某個套介面上時,還允許此IP地址和埠捆綁到另一個套介面上。一般來說,這個特性僅在支援多播的系統上才有,而且只對UDP套介面而言(TCP不支援多播)。

測試結果的總結:

1.如果採用複用埠方式執行程式,則表示該程式監聽的地址可以與其他程式共享

2.如果不採用複用埠方式執行程式,則表示此程式獨佔這個監聽地址,比如(“127.0.0.1”)

可以進行如下的攻擊:

1。一個木馬繫結到一個已經合法存在的埠上進行埠的隱藏,他通過自己特定的包格式判斷是不是自己的包,如果是自己處理,如果不是通過127.0.0.1的地址交給真正的伺服器應用進行處理。

2。一個木馬可以在低許可權使用者上繫結高許可權的服務應用的埠,進行該處理資訊的嗅探,本來在一個主機上監聽一個SOCKET的通訊需要具備非常高的許可權要求,但其實利用SOCKET重繫結,你可以輕易的監聽具備這種SOCKET程式設計漏洞的通訊,而無須採用什麼掛接,鉤子或低層的驅動技術(這些都需要具備管理員許可權才能達到)

3。針對一些的特殊應用,可以發起中間人攻擊,從低許可權使用者上獲得資訊或事實欺騙,如在guest許可權下攔截telnet伺服器的23埠,如果是採用NTLM加密認證,雖然你無法通過嗅探直接獲取密碼,但一旦有admin使用者通過你登陸以後,你的應用就完全可以發起中間人攻擊,扮演這個登陸的使用者通過SOCKET傳送高許可權的命令,到達入侵的目的。

4.對於構建的WEB伺服器,入侵者只需要獲得低階的許可權,就可以完全達到更改網頁目的,很簡單,扮演你的伺服器給予連線請求以其他資訊的應答,甚至是基於電子商務上的欺騙,獲取非法的資料。

全部程式碼:

//工作區域//
//複用程式只有一個可以獲得到資料,並且是先啟動的那個
 
HWND   gMainWnd;
SOCKET gServerListenSock;
SOCKET gServerFromClient;
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
	WSAData ws;
	WSAStartup(MAKEWORD(2,2),&ws);
	gServerListenSock=socket(AF_INET,SOCK_STREAM,0);
	sockaddr_in serverAddr;
	ZeroMemory(&serverAddr,sizeof(sockaddr_in));
	serverAddr.sin_port=htons(101);
	serverAddr.sin_family=AF_INET;
	serverAddr.sin_addr.S_un.S_addr=INADDR_ANY;//inet_addr("192.168.0.44");//inet_addr("127.0.0.1");//
 
	int bOptval=1;
	int retSetsockopt=setsockopt(gServerListenSock,SOL_SOCKET ,SO_REUSEADDR ,(char *)&bOptval,sizeof(bOptval));
	if (SOCKET_ERROR==retSetsockopt)
	{
		AfxMessageBox(_T("setsockopt函數出錯"));
		return 0;
	}
 
	int retBind=bind(gServerListenSock,(sockaddr*)&serverAddr,sizeof(sockaddr_in));
	if (SOCKET_ERROR==retBind)
	{
		AfxMessageBox(_T("bind函數出錯"));
		return 0;
	}
 
	int retListen=listen(gServerListenSock,5);
	if (SOCKET_ERROR==retListen)
	{
		AfxMessageBox(_T("listen函數出錯"));
		return 0;
	}
	else
	{
		AfxMessageBox(_T("監聽成功"));
	}
 
	sockaddr_in clientAddr;
	int addrlen=sizeof(sockaddr_in);
	ZeroMemory(&clientAddr,sizeof(sockaddr_in));
	gServerFromClient=accept(gServerListenSock,(sockaddr *)&clientAddr,&addrlen);
 
	int e = WSAGetLastError();
 
	char recvBuffer[256]="";
	CString showRecv;
	int retRecv=recv(gServerFromClient,recvBuffer,256,0);
	if (SOCKET_ERROR==retRecv)
	{
		AfxMessageBox(_T("recv函數出錯"));
		return 0;
	}
	else
	{
		showRecv.Format(_T("收到資訊:%s"),recvBuffer);
		::SetDlgItemText(gMainWnd,IDC_STATIC_RECV,showRecv);
 
	}
	exit( 0);
}
 
void CServerDlg::OnBnClickedButton1()
{
	// TODO: 在此新增控制元件通知處理程式程式碼
	gMainWnd=AfxGetMainWnd()->m_hWnd;
	CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
 
}