Own And You Shall Be Owned

While working on Poison Ivy’s communication, one of my students approached me and asked me if the fact that an infected computer can connect to the C&C server means that the compromised host can break into the server. Well folks, it appears that it’s possible. We will now present a fully working exploit for all Windows platforms (i.e., bypassing DEP and ASLR), allowing a computer infected by Poison Ivy (or any other computer, for that matter) to assume control of PI’s C&C server.

As we already know, Poison Ivy’s initial communication sequence goes as follows:

  1. The client contacts the server and sends 256 bytes of data (challenge).
  2. The server encrypts the data and sends it back (response).
  3. The server sends an encrypted command (machine code) to the client (preceded by a cleartext length DWORD).
  4. The client sends the infected computer’s encrypted details to the server.

Steps 3 and 4 are somewhat interchangeable. In any case, we’ll be attacking step 4. This sort of attack has already been investigated by Andrzej Dereszowski, but some details were omitted, and the exploit was very limited in nature (and not disclosed).

First, let’s see what bytes the client sends to the server in step 4:

The data given here provides the server with the following information:

When analyzing the PI server (it’s packed with ExeStealth, BTW), we see that it first reads 0×20 bytes of client data (i.e., the header), parses that header, and acts accordingly. Some interesting values in the header:

  • The 1st DWORD is either 4 or not. A value of 4 involves taking a different branch that doesn’t interest us.
  • The 3rd DWORD indicates the number of additional bytes to read from the socket after reading the header (i.e., the data).
  • The 4th DWORD is the number of relevant data bytes in the data that’s going to be read from the socket.
  • The 5th DWORD is the real size of the relevant data. If this is bigger than the 4th DWORD, the read data should be decompressed using RtlDecompressBuffer.
  • The 6th DWORD is the size of the buffer to allocate for the (uncompressed) relevant data. This has nothing to do with the buffer for reading the data from the socket, which is simply a local array variable, residing on the stack.

If you think this construction is weird, you’re absolutely right. Either the author did it so he can have a backdoor via an exploit, or I’m giving him way too much credit. Either way, this header screams “exploit me!”, and in this case, I don’t mind being a pleaser. :)

First thing’s first. If we want to transfer our own header, we need to encrypt it. We use what we already know about Poison Ivy’s crypto system, and utilize PI’s own PILib.dll to our advantage:

And the actual code (note that Camellia is a block cipher):

PI’s C&C server creates a thread for each new connection. It’s that thread’s function that has the vulnerability. Here’s the buffer that we want to overflow:

Now, to the exploit. We want to indicate that there’s a lot of data to be sent. However, we don’t want to send that much data, because if we break the connection we can quickly get to the overwritten return address. We must keep in mind, though, that we can’t break the connection before all of the data we wanted to send was actually received by the other side. This way, we get both the overflow, and the quick exit. We also note that PI was built so that threads can terminate without affecting the server, which is an attribute we’re going to use to exit cleanly from our shellcode.

Ok, so we can overwrite the return address, but where should we point it to? The thread’s stack is not executable, and we don’t even know where it is. However, the PI server’s executable doesn’t support ASLR, so we know exactly where it is (as a side note, all of its sections are marked RWX). We’re going to construct a ROP chain that calls VirtualProtect and makes the stack executable, so we can run our code. The problem is we don’t have much of a stack to work with when the function returns, having that this is a function directly called by CreateThread. This is all the stack space we have:

So, using the helpful assistance of mona.py, we manually create a ROP chain to take us back 0×8000 bytes to where the stack was, so we can have a bigger ROP chain there that calls VirtualProtect on 0×4000 stack bytes (which is more than enough for any shellcode you might want to run). One last thing to remember is that EIP and ESP are the same when the shellcode starts to run, so it’s important not to write things on the stack that will destroy the shellcode. We deal with it by subtracting 0×40 from ESP upon entering our shellcode, so we have some space for local variables.

See the inline comments in the code below for specific details on the ROP chains and the shellcode:

The exploit was tested on Windows XP Service Pack 3, but should work without any problem on all Windows versions, as it bypasses DEP (using ROP chains and VirtualProtect) and ASLR (using the fact that the executable doesn’t support rebasing, and utilizing only relative addresses).

Exploiter’s view:

PI’s C&C server’s view:

Although the exploit presented here uses Poison Ivy’s own PILib.dll to encrypt the communication to the server, and thus the correct encryption key/password is needed, we can perform the exploitation quite reliably even without encrypting the data. For the exploit to be reliable, the server needs to see two things after decrypting the header:

  1. The first DWORD should not be 4.
  2. The third DWORD should be higher than the actual size of the data we send (minus the header).

For the first point, out of about 4 billion numbers, only one poses a problem. In fact, we can just send the number 4, and assume that it’s not going to get decrypted back to 4 (i.e., the encryption wouldn’t have done anything to it). As for the second point, we observe that we send 0×8095 bytes, meaning that it suffices for the 3rd DWORD in the header to have one of its higher bytes not equal to 0. Following the same logic we used before, we can simply send zeros as the higher bytes.

It’s important to note that the exploit data following our header never gets decrypted, so we don’t have to worry about PI ruining our values if we don’t encrypt the data.

In light of this analysis, a Metasploit module without encryption is being prepared.

 

Be Sociable, Share!

5 thoughts on “Own And You Shall Be Owned

  1. This gotta be the second coolest remote exploit I have seen in my entire life. Pwnd a PI C&C this is just to funny :D

Leave a Reply

Your email address will not be published. Required fields are marked *

*

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