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地址在哪里,如何获得,这个。。。。。再想想

时间: 2024-10-13 12:14:46

Pin截获socket系统调用初步分析的相关文章

socket系统调用深度分析

1.系统调用过程 1.1用户态和内核态以及系统调用机制 1.进程的地址空间 linux进程有4GB地址空间,如图所示: 3G-4G大部分是共享的,是内核态的地址空间.这里存放整个内核的代码和所有的内核模块以及内核所维护的数据. 2.特权级别 对于任何操作系统来说,创建一个进程是核心功能.创建进程要做很多工作,会消耗很多物理资源.比如分配物理内存,父子进程拷贝信息,拷贝设置页目录页表等等,这些工作得由特定的进程去做,所以就有了特权级别的概念.最关键的工作必须交给特权级最高的进程去执行,这样可以做到

Socket与系统调用深度分析

Socket与系统调用深度分析 可以想象的是,当应用程序调用socket()接口,请求操作系统提供服务时,必然会系统调用,内核根据发起系统调用时传递的系统调用号,判断要执行的程序,若为socket对应的编号,则执行socket对应的中断服务程序.服务程序内部,又根据你要请求的不同服务,来执行不同服务对应的处理程序.当处理结束,执行返回,从中断服务程序到发起中断的int 0x80,再到用户态我们执行的用户程序,层层返回,socket()也就执行完毕了. 本次,我们关心三个问题: 1.应用程序如何如

Socket与系统调用深度分析 ——X86 64环境下Linux5.0以上的内核中

1.Socket与系统调用——概述 Socket API编程接口之上可以编写基于不同网络协议的应用程序: Socket接口在用户态通过系统调用机制进入内核: 内核中将系统调用作为一个特殊的中断来处理,以socket相关系统调用为例进行分析: socket相关系统调用的内核处理函数内部通过“多态机制”对不同的网络协议进行的封装方法: 下面会将Socket API编程接口.系统调用机制及内核中系统调用相关源代码. socket相关系统调用的内核处理函数结合起来分析,并在X86 64环境下Linux5

【Socket系统调用】Socket与系统调用深度分析

Socket与系统调用深度分析 系统调用 在一开始,应用程序是可以直接控制硬件的,这就需要程序员有很高的编程能力,否则一旦程序出了问题,会将整个系统Crash. 在现在的操作系统中,用户程序运行在用户态,而要进行诸如Socket.磁盘I/O这样的一些操作,这需要切换到内核态,再进行进行相应的操作,而这一过程则是系统调用system call.有了操作系统分离了内核和用户态,应用程序就无法直接进行硬件资源的访问,需要经过系统调用来进行. 每次的系统调用,都会从用户态转换到内核态,运行完任务后,回到

U-BOOT-2016.07移植 (第一篇) 初步分析

U-BOOT-2016.07移植 (第一篇) 初步分析 目录 U-BOOT-201607移植 第一篇 初步分析 目录 编译和移植环境 更新交叉编译工具 1 下载arm-linux-gcc 443 2 安装arm-linux-gcc 443 安装环境Ubuntu 910 下载u-boot-201607并解压 分析顶层Makefile 1 找出目标依赖关系 2 总结 初次编译u-boot 1 配置 2 编译 分析u-boot启动流程 1 分析startS 2 分析crt0S 3 总结 1. 编译和移

linux中mmap系统调用原理分析与实现

参考文章:http://blog.csdn.net/shaoguangleo/article/details/5822110 linux中mmap系统调用原理分析与实现 1.mmap系统调用(功能)      void* mmap ( void * addr , size_t len , int prot , int flags ,int fd , off_t offset )      内存映射函数mmap, 负责把文件内容映射到进程的虚拟内存空间, 通过对这段内存的读取和修改,来实现对文件的

Cocos2d-x 3.1 Director ActionManger Scheduler初步分析

Director游戏主循环显示Node DisplayLinkDirector继承Director override了以下方法 virtual void mainLoop() override; virtual void setAnimationInterval(double value) override; virtual void startAnimation() override; virtual void stopAnimation() override; mainLoop()是游戏主循

win10系统调用架构分析

1.  操作系统模型 大多数操作系统中,都会把应用程序和内核代码分离运行在不同的模式下.内核模式访问系统数据和硬件,应用程序运行在没有特权的模式下(用户模式),只能使用有限的API,且不能直接访问硬件.当用户模式调用系统服务时,CPU执行一个特殊的指令以切换到内核模式(Ring0),当系统服务调用完成时,操作系统切换回用户模式(Ring3). Windows与大多数UNIX系统类似,驱动程序代码共享内核模式的内存空间,意味着任何系统组件或驱动程序都可能访问其他系统组件的数据.但是,Windows

mysql--error150错误原因初步分析

1, 两个字段的类型或者大小不严格匹配,例如,如果一个是INT(10), 那么外键也必须设置成INT(10), 而不是 INT(11) 也不能是 TINYINT. 你得使用 SHOW 命令来查看字段的大小,因为一些查询浏览器有时候把 int(10) 和int(11) 都显示为integer.另外,你还必须确定两个字段是否一个为 SIGNED,而另一个又是UNSIGNED, 这两字段必须严格地一致匹配. 2, 你试图引用的其中一个外键没有建立起索引,或者不是一个primary key , 如果其中