Debunking the prank to rebuild the connection between the TCP connection and the process

It's time to expose the trick.

Please read the following first:
https://blog.csdn.net/dog250/article/details/108113329

According to the trick described in the article, let's hack the attribution of the tcp connection of the two processes. First, give the scene before the 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

Then, after implementing the hack, the tcp connection to which the process belongs is exchanged:

[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

If system operation and maintenance or other administrators encounter such a situation, which process should they target to debug?

Note ⚠️, we have to abandon the post-event presupposition. In fact, they can't realize that the connection has been exchanged. They may not realize that something is wrong after a long time after pulling a lot of people together for a meeting.

If I were there, this kind of thing would not happen. As a craftsman, I prefer to face the essence directly instead of using tools to detour. In my opinion, to find the connection between the tcp connection and the process through procfs is roundabout.

Why not just point it?

Consider the following diagram:
Insert picture description here
If the piece through a non-removable clues to associate tcp_sock and socket, without having to detour it not?

OK, the following code describes how to do it:

#!/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();
}

Come on, let's run the above script to try to find out the truth about the hacked system:

[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

Use this result to compare the situation after being hacked:

[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

Haha, the truth is revealed!

What is a craftsman? Do not rely on large-scale tools, do not rely on professional knowledge, it is also the one who repairs pots in small towns without traces. Of course, leather shoes can also be made.


The leather shoes in Wenzhou, Zhejiang are wet, so they won’t get fat in the rain.

Guess you like

Origin blog.csdn.net/dog250/article/details/108134813