我试图通过将处理程序挂钩到sock_sendmsg()
中定义的内核函数linux/socket.c
来转储特定进程在Linux上发送的所有数据。
我可以通过为probe kernel.function("sock_sendmsg@net/socket.c")
编写一个systemtap探针处理程序来转储使用第二个参数struct msghdr *msg
传递的所有数据块。
以下是net/socket.c
的摘录:
int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
{
struct kiocb iocb;
struct sock_iocb siocb;
int ret;
init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
ret = __sock_sendmsg(&iocb, sock, msg, size);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb);
return ret;
}
我测试了我的systemtap脚本hook_sendmsg.stp
。首先,我在一个终端中运行hook_sendmsg.stp
。然后我打开另一个终端并调用telnet
命令连接到stackoverflow.com
并在终端中输入HEAD / HTTP/1.0<Enter twice>
。我从hook_sendmsg.stp
获得了以下输出:
root@debian:~# stap -g hook_sendmsg.stp
message block [0]; type=3(raw); state=1(unconnected)
14 00 00 00 16 00 01 03 ec 95 f4 52 00 00 00 00 |...........R....|
00 00 00 00 |................|
message block [0]; type=3(raw); state=1(unconnected)
14 00 00 00 16 00 01 03 ec 95 f4 52 00 00 00 00 |...........R....|
00 00 00 00 |................|
message block [0]; type=2(udp); state=1(unconnected)
4d 0d 01 00 00 01 00 00 00 00 00 00 0d 73 74 61 |M............sta|
63 6b 6f 76 65 72 66 6c 6f 77 03 63 6f 6d 00 00 |ckoverflow.com..|
01 00 01 |................|
message block [0]; type=2(udp); state=1(unconnected)
0f 1e 01 00 00 01 00 00 00 00 00 00 0d 73 74 61 |.............sta|
63 6b 6f 76 65 72 66 6c 6f 77 03 63 6f 6d 00 00 |ckoverflow.com..|
1c 00 01 |................|
message block [0]; type=1(tcp); state=3(connected)
48 45 41 44 20 2f 20 48 54 54 50 2f 31 2e 30 0d |HEAD / HTTP/1.0.|
0a |................|
message block [0]; type=1(tcp); state=3(connected)
0d 0a |................|
这表明在sock_sendmsg()
的上下文中,完全telnet
被调用了6次。显然,第3和第4个是对Google的公共DNS服务器8.8.8.8
和8.8.4.4
的DNS查询。第5和第6行是从telnet
发送的两行HTTP请求。但第一和第二要求的是什么?他们是否通过内核调用内部?
提前致谢。
答案 0 :(得分:1)
它们是NETLINK消息,您可以看到是否使用strace监视来自用户空间的telnet命令(检查套接字系列):
sendto(3, "\24\0\0\0\26\0\1\3?\254\364R\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
sendto(3, "\24\0\0\0\26\0\1\3?\254\364R\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
send(3, "\212\355\1\0\0\1\0\0\0\0\0\0\rstackoverflow\3com\0\0"..., 35, MSG_NOSIGNAL) = 35
send(3, "\241\353\1\0\0\1\0\0\0\0\0\0\rstackoverflow\3com\10i"..., 50, MSG_NOSIGNAL) = 50
send(3, "|\341\1\0\0\1\0\0\0\0\0\0\rstackoverflow\3com\0\0"..., 35, MSG_NOSIGNAL) = 35
send(3, "HEAD / HTTP/1.0\r\n", 17, 0) = 17
send(3, "\r\n", 2, 0) = 2
Netlink是用户空间进程用来与内核通信的接口(因此,它们由telnet发送),通常用于路由,防火墙...... pourposes [1]。一些常用的网络C函数(即getsockname)在内部使用这种NETLINK消息。
如果您想进一步研究,您应该将send_message的有效负载转换为netlink标头结构,并检查消息的类型:
struct nlmsghdr {
__u32 nlmsg_len; /* Length of message including header. */
__u16 nlmsg_type; /* Type of message content. */
__u16 nlmsg_flags; /* Additional flags. */
__u32 nlmsg_seq; /* Sequence number. */
__u32 nlmsg_pid; /* Sender port ID. */
};