siddhesh (siddhesh) wrote,

Finding connections to a specific port with SystemTap

Earlier in the week I was asked by someone if I know a way to monitor applications trying to connect to the telnet port. The obvious answer was netstat/lsof, but the problem was that this application would be up for merely seconds and he did not know when/where it started up. All he had was his telnetd log telling him about the connections. So I decided to go the SystemTap way and came up with this:

/* snoop.stp */
function sockaddr_to_port:long(sck:long)
        short ret = 0;
        struct sockaddr *sock = (struct sockaddr *) (long) THIS->sck;

        memcpy(&ret, sock->sa_data+1, 1);
        memcpy(((char *)&ret)+1, sock->sa_data, 1);

        THIS->__retvalue = ret;

global testport = 0

probe begin(0) {
        if (testport == 0) {
                printf("Usage staprun snoop.ko testport=<portnum>\n");

probe syscall.connect {
        port = sockaddr_to_port($uservaddr)

        if (port == testport) {
                printf ("%d: %s trying to connect to port %d\n", gettimeofday_s(), execname(), testport);
                printf ("\tPID: %d\n", pid());
                printf ("\tUID: %d\n", uid());
                printf ("\tEUID: %d\n", euid());
                printf ("\tParent: %s\n", pexecname());
                printf ("\tPPID: %d\n", ppid());

So this really is a very simple tap on the connect syscall to be able to intercept all connect requests on the system. The sockaddr_to_port is a little more interesting. It takes the first two bytes of sockaddr->sa_data and swaps them to get them to the correct byte order to return as the port number. The reason for the swap is that network byte ordering is essentially big endian (The most significant byte first) while x86 computers are little endian. So the port number 23, at byte level would be seen on your computer as:


while in network byte order it is seen as:


Once we have the port number, the rest is easy pickings with SystemTap giving us easy functions to collect the executable name, pid, parent process name, etc. As for the date, one may easily convert it to human readable form using:

date -d @<my date in seconds>

Now that we have all the pieces in place, we can build the above script into a kernel module using:

stap -vvvg -r `uname -r` snoop.stp -m snoop

The output of this is the kernel module named snoop.ko. The -g signifies the "Guru mode". We need it since our function sockaddr_to_port is embedded C and we need to tell stap that we really know what we're doing. I like putting in a lot of v's in the first place so that I get build errors right away. This is essentially building a kernel module. The -r and -m are for kernel version number and module name respectively. Once built, you can deploy the module using:

staprun snoop.ko testport=23

This loads the module into the kernel and waits to print messages (whenever the program decides to connect to telnet) to standard output. If you look into the output of lsmod, you will find that snoop is a loaded module.

Packages you will need to implement all of this:

  • systemtap
  • systemtap-runtime
  • kernel-debuginfo
  • kernel-devel
  • kernel-debuginfo-common

If you're using the PAE kernel then you need the kernel-PAE-debuginfo and kernel-PAE-devel instead of kernel-debuginfo and kernel-devel. If you're only looking to deploy a binary systemtap module, you will only need systemtap-runtime. Yes, I can run a module built on one system, on another system provided they have the same kernel version and architecture. But be careful of what you run, always inspect the source to make sure you're not running anything malicious.

Tags: endianness, systemtap

  • Moving on

    I have finally moved my website content over to dreamhost. The Net4 account has been utter nonsense, with its idiotic control panel and silly…

  • Preparing for FUDCon -- Fedora Activity Day

    September has been a very busy month for me with Siddhi going to UK for her studies, Mom moving in with us and my role change at work. In all of…

  • My first program on my Samsung Galaxy S

    No, it is not a java program, it is in assembly, which was possible because I recently flashed Cyanogenmod on my phone. Here it is: .text .global…

  • Post a new comment


    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened