Sep 192014
 

Had a situation at $WORK where network connections were just hanging there, open, with no activity. So I needed to send something, whatever, on the open connection, just to see how it behaves.

TL;DR: attach to the process using the debugger, gdb(1), then call send(2) on the network socket

In very simple terms, when a program wants to talk to another program over the network, it will create what is called a network socket(2) on the local computer. The local kernel then “connects” that socket to the remote computer, where another socket is open. In Unix a network socket is (like) a file. It can be written to or read from. So sending something over a network connection is just like writing something to a file.

When a program wants to write to a file, it asks the kernel to open the file first. That’s done by calling open(2) for regular files or socket(2) for sockets. The kernel returns a file descriptor that the program then uses to tell the kernel to write(2) or read(2) stuff from/to the file. The file descriptor is a number, int type.

Since that network socket is treated like a file, it will show up in the output of lsof(8) (on Linux) or fstat(1) (on BSD). Normally socket is owned by the process that created it, so it can’t be used by something else. In order to write to it, we need the respective process to do it, so we attach a debugger to the process.

When a debugger attaches to a process it will use the ptrace(2) system call and put the process “on pause”, if you will. Which is very handy for a number of reasons, one being that it gives humans enough time to type things on the keyboard.

Here’s an example of how that works on FreeBSD:

First, let’s open a “server” using netcat:

This will tell nc to start listening on port 12345

Connect a client to that “server”:

Just to double check what is going on, start a tcpdump on that port:

Type something in either netcat and you should see it echoed in the other one and in the tcpdump session. The -X on tcpdump shows the contents of the packet, so whatever is typed in netcat should show up in tcpdump, since it’s a clear text connection.

We’re set. So far we’re simulating a real connection. Let’s see about injecting something. We’ll inject a string in the client netcat session. So first, we need the socket descriptor.

That’s the output of both fstat and lsof. Last line is what we are looking for. FD is the file descriptor column. In our case, it’s 3. 0, 1 and 2 are stdin, stdout and stderr, respectively. So the next descriptor is going to be 3. It so happens that this is our socket, because netcat doesn’t do much else, a real process will probably have a different number.

So now we have the process number and the file descriptor, let’s attach the debugger and send(2) a message:

That’s it. Message sent, it should show up in the “server” netcat as well as tcpdump. It will not show up in the client, of course. The key line is line number 25, where a function in the program is called. send(2) is a standard libc function, pretty much guaranteed to be present in any program. send(2) is used for writing to sockets, write(2) for writing to files, but since a socket is a file write(2) would work just as good in this case. The arguments are the file descriptor (3), the string (look ma! no hands!) and the length of the string.

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

(required)

(required)