icmp
我用VC++写了一个利用ICMP进行通信的程序,初始化一切都正常,
可一到recvfrom时就返回-1,但如果在这之前发送一个sendto地话,
后边这个recvfrom就能接收到一个包,为什么。
顺便告诉我一下哪里有icmp木马的代码?
谢谢!
问题点数:100、回复次数:8Top
1 楼changmangke(环顾四方)回复于 2003-01-08 16:17:54 得分 20
你必须用sendto发送一个ICMP请求,才能得到回应Top
2 楼ruike(瑞克)回复于 2003-01-08 21:46:08 得分 0
gzTop
3 楼wxzfox(乐乐)回复于 2003-01-09 09:38:44 得分 20
ICMP就是Internet控制报文协议,它是便于不同主机之间传递简短消息的一种机制.大多数ICMP消息都牵涉到主机间通信时发生的一些错误;而其他ICMP消息用于对主机进行查询.
报文分为 查询报文 和 差错报文.区别是:查询报文需要应答,而差错报文只是个错误发生通知,不需要接收方应答.
如果你SendTo发送一个ICMP查询报文,才能得到相应的ICMP应答.
如果你的网络出现问题,也会收到ICMP差错报文,你的机器也不用回复这个差错报文.Top
4 楼Shinky(好好)回复于 2003-01-09 14:40:46 得分 0
那为什么有的书上说,对接收到的ICMP报文要检查它的ID号?(也就是用自己的进程ID号添充的那个区域),因为它说有可能收到不是和自己刚才发送有关的包,(但我从来没有收到过),这是为什么?
还有,不是有一种木马是用ICMP协议来通信地吗?
怎么才能实现呢?
谢谢楼上几位大虾!Top
5 楼changmangke(环顾四方)回复于 2003-01-09 14:52:46 得分 60
ICMP 的接收与其它SOCKET编程有一个非常明显的不同:接收到的数据可能并不是由这个SOCKET发送出去的。也许是另一个线程发送的ICMP回送请求而导致的响应,而这个线程却也收到了这个响应数据报。如何区分一个ICMP应答是不是自己的呢?ICMP报头中的ID号能够帮助我们做到这一点。还记得在生成ICMP回送请求的时候,我们在ICMP的ID数据域填入了当前线程的ID号,目标机在返回应答信息的时候不会修改这个域,所以我们可以将接收到的数据报的ID与当前线程的ID号相比较,如果不同就丢弃它。
ICMP木马的大致原理如下:
ICMP报文是由系统内核或进程直接处理而不是通过端口,这就给木马一个摆脱端口的绝好机会,木马将自己伪装成一个Ping的进程,系统就会将ICMP_ECHOREPLY(Ping的回包)的监听、处理权交给木马进程,一旦事先约定好的ICMP_ECHOREPLY包出现(可以判断包大小、ICMP_SEQ等特征),木马就会接受、分析并从报文中解码出命令和数据。
你可以看一看这个简单的例子:
http://www.yesky.com/20010525/181452.shtml
Top
6 楼Shinky(好好)回复于 2003-01-11 19:13:39 得分 0
#include "Stdafx.h"
#include "Socklib.h"
#include "../Packet.h"
#include "../Command.h"
#include "Header.h"
//////////////////// [Globals] ///////////////////
SOCKET g_socket;
struct sockaddr_in g_recv_addr;
int g_addr_len;
char g_recv_buffer[MAX_BUFF];
char * g_recv_pdata;
int g_recv_len;
int g_icmp_hdr_len = sizeof(_IcmpHeader);
int g_ip_hdr_len = sizeof(_IpHeader);
//////////////////////////////////////////////////
SOCKET icmp_socket(int sto, int rto, int ttl);
unsigned short icmp_check_sum(unsigned short FAR *lpBuf, int Len);
int BeginServer();
void Handle();
//////////////////////////////////////////////////
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
int ret = 0;
ret = init_sock_lib();
if (ret == 0) {
MessageBox(NULL, "init_sock_lib()", "Error", MB_OK);
return 0;
}
////////////////////////////////
g_addr_len = sizeof(sockaddr_in);
g_recv_len = 0;
memset(&g_recv_addr, 0, g_addr_len);
memset(g_recv_buffer, 0, MAX_BUFF);
////////////////////////////////
g_socket = icmp_socket(1000, 1000, 30);
if (g_socket == INVALID_SOCKET) {
MessageBox(NULL, "icmp_socket()", "Error", MB_OK);
dis_sock_lib();
return 0;
}
BeginServer();
return 0;
}
SOCKET icmp_socket(int sto, int rto, int ttl)
{
int ret = 0;
SOCKET sck = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sck == INVALID_SOCKET)
return INVALID_SOCKET;
ret = setsockopt(sck, SOL_SOCKET, SO_SNDTIMEO, (char*)&sto, sizeof(sto));
if (ret < 0) {
closesocket(sck);
sck = INVALID_SOCKET;
}
ret = setsockopt(sck, SOL_SOCKET, SO_RCVTIMEO, (char*)&rto, sizeof(rto));
if (ret < 0) {
closesocket(sck);
sck = INVALID_SOCKET;
}
ret = setsockopt (sck, IPPROTO_IP, IP_TTL, (LPSTR)&ttl, sizeof(int));
if (ret < 0) {
closesocket(sck);
sck = INVALID_SOCKET;
}
return sck;
}
unsigned short icmp_check_sum(unsigned short FAR *lpBuf, int Len)
{
register long ChkSum = 0L;
while (Len > 1) {
ChkSum += *(lpBuf++);
Len -= sizeof (USHORT);
}
if (Len)
ChkSum += *(UCHAR *)lpBuf;
ChkSum = (ChkSum & 0xffff) + (ChkSum>>16);
ChkSum += (ChkSum >> 16);
#pragma warning(disable : 4244)
return (~ChkSum);
#pragma warning(default : 4244)
}
int BeginServer()
{
if (g_socket == INVALID_SOCKET)
return -1;
/* fd_set set;
FD_ZERO(&set);
FD_SET(g_socket, &set);
*/
int recv_len = 0;
for (;;) {
g_recv_addr.sin_addr.S_un.S_addr = INADDR_ANY;
g_recv_addr.sin_family = AF_INET;
g_recv_addr.sin_port = 0;
recv_len = recvfrom(g_socket, g_recv_buffer, MAX_BUFF, 0, (sockaddr *)&g_recv_addr, &g_addr_len);
if (recv_len <= 0)
continue;
g_recv_len = recv_len;
g_recv_pdata = g_recv_buffer + g_icmp_hdr_len;
Handle();
}
}
void Handle()
{
IpHeader * iph = (IpHeader *)g_recv_buffer;
IcmpHeader * icmph = (IcmpHeader *)g_recv_buffer + g_ip_hdr_len;
g_recv_pdata = (char *)icmph + g_icmp_hdr_len;
if (g_recv_len < sizeof(_IpHeader) + ICMP_MIN)
return;
if (icmph->IcmpType != ICMP_ECHOREPLY)
return;
MessageBox(NULL, (LPCTSTR)g_recv_pdata, "V O I D", MB_OK);
} Top
7 楼Shinky(好好)回复于 2003-01-11 19:20:26 得分 0
以上是一个我写的利用ICMP来接收数据的一小段程序,
可是为什么接收recvfrom()总是返回-1,但我要是在这之前向一主机发送一个ICMP包时就可以接收到一个回复;
另外,再调试到recvfrom()时,我运行了一个Ping xxx.xxx.xxx.xxx -t的DOS命令,我的程序为什么收不到这个PING 的回复呢?
这个问题我想了很久,不知道为什么,希望大虾们能够告诉我一下是怎么回事?
非常非常感谢!!!!!!Top
8 楼Shinky(好好)回复于 2003-01-14 11:03:26 得分 0
aTop




