揭穿恶作剧重建TCP连接和进程之间的关联_tcp 连接和进程

是时候将把戏揭穿了。

请先阅读下文:
https://blog.csdn.net/dog250/article/details/108113329

依照文章中所描述的把戏,我们hack一下两个进程的tcp连接的归属,首先给出hack之前的情景:

[root@localhost ~]# netstat -ntp
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 192.168.56.110:22       192.168.56.1:55287      ESTABLISHED 1344/sshd: root@pts
tcp        0      0 192.168.56.110:22       192.168.56.1:55589      ESTABLISHED 4791/sshd: root@pts

然后,在实施hack之后,进程所属的tcp连接被交换了:

[root@localhost ~]# netstat -ntp
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 192.168.56.110:22       192.168.56.1:55287      ESTABLISHED 4791/sshd: root@pts
tcp        0      0 192.168.56.110:22       192.168.56.1:55589      ESTABLISHED 1344/sshd: root@pts

如果系统运维或者其它管理员遇到这样的情况,他们到底要瞄准哪个进程来debug呢?

注意⚠️,我们要抛弃事后的预设,事实上,他们根本无法意识到连接被交换了,等到拉了一大堆人一起开完会后很久,他们或许才能意识到事情哪里有点不对劲。

如果有我在,这种事情就不会发生,作为手艺人,我更喜欢直接面对本质,而不是使用工具迂回,在我看来,通过procfs来查找tcp连接和进程之间的关联,就是迂回。

何不直接点儿呢?

来看下面的图:
在这里插入图片描述
如果通过那条 不可拆除的线索 来关联tcp_sock和socket,岂不是无需迂回?

OK,下面的代码描述了如何做:

#!/usr/bin/stap -g
// tcpstat(.stp)

%{
#include <net/tcp.h>
#include <linux/fdtable.h>

struct result {
    char laddr[16];
    char raddr[16];
    unsigned short    lport;
    unsigned short    rport;
    unsigned long ino;
    int pid;
    char comm[32];
};

static inline void ip2str(char *to, unsigned int from)
{
    int size = snprintf(to, 16, "%pI4", &from);
    to[size] = '\0';
}

void traverse(struct sock *sk, unsigned long ino, struct result *ret)
{
    struct task_struct *tsk;
    int i;

    for_each_process(tsk) {
        struct file *file;
        for (i = 0; i < tsk->files->fdt->max_fds; i++) {
            file = tsk->files->fdt->fd[i];
            if (file == NULL) {
                continue;
            }
            if (file->f_inode->i_ino == ino) {
                char laddr[16], raddr[16];

                ip2str(laddr, inet_sk(sk)->inet_rcv_saddr);
                ip2str(raddr, inet_sk(sk)->inet_daddr);

                memcpy(&ret->laddr[0], laddr, 16);
                memcpy(&ret->raddr[0], raddr, 16);
                ret->lport = sk->sk_num;
                ret->rport = htons(sk->sk_dport);
                ret->ino = ino;
                ret->pid = tsk->pid;
                memcpy(&ret->comm[0], tsk->comm, 32);
            }
        }
    }
}
%}

function dump_tcp_info()
%{
    struct task_struct *tsk;
    struct inet_hashinfo *hashinfo = &tcp_hashinfo;
    struct hlist_nulls_node *node;
    struct socket_alloc *sa;
    struct sock *sk;
    struct result ret;
    int i, ino;

    for (i = 0; i < INET_LHTABLE_SIZE; i++) {
        struct inet_listen_hashbucket *ilb;

        ilb = &hashinfo->listening_hash[i];
        sk_nulls_for_each(sk, node, &ilb->head) {
            unsigned long ino;

            sa = (struct socket_alloc *)sk->sk_socket;
            ino = sa->vfs_inode.i_ino;

            traverse(sk, ino, &ret);
            STAP_PRINTF("LISTEN %s:%d  inode:%d/[%d] %s\n",
                        ret.laddr,
                        ret.lport,
                        ret.ino,
                        ret.pid,
                        ret.comm);
        }
    }

    for (i = 0; i <= hashinfo->ehash_mask; i++) {
        struct inet_ehash_bucket *head = &hashinfo->ehash[i];

        if (hlist_nulls_empty(&head->chain)) {
            continue;
        }

        sk_nulls_for_each(sk, node, &head->chain) {
            unsigned long ino;

            sa = (struct socket_alloc *)sk->sk_socket;
            ino = sa->vfs_inode.i_ino;

            traverse(sk, ino, &ret);
            STAP_PRINTF("ESTABLISHED %s:%d  %s:%d inode:%d/[%d] %s\n",
                        ret.laddr,
                        ret.lport,
                        ret.raddr,
                        ret.rport,
                        ret.ino,
                        ret.pid,
                        ret.comm);
        }
    }
%}

probe begin
{
    dump_tcp_info();
    exit();
}

来来来,我们运行上面的脚本来试一下能不能把被hack的系统真相找出来:

[root@localhost test]# ./tcpstat
LISTEN 0.0.0.0:22  inode:22852/[1001] sshd
LISTEN 0.0.0.0:22  inode:22850/[1001] sshd
ESTABLISHED 192.168.56.110:22  192.168.56.1:55287 inode:25510/[1344] sshd
ESTABLISHED 192.168.56.110:22  192.168.56.1:55589 inode:28747/[4791] sshd

用这个结果来对比一下被hack后的情形:

[root@localhost ~]# netstat -ntp
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 192.168.56.110:22       192.168.56.1:55287      ESTABLISHED 4791/sshd: root@pts
tcp        0      0 192.168.56.110:22       192.168.56.1:55589      ESTABLISHED 1344/sshd: root@pts

哈哈,真相大白!

何为手艺人?不依赖大型工具,不依赖专业知识,小镇上修锅换底而无痕迹者是也。当然,皮鞋也能做。


浙江温州皮鞋湿,下雨进水不会胖。

原文链接: https://blog.csdn.net/dog250/article/details/108134813

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    揭穿恶作剧重建TCP连接和进程之间的关联_tcp 连接和进程

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/405847

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月26日 上午9:28
下一篇 2023年4月26日 上午9:28

相关推荐