日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

icmp篇 突破TCP-IP過(guò)濾/防火墻進(jìn)入內(nèi)網(wǎng)( 二 )


同時(shí) , QQ客戶端也在端口4000(假設(shè)為非內(nèi)網(wǎng)主機(jī)上的第一個(gè)QQ)監(jiān)聽(tīng)來(lái)自QQicmp(l)的數(shù)據(jù)報(bào) 。
我們可以看到 , QQicmp(l)的主要作用就是將接收到了來(lái)自QQ客戶端的UPD數(shù)據(jù)報(bào) ,
sock[0][0]=socket(AF_INET,SOCK_DGRAM,0); //創(chuàng)建基于UDP協(xié)議的套接字
bind(sock[0][0],(struct sockaddr *)&sin[0][1],addrlen); //綁定到指定地址 , 指定端口上
iret=recvfrom(sock[0][0],msgrecv,sizeof(msgrecv),0,(struct sockaddr *)&tempr,&addrlen); //接收來(lái)自QQ客戶端的UDP數(shù)據(jù)然后以ICMP數(shù)據(jù)報(bào)的形式發(fā)送到QQicmp(g) , 在此需要自己構(gòu)造ICMP echo Reply數(shù)據(jù)報(bào),并將接收到的UDP數(shù)據(jù)報(bào)填充到ICMP報(bào)文的數(shù)據(jù)段 ,
sock[0][1]=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); //創(chuàng)建ICMP協(xié)議的原始套接字 , 用來(lái)發(fā)送自定義數(shù)據(jù)報(bào)
bind(sock[0][1],(struct sockaddr *)&sin[0][2],addrlen); //并捆綁到指定地址 , 指定端口上icmphdr.type=0; //類型:echo reply
icmphdr.code=0; //代碼
icmphdr.id=htons(65456); //序號(hào)
icmphdr.seq=htons(65456); //標(biāo)志符 , 用以過(guò)濾數(shù)據(jù)報(bào)
icmphdr.checksum=0;if(istbcs==0) //填充ICMP數(shù)據(jù)報(bào)頭部
{
memset(msgsend,0,sizeof(msgsend));
memcpy(msgsend,&icmphdr,sizeof(icmphdr));
istbcs =sizeof(icmphdr);
}
memcpy(msgsend istbcs,msgrecv,iret); //將接收到的UDP數(shù)據(jù)報(bào)的內(nèi)容提取 , 準(zhǔn)備以ICMP的形式發(fā)送iret=sendto(sock[0][1],msgsend,istbcs,0,(struct sockaddr *)&sin[0][3],addrlen); //發(fā)送到網(wǎng)關(guān)
同時(shí) , QQicmp(l)監(jiān)聽(tīng)通過(guò)本機(jī)的IP數(shù)據(jù)報(bào) , 篩選出來(lái)自QQicmp(g)及網(wǎng)關(guān)的數(shù)據(jù)報(bào) ,
sock[1][0]=socket(AF_INET,SOCK_RAW,IPPROTO_IP); //創(chuàng)建原始套接字 , 接收所有的IP數(shù)據(jù)報(bào)
bind(sock[1][0],(struct sockaddr *)&sin[1][1],addrlen); //綁定到指定地址 , 端口DWord dwbufferlen[10];
DWORD dwbufferinlen=1;
DWORD dwbytesreturned=0;
WSAIoctl(sock[1][0],SIO_RCVALL,&dwbufferinlen,sizeof(dwbufferinlen),&dwbufferlen,sizeof(dwbufferlen),&dwbytesreturned,NULL,NULL);
//設(shè)置為接收所有的數(shù)據(jù)報(bào) , 需要mstcpip.h頭文件 , T-QQ相關(guān)文件里就有 , 或安裝SDKiret=recvfrom(sock[1][0],msgrecv,sizeof(msgrecv),0,(struct sockaddr *)&temps,&addrlen); //接收所有數(shù)據(jù)報(bào)
if(iret<=28) //文件過(guò)小
{
break;
}
if((icmphdr->type!=0) || (icmphdr->code!=0) || ((icmphdr->id)!=htons(65456)) || ((icmphdr->seq)!=htons(65456)))
//不符合接收條件
{
break;
}memcpy(msgsend istbcs,msgrecv,iret); //將接收到的ICMP數(shù)據(jù)報(bào)的內(nèi)容提取 , 準(zhǔn)備以UDP的形式發(fā)送
解包后 , 用UDP數(shù)據(jù)報(bào)將接收到的來(lái)自網(wǎng)關(guān)的數(shù)據(jù)發(fā)送到QQ客戶端 ,
idx=28; //ICMP數(shù)據(jù)報(bào)的前20字節(jié)是IP頭部 , 接著的8字節(jié)是ICMP頭部 ,
iret=sendto(sock[1][1],&msgsend[idx],ileft,0,(struct sockaddr *)&sin[1][3],addrlen); //發(fā)送到QQ客戶端我們創(chuàng)建了兩個(gè)線程在兩個(gè)方向(udp-->icmp,icmp-->udp)上接收并傳送數(shù)據(jù) , 如果某個(gè)線程出錯(cuò) , 就重新創(chuàng)建該線程 ,
而未出錯(cuò)的線程則保持不變 ,
hthreads[0]=CreateThread(NULL,0,u2i,(LPVOID)0,NULL,&hthreadid[0]); //創(chuàng)建udp接收數(shù)據(jù) , icmp發(fā)送數(shù)據(jù)的線程0
hthreads[1]=CreateThread(NULL,0,i2u,(LPVOID)1,NULL,&hthreadid[1]); //創(chuàng)建icmp接收數(shù)據(jù) , udp發(fā)送數(shù)據(jù)的線程1while(1)
{
dwret=WaitForMultipleObjects(2,hthreads,false,INFINITE); //等待某個(gè)線程的結(jié)束
if(dwret==WAIT_FAILED) //等待出錯(cuò)
{
cout<<"WaitForMultipleObjects Error: "<return -1;
}
log=dwret-WAIT_OBJECT_0;
if(log==0) //線程0結(jié)束
{
CloseHandle(hthreads[0]); //關(guān)閉線程handle
closesocket(sock[0][1]); //關(guān)閉套接字
hthreads[0]=CreateThread(NULL,0,u2i,(LPVOID)0,NULL,&hthreadid[0]); //重新創(chuàng)建線程0
}
else if(log==1) //線程1結(jié)束
{
CloseHandle(hthreads[1]);
closesocket(sock[1][0]);
hthreads[1]=CreateThread(NULL,0,i2u,(LPVOID)1,NULL,&hthreadid[1]);
}以上就是QQicmp(l)的工作原理 , QQicmp(g)運(yùn)行在網(wǎng)關(guān)上 , 雖然模式不同 , 但工作原理是一樣的 , 只是數(shù)據(jù)報(bào)的流動(dòng)方向有點(diǎn)差異 。

推薦閱讀