C++端口复用代码
主要用到的函數(shù):
int?setsockopt(?SOCKET?s,?int?level,?int?optname,?const?char?FAR?*optval,?int?optlen?);
s:標識一個套接口的描述字。
level:選項定義的層次;支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。
optname:需設置的選項。
optval:指針,指向存放選項待設置的新值的緩沖區(qū)。
optlen:optval緩沖區(qū)長度。
第三個列表及意義:
注意:
地址監(jiān)聽的時候地址的寫法有好幾種(只考慮獨立網(wǎng)卡):
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的地址,這個地址事實上表示不確定地址,或“所有地址”、“任意地址”。?一來般說,在各個系統(tǒng)中均定義成為0值。監(jiān)聽它時客戶端無論是連接127.0.0.1還是192.168.0.44都能正確的連接到。如果同時監(jiān)聽了192.168.0.44和INADDR_ANY,連接(192.168.0.44)則先連接前者,前者不存在才會連接后者。
?
SO_REUSEADDR提供如下四個功能:
1.SO_REUSEADDR允許啟動一個監(jiān)聽服務器并捆綁其眾所周知端口,即使以前建立的將此端口用做他們的本地端口的連接仍存在。這通常是重啟監(jiān)聽服務器時出現(xiàn),若不設置此選項,則bind時將出錯。
2.SO_REUSEADDR允許在同一端口上啟動同一服務器的多個實例,只要每個實例捆綁一個不同的本地IP地址即可。對于TCP,我們根本不可能啟動捆綁相同IP地址和相同端口號的多個服務器。????
3.SO_REUSEADDR允許單個進程捆綁同一端口到多個套接口上,只要每個捆綁指定不同的本地IP地址即可。這一般不用于TCP服務器。
4.SO_REUSEADDR允許完全重復的捆綁:當一個IP地址和端口綁定到某個套接口上時,還允許此IP地址和端口捆綁到另一個套接口上。一般來說,這個特性僅在支持多播的系統(tǒng)上才有,而且只對UDP套接口而言(TCP不支持多播)。
????
測試結果的總結:
1.如果采用復用端口方式運行程序,則表示該程序監(jiān)聽的地址可以與其他程序共享
2.如果不采用復用端口方式運行程序,則表示此程序獨占這個監(jiān)聽地址,比如(“127.0.0.1”)
?
可以進行如下的攻擊:?
1。一個木馬綁定到一個已經(jīng)合法存在的端口上進行端口的隱藏,他通過自己特定的包格式判斷是不是自己的包,如果是自己處理,如果不是通過127.0.0.1的地址交給真正的服務器應用進行處理。?
2。一個木馬可以在低權限用戶上綁定高權限的服務應用的端口,進行該處理信息的嗅探,本來在一個主機上監(jiān)聽一個SOCKET的通訊需要具備非常高的權限要求,但其實利用SOCKET重綁定,你可以輕易的監(jiān)聽具備這種SOCKET編程漏洞的通訊,而無須采用什么掛接,鉤子或低層的驅動技術(這些都需要具備管理員權限才能達到)?
3。針對一些的特殊應用,可以發(fā)起中間人攻擊,從低權限用戶上獲得信息或事實欺騙,如在guest權限下攔截telnet服務器的23端口,如果是采用NTLM加密認證,雖然你無法通過嗅探直接獲取密碼,但一旦有admin用戶通過你登陸以后,你的應用就完全可以發(fā)起中間人攻擊,扮演這個登陸的用戶通過SOCKET發(fā)送高權限的命令,到達入侵的目的。?
4.對于構建的WEB服務器,入侵者只需要獲得低級的權限,就可以完全達到更改網(wǎng)頁目的,很簡單,扮演你的服務器給予連接請求以其他信息的應答,甚至是基于電子商務上的欺騙,獲取非法的數(shù)據(jù)。
全部代碼:
//工作區(qū)域// //復用程序只有一個可以獲得到數(shù)據(jù),并且是先啟動的那個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函數(shù)出錯"));return 0;}int retBind=bind(gServerListenSock,(sockaddr*)&serverAddr,sizeof(sockaddr_in));if (SOCKET_ERROR==retBind){AfxMessageBox(_T("bind函數(shù)出錯"));return 0;}int retListen=listen(gServerListenSock,5);if (SOCKET_ERROR==retListen){AfxMessageBox(_T("listen函數(shù)出錯"));return 0;}else{AfxMessageBox(_T("監(jiān)聽成功"));}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函數(shù)出錯"));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);}?
總結
- 上一篇: 端口复用突破防火墙(图)
- 下一篇: C++使用MD5