码迷,mamicode.com
首页 > 其他好文 > 详细

Pin截获socket系统调用初步分析

时间:2015-03-20 12:55:54      阅读:192      评论:0      收藏:0      [点我收藏+]

标签:pin   socket   系统调用   

Pin截获socket系统调用初步分析

根据为知笔记中上传的Pin tool for tracing system calls,修改代码过滤出socket相关的系统调用,并进行初步的分析。主要有2点:
- 过滤socket相关的系统调用
- 分析得到的系统调用参数

过滤socket相关的系统调用

socket编程中与访问网络相关的主要关注socket()accept()。然后在PinTool中过滤出这两个系统调用,对他们的参数进行初步的分析。下面先看一下这两个函数:


int socket(int domain,int type,int protocol);

socket函数说明

socket()用来建立一个新的socket,也就是向系统注册,通知系统建立一通信端口。

参数domain 指定使用何种的地址类型,完整的定义在/usr/include/bits/socket.h 内,底下是常见的协议:
PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL UNIX 进程通信协议
PF_INET/AF_INET Ipv4网络协议
PF_INET6/AF_INET6 Ipv6 网络协议
PF_IPX/AF_IPX IPX-Novell协议
PF_NETLINK/AF_NETLINK 核心用户接口装置
PF_X25/AF_X25 ITU-T X.25/ISO-8208 协议
PF_AX25/AF_AX25 业余无线AX.25协议
PF_ATMPVC/AF_ATMPVC 存取原始ATM PVCs
PF_APPLETALK/AF_APPLETALK appletalk(DDP)协议
PF_PACKET/AF_PACKET 初级封包接口

参数type有下列几种数值:
SOCK_STREAM 提供双向连续且可信赖的数据流,即TCP。支持OOB 机制,在所有数据传送前必须使用connect()来建立连线状态。
SOCK_DGRAM 使用不连续不可信赖的数据包连接
SOCK_SEQPACKET 提供连续可信赖的数据包连接
SOCK_RAW 提供原始网络协议存取
SOCK_RDM 提供可信赖的数据包连接
SOCK_PACKET 提供和网络驱动程序直接通信。

参数protocol用来指定socket所使用的传输协议编号,通常此参考不用管它,设为0即可。

返回值成功则返回socket处理代码,失败返回-1。


int accept(int s,struct sockaddr * addr,int * addrlen);
struct sockaddr
{
    unsigned short int sa_family;
    char sa_data[14];
};

accept函数说明

accept 系统调用是等待传入连接的阻塞调用。处理连接请求后,accept 将返回新的套接字描述符。将此新的套接字连接到客户端,使另外一个套接字 s 保持 LISTEN 状态,以接受进一步连接。
参数s是套接字描述符。参数addr所指的结构会被系统填入远程主机的地址数据,参数addrlen为scokaddr的结构长度。
此外sockaddr结构会因使用不同的socket domain而有不同结构定义,例如使用AF_INET domain,其socketaddr结构定义便为

struct socketaddr_in
{
    unsigned short int sin_family;
    uint16_t sin_port;
    struct in_addr sin_addr;
    unsigned char sin_zero[8];
};
struct in_addr
{
    uint32_t s_addr;
};

sin_family 即为sa_family
sin_port 为使用的port编号
sin_addr.s_addr 为IP 地址
sin_zero 未使用。


也就是说判断程序的网络访问情况我们主要考虑:
socket(int domain,int type,int protocol)函数中的domain参数,是否为PF_INET/AF_INET
accept(int s,struct sockaddr * addr,int * addrlen)函数中addr参数内的IP地址


另一方面SystemCallTrace.cpp中SysBefore()函数用来打印系统调用号和参数。通过查看unistd_64.h中定义的各个系统调用的系统调用号,其中(socket,41),(accept,43),(listen,50),系统调用号41到50之间都是与socket相关的,所以我就在代码中做一个简单的过滤。代码如下:

if((num >= 41) && (num <= 50))
    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);

修改makefile.rules,添加SystemCallTrace工具:

TEST_TOOL_ROOTS := MyPinTool SystemCallTrace

生成SystemCallTrace.so

root@kali:~/pin-2.14-71313-gcc.4.4.7-linux/source/tools/MyPinTool# make

从网上下载一个简单的TCP小程序将其放到根目录下,首先生成可执行文件tcp_server和tcp_client,开始做实验,代码见附件。

root@kali:~/pin-2.14-71313-gcc.4.4.7-linux# bash pin.sh -t ~/pin-2.14-71313-gcc.4.4.7-linux/source/tools/MyPinTool/obj-intel64/SystemCallTrace.so -- ~/tcp_server

现在tcp_server已经运行起来了,运行tcp_client向server发送几个字符,结束实验。打开strace.out,部分结果如下:

0x7f7099132a95: 41(0x2, 0x1, 0x0, 0x0, 0x7f70993dc300, 0x7f70ac435310)returns: 0x4
0x7f709913258e: 43(0x4, 0x0, 0x0, 0x0, 0xffffffff, 0x0)returns: 0x5

分析得到的系统调用参数

strace.out中

0x7f7099132a95: 41(0x2, 0x1, 0x0, 0x0, 0x7f70993dc300, 0x7f70ac435310)returns: 0x4

系统调用号: 41,即系统调用socket()
参数1: 0x2,在/usr/include/x86_64-linux-gnu/bits/socket.h中定义了socket使用的协议的值,0x2即PF_INET/AF_INET
参数2: 0x1,在/usr/include/x86_64-linux-gnu/bits/socket.h定义了socket类型,SOCK_STREAM = 1
参数3: 0x0
返回值: 0x4,返回socket句柄为4
下面我们看一下tcp_server.c的源代码:

 //初始化Socket  
 if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){  
    printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);  
    exit(0);  
 }  

可以看出关于socket()函数的参数,分析结果与源程序是完全一致的。
我们在这一步获得了参数AF_INET


0x7f709913258e: 43(0x4, 0x0, 0x0, 0x0, 0xffffffff, 0x0)returns: 0x5

系统调用号: 43,即系统调用accept()
参数1: 0x0,即socket句柄为4,也就是socket()的返回值。
参数2: 0x0,这是一个(struct sockaddr*)类型的地址
参数3: 0x0,是参数2结构体的长度
返回值: 0x5,返回已连接socket句柄为5
下面我们看一下tcp_server.c的源代码:

 //阻塞直到有客户端连接,不然多浪费CPU资源。  
 if( (connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL)) == -1){  
     printf("accept socket error: %s(errno: %d)",strerror(errno),errno);  
     continue;  
 }  

可以看出关于accept()函数的参数,分析结果与源程序是也完全一致的。

但是,客户端的IP地址在哪里,如何获得,这个。。。。。再想想

Pin截获socket系统调用初步分析

标签:pin   socket   系统调用   

原文地址:http://blog.csdn.net/hanchaoqi/article/details/44487263

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!