使用Pin监控,解析connect()系统调用获取服务器端IP

使用Pin监控,解析connect()系统调用获取服务器端IPconnect()函数:connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

connect()函数通常用于客户端建立tcp连接。 参数列表: sockfd:指定数据发送的套接字。 serv_addr:指定数据发送的目的地,包括套接字sockfd想要连接的主机地址和端口号。 addrlen:指定serv_addr结构体的长度。 返回值: 成功则返回0,失败返回-1,错误原因存于errno中。

既然serv_addr中存放了服务器端的IP地址,所以我们要从客户端获取服务器端的IP地址,只要得到connect()函数的addr参数就可以了。

struct sockaddr *addr:struct sockaddr {sa_data[14];/* 14 bytes of protocol address */};

sa_family是地址家族,一般都是“AF_xxx”的形式。好像通常大多用的是都是AF_INET。 sa_data是14字节协议地址。 此数据结构用做bind、connect、recvfrom、sendto等函数的参数,指明地址信息。

但一般编程中并不直接针对此数据结构操作,,而是使用另一个与sockaddr等价的数据结构

struct sockaddr_in {sin_port;sin_zero[8];/* Same size as struct sockaddr */};struct in_addr {unsigned long s_addr;};

sockaddr_in和sockaddr是并列的结构,指向sockaddr_in的结构体的指针也可以指向sockadd的结构体,并代替它。也就是说,我们可以使用sockaddr_in建立所需要的信息,在最后用进行类型转换就可以了。

我们要的IP地址就在s_addr中。

在Pin中获取IP地址

查看unistd_64.h得到connect()的系统调用号为42,所以使用Pin监控Client端的运行,并筛选出42号系统调用。结果如下:

0x7ff9a794561e: 42(0x4, 0x7fff1466d780, 0x10, 0x0, 0x0, 0x4)returns: 0x0

这个就是我们要得到的connect()系统调用的相关信息。显然第二个参数是serv_addr结构体的内存地址,所以我们现在要做的是从这块内存中提取出IP地址,即serv_addr的第三个成员变量值sin_addr。sin_addr也是一个in_addr类型的结构体,所以最终要拿到的数据还是unsigned long s_addr。

获得s_addr有两种方法:

直接用内存操作 这是我最开始想到的方法,主要思路是既然有了内存地址,那么就可以根据结构体的定义来计算成员变量的偏移量,然后直接将内存数据取出。

这种方法不但麻烦,而且有一个致命的问题,那就是数据对齐。许多计算机系统对基本数据类型合法地址做出了一些限制,要求某种类型对象的地址必须是某个K(2、4或8)值的倍数。不一样的操作系统(比如Linux和Windows)的强制对齐规则是不一样的,对于结构体类型我们直接计算变量的偏移很有可能会得到错误的值。关于数据对齐的知识在《深入理解计算机系统》一书中有详细的介绍。

使用指针访问 既然知道了结构体的内存地址,那我可以在程序中声明一个sockaddr_in结构体变量,然后将内存地址进行强制类型转换赋给该变量,这样就可以通过直接访问该结构体变量来访问成员变量,而不需要进行直接的内存操作了。 最后要使用inet_ntoa()函数将in_addr类型的IP地址转换为点分十进制,并打印出来。 代码如下:

if(num == 42){fprintf(trace,”0x%lx: %ld(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)”,(unsigned long)ip,(long)num,(unsigned long)arg0,(unsigned long)arg1,(unsigned long)arg2,(unsigned long)arg3,(unsigned long)arg4,(unsigned long)arg5);struct sockaddr_in addr;addr = *((sockaddr_in *)arg1);fprintf(trace,”\nIP:%s\n”,inet_ntoa(addr.sin_addr));}}

结果如下:

0x7fca80ee061e: 42(0x4, 0x7fffeb46b2c0, 0x10, 0x0, 0x0, 0x4)

在这个阳光明媚的三月,我从我单薄的青春里打马而过,

使用Pin监控,解析connect()系统调用获取服务器端IP

相关文章:

你感兴趣的文章:

标签云: