Connect-Back Shellcode

connect-back_shellcode.html

Port-binding shellcode is easily foiled by firewalls. Most firewalls will block incoming connections, except for certain ports with known services. This limits the user's exposure and will prevent port-binding shellcode from receiving a connection. Software firewalls are now so common that port-bind shellcode has little chance of actually working in the wild.

However, firewalls typically do not filter outbound connections, since that would hinder usability. From inside the firewall, a user should be able to access any web page or make any other outbound connections. This means that if the shellcode initiates the outbound connection, most firewalls will allow it.

Instead of waiting for a connection from an attacker, connect-back shellcode initiates a TCP connection back to the attacker's IP address. Opening a TCP connection only requires a call to socket() and a call to connect(). This is very similar to the bind-port shellcode, since the socket call is exactly the same and the connect() call takes the same type of arguments as bind(). The following connect-back shellcode was made from the bind-port shellcode with a few modifications (shown in bold).

In the shellcode above, the connection IP address is set to 192.168.42.72, which should be the IP address of the attacking machine. This address is stored in the in_addr structure as 0x482aa8c0, which is the hexadecimal representation of 72, 42, 168, and 192. This is made clear when each number is displayed in hexadecimal:

Since these values are stored in network byte order but the x86 architecture is in little-endian order, the stored DWORD seems to be reversed. This means the DWORD for 192.168.42.72 is 0x482aa8c0. This also applies for the two-byte WORD used for the destination port. When the port number 31337 is printed in hexadecimal using gdb, the byte order is shown in little-endian order. This means the displayed bytes must be reversed, so WORD for 31337 is 0x697a.

The netcat program can also be used to listen for incoming connections with the -l command-line option. This is used in the output below to listen on port 31337 for the connect-back shellcode. The ifconfig command ensures the IP address of eth0 is 192.168.42.72 so the shellcode can connect back to it.

Now, let's try to exploit the tinyweb server program using the connectback shellcode. From working with this program before, we know that the request buffer is 500 bytes long and is located at 0xbffff5c0 in stack memory. We also know that the return address is found within 40 bytes of the end of the buffer.

Since the offset from the beginning of the buffer to the return address is 540 bytes, a total of 544 bytes must be written to overwrite the four-byte return address. The return address overwrite also needs to be properly aligned, since the return address uses multiple bytes. To ensure proper alignment, the sumof the NOP sled and shellcode bytes must be divisible by four. In addition, the shellcode itself must stay within the first 500 bytes of the overwrite. These are the bounds of the response buffer, and the memory afterward corresponds to other values on the stack that might be written to before we change the program's control flow. Staying within these bounds avoids the risk of random overwrites to the shellcode, which inevitably lead to crashes. Repeating the return address 16 times will generate 64 bytes, which can be put at the end of the 544-byte exploit buffer and keeps the shellcode safely within the bounds of the buffer. The remaining bytes at the beginning of the exploit buffer will be the NOP sled. The calculations above show that a 402-byte NOP sled will properly align the 78-byte shellcode and place it safely within the bounds of the buffer. Repeating the desired return address 12 times spaces the final 4 bytes of the exploit buffer perfectly to overwrite the saved return address on the stack. Overwriting the return address with 0xbffff688 should return execution right to the middle of the NOP sled, while avoiding bytes near the beginning of the buffer, which might get mangled. These calculated values will be used in the following exploit, but first the connect-back shell needs some place to connect back to. In the output below, netcat is used to listen for incoming connections on port 31337.

Back in the original terminal, the shellcode has connected back to the netcat process listening on port 31337. This provides root shell access remotely.

The network configuration for this example is slightly confusing because the attack is directed at 127.0.0.1 and the shellcode connects back to 192.168.42.72. Both of these IP addresses route to the same place, but 192.168.42.72 is easier to use in shellcode than 127.0.0.1. Since the loopback address contains two null bytes, the address must be built on the stack with multiple instructions. One way to do this is to write the two null bytes to the stack using a zeroed register. The file loopback_shell.s is a modified version of connectback_shell.s that uses the loopback address of 127.0.0.1. The differences are shown in the following output.

After pushing the value 0x01BBBB7f to the stack, the ESP register will point to the beginning of this DWORD. By writing a two-byte WORD of null bytes at ESP+1, the middle two bytes will be overwritten to form the correct return address.

This additional instruction increases the size of the shellcode by a few bytes, which means the NOP sled also needs to be adjusted for the exploit buffer. These calculations are shown in the output below, and they result in a 397-byte NOP sled. This exploit using the loopback shellcode assumes that the tinyweb program is running and that a netcat process is listening for incoming connections on port 31337.