This is a walkthrough of the Ghost challenges on BreachLab. Passwords for levels are not saved automatically. If you do not save them yourself, you will need to start over. Passwords also occasionally change. It is recommended to take notes on how to solve each challenge. As levels get more challenging, detailed notes are useful to return to where you left off, reference for later problems, or help others after you’ve completed the challenge.
Level 0: First Contact | Getting your bearings on a box you have never seen before. Every single engagement — offensive or defensive — starts here. Use the password for ghost0 that you captured on the previous level, then: ssh ghost0@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login. When we use ls, we can see a README and a workspace folder. Then cd to the workspace folder. Using ls shows us archive folder and notes.txt. Reading notes.txt shows the following:
OPERATIONAL NOTES — KAEL
========================
Target: internal network segment 10.4.x.x
Method: passive recon, no active scanning
Status: ongoing
Credentials filed separately in archive/.
Do not store passwords in plaintext notes.
Once we navigate to workspace/archive and read a file named credentials, we get the password for the Level 1.
Password: W3lc0m3T0Gh0st
Level 1: Name Game | Shell quoting is the foundation for shell injection, path traversal, and every real attack that abuses how operators pass arguments to other programs. Use the password that you captured on the previous level, then: ssh ghost1@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login. When we use ls -al, we see the following:
ghost1@breachlab:~$ ls -al
total 100
-rw-r----- 1 ghost1 ghost1 13 May 19 12:05 -
-rw-r----- 1 ghost1 ghost1 13 May 19 12:05 --help
drwx------ 1 ghost1 ghost1 4096 Jun 13 06:58 .
drwxr-xr-x 1 root root 4096 May 19 12:05 ..
-rw-r----- 1 ghost1 ghost1 13 May 19 12:05 ...
-rw-r--r-- 1 ghost1 ghost1 220 Jan 6 2022 .bash_logout
-rw-r--r-- 1 ghost1 ghost1 3771 Jan 6 2022 .bashrc
drwx------ 2 ghost1 ghost1 4096 Jun 13 06:58 .cache
drwxrwxr-x 3 ghost1 ghost1 4096 May 24 13:08 .local
-rw-r--r-- 1 ghost1 ghost1 807 Jan 6 2022 .profile
drwx------ 2 ghost1 ghost1 4096 May 19 14:59 .ssh
drwxrwxr-x 3 ghost1 ghost1 4096 Jun 9 14:41 .terminfo
drwxrwxr-x 4 ghost1 ghost1 4096 Jun 10 06:41 LazyOwn
-rw-r----- 1 ghost1 ghost1 228 Apr 17 09:44 MANIFEST
-rw-r----- 1 ghost1 ghost1 15 May 19 12:05 'file name'
Simply use cat 'file name' to read the password. It is important to use single or double quotes when reading the file because it has a space in its name.
Password: D4shIsN0tAFl4g
Level 2: In The Shadows | Forensics and malware persistence analysis. Attackers hide their tools in exactly this way. Defenders hunt exactly this way. Use the password that you captured on the previous level, then: ssh ghost2@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
ghost2@breachlab:~$ ls -a
. .. .bash_logout .bashrc .cache .local .memo .profile .ssh .terminfo investigation
ghost2@breachlab:~$ cd investigation
ghost2@breachlab:~/investigation$ ls -la
total 40
drwxr-x--- 1 ghost2 ghost2 4096 Jun 22 13:41 .
drwx------ 1 ghost2 ghost2 4096 Jun 26 04:04 ..
drwxr-x--- 1 ghost2 ghost2 4096 Jun 22 13:41 .leads
-rw-r----- 1 ghost2 ghost2 201 Jun 22 13:41 report.txt
-rw-r----- 1 ghost2 ghost2 205 Jun 22 13:41 summary.txt
ghost2@breachlab:~/investigation$ cd .leads
ghost2@breachlab:~/investigation/.leads$ ls -la
total 40
drwxr-x--- 1 ghost2 ghost2 4096 Jun 22 13:41 .
drwxr-x--- 1 ghost2 ghost2 4096 Jun 22 13:41 ..
-rw-r----- 1 ghost2 ghost2 13 Jun 22 13:41 .source_alpha
-rw-r----- 1 ghost2 ghost2 13 Jun 22 13:41 .source_beta
-rw-r----- 1 ghost2 ghost2 15 Jun 22 13:41 .source_omega
ghost2@breachlab:~/investigation/.leads$ cat .*
cat: .: Is a directory
cat: ..: Is a directory
7a4e91c63d2f
bb50d8e4a11c
H1dd3nInSh4dow
Once we are logged in, we use ls -la to view hidden folders and files. Running cat .* attempts to read all items in the current directory, which reveals the password to the next level.
Password: H1dd3nInSh4dow
Level 3: Access Denied | Linux permissions are the entire foundation of privilege escalation. This is level zero of real privesc. Use the password that you captured on the previous level, then: ssh ghost3@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login. We then list out all the contents of the current directory.
ghost3@breachlab:~$ ls -al
total 68
drwx------ 1 ghost3 ghost3 4096 Aug 23 02:47 .
drwxr-xr-x 1 root root 4096 Jun 22 13:41 ..
-rw-r--r-- 1 ghost3 ghost3 220 Jan 6 2022 .bash_logout
-rw-r--r-- 1 ghost3 ghost3 3771 Jan 6 2022 .bashrc
drwx------ 2 ghost3 ghost3 4096 Aug 9 13:36 .cache
drwxrwxr-x 3 ghost3 ghost3 4096 Jul 4 20:41 .local
-rw-r--r-- 1 ghost3 ghost3 807 Jan 6 2022 .profile
drwx------ 2 ghost3 ghost3 4096 Jun 24 02:16 .ssh
drwxrwxr-x 3 ghost3 ghost3 4096 Aug 10 17:47 .terminfo
drwxrwxr-x 3 ghost3 ghost3 4096 Aug 16 20:35 .warp
-rw-r----- 1 ghost3 ghost3 308 Apr 17 09:44 map.txt
Notice that there is a file named map.txt. Reading it shows the following:
ghost3@breachlab:~$ cat map.txt
KAEL'S STORAGE LAYOUT
=====================
Recovered from workstation. Partially redacted.
/var/intel/public/ — world readable
/var/intel/ops/ — restricted
/var/intel/archive/ — root only
Access follows the group scheme. The kernel will
tell you what you are, if you ask it.
— KAEL
With the clues provided, we attempt to list out all the contents of each of the directories:
ghost3@breachlab:~$ ls -al /var/intel/public/
total 12
drwxr-xr-x 1 root root 4096 Jun 22 13:41 .
drwxr-xr-x 1 root root 4096 Jun 22 13:41 ..
-rw-r--r-- 1 root root 161 Jun 22 13:41 report_q1.txt
ghost3@breachlab:~$ ls -al /var/intel/ops/
total 16
drwxr-x--- 1 root analysts 4096 Jun 22 13:41 .
drwxr-xr-x 1 root root 4096 Jun 22 13:41 ..
----r----- 1 root analysts 19 Jun 22 13:41 access_codes.dat
----r----- 1 root analysts 103 Jun 22 13:41 operative_list.txt
ghost3@breachlab:~$ ls -al /var/intel/archive/
ls: cannot open directory '/var/intel/archive/': Permission denied
Notice the permissions of the files access_codes.dat and operative_list.txt in /var/intel/ops/. To cross check our current user permissions, we run id which returns uid=5003(ghost3) gid=5003(ghost3) groups=5003(ghost3),5010(analysts),5024(ghost-players). Since we do have the permissions to read those files, we can directly read /var/intel/ops/access_codes.dat which gives us the password for the next level.
Password: P3rm1ss10ns_M4tt3r
Level 4: Signal In The Noise | Threat hunting. This is the core loop of every SOC analyst on the planet — find the needle in the log haystack. Use the password that you captured on the previous level, then: ssh ghost4@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login. The current directory contains a folder named vault, which we then change directory to. Listing out the contents reveals a huge number of files.
ghost4@breachlab:~$ ls
vault
ghost4@breachlab:~$ cd vault
ghost4@breachlab:~/vault$ ls
louco record_0042 record_0084 record_0126 record_0168 record_0210 record_0252 record_0294 record_0336 record_0378 record_0420 record_0462
record_0001 record_0043 record_0085 record_0127 record_0169 record_0211 record_0253 record_0295 record_0337 record_0379 record_0421 record_0463
record_0002 record_0044 record_0086 record_0128 record_0170 record_0212 record_0254 record_0296 record_0338 record_0380 record_0422 record_0464
record_0003 record_0045 record_0087 record_0129 record_0171 record_0213 record_0255 record_0297 record_0339 record_0381 record_0423 record_0465
record_0004 record_0046 record_0088 record_0130 record_0172 record_0214 record_0256 record_0298 record_0340 record_0382 record_0424 record_0466
record_0005 record_0047 record_0089 record_0131 record_0173 record_0215 record_0257 record_0299 record_0341 record_0383 record_0425 record_0467
record_0006 record_0048 record_0090 record_0132 record_0174 record_0216 record_0258 record_0300 record_0342 record_0384 record_0426 record_0468
record_0007 record_0049 record_0091 record_0133 record_0175 record_0217 record_0259 record_0301 record_0343 record_0385 record_0427 record_0469
record_0008 record_0050 record_0092 record_0134 record_0176 record_0218 record_0260 record_0302 record_0344 record_0386 record_0428 record_0470
record_0009 record_0051 record_0093 record_0135 record_0177 record_0219 record_0261 record_0303 record_0345 record_0387 record_0429 record_0471
record_0010 record_0052 record_0094 record_0136 record_0178 record_0220 record_0262 record_0304 record_0346 record_0388 record_0430 record_0472
record_0011 record_0053 record_0095 record_0137 record_0179 record_0221 record_0263 record_0305 record_0347 record_0389 record_0431 record_0473
record_0012 record_0054 record_0096 record_0138 record_0180 record_0222 record_0264 record_0306 record_0348 record_0390 record_0432 record_0474
record_0013 record_0055 record_0097 record_0139 record_0181 record_0223 record_0265 record_0307 record_0349 record_0391 record_0433 record_0475
record_0014 record_0056 record_0098 record_0140 record_0182 record_0224 record_0266 record_0308 record_0350 record_0392 record_0434 record_0476
record_0015 record_0057 record_0099 record_0141 record_0183 record_0225 record_0267 record_0309 record_0351 record_0393 record_0435 record_0477
record_0016 record_0058 record_0100 record_0142 record_0184 record_0226 record_0268 record_0310 record_0352 record_0394 record_0436 record_0478
record_0017 record_0059 record_0101 record_0143 record_0185 record_0227 record_0269 record_0311 record_0353 record_0395 record_0437 record_0479
record_0018 record_0060 record_0102 record_0144 record_0186 record_0228 record_0270 record_0312 record_0354 record_0396 record_0438 record_0480
record_0019 record_0061 record_0103 record_0145 record_0187 record_0229 record_0271 record_0313 record_0355 record_0397 record_0439 record_0481
record_0020 record_0062 record_0104 record_0146 record_0188 record_0230 record_0272 record_0314 record_0356 record_0398 record_0440 record_0482
record_0021 record_0063 record_0105 record_0147 record_0189 record_0231 record_0273 record_0315 record_0357 record_0399 record_0441 record_0483
record_0022 record_0064 record_0106 record_0148 record_0190 record_0232 record_0274 record_0316 record_0358 record_0400 record_0442 record_0484
record_0023 record_0065 record_0107 record_0149 record_0191 record_0233 record_0275 record_0317 record_0359 record_0401 record_0443 record_0485
record_0024 record_0066 record_0108 record_0150 record_0192 record_0234 record_0276 record_0318 record_0360 record_0402 record_0444 record_0486
record_0025 record_0067 record_0109 record_0151 record_0193 record_0235 record_0277 record_0319 record_0361 record_0403 record_0445 record_0487
record_0026 record_0068 record_0110 record_0152 record_0194 record_0236 record_0278 record_0320 record_0362 record_0404 record_0446 record_0488
record_0027 record_0069 record_0111 record_0153 record_0195 record_0237 record_0279 record_0321 record_0363 record_0405 record_0447 record_0489
record_0028 record_0070 record_0112 record_0154 record_0196 record_0238 record_0280 record_0322 record_0364 record_0406 record_0448 record_0490
record_0029 record_0071 record_0113 record_0155 record_0197 record_0239 record_0281 record_0323 record_0365 record_0407 record_0449 record_0491
record_0030 record_0072 record_0114 record_0156 record_0198 record_0240 record_0282 record_0324 record_0366 record_0408 record_0450 record_0492
record_0031 record_0073 record_0115 record_0157 record_0199 record_0241 record_0283 record_0325 record_0367 record_0409 record_0451 record_0493
record_0032 record_0074 record_0116 record_0158 record_0200 record_0242 record_0284 record_0326 record_0368 record_0410 record_0452 record_0494
record_0033 record_0075 record_0117 record_0159 record_0201 record_0243 record_0285 record_0327 record_0369 record_0411 record_0453 record_0495
record_0034 record_0076 record_0118 record_0160 record_0202 record_0244 record_0286 record_0328 record_0370 record_0412 record_0454 record_0496
record_0035 record_0077 record_0119 record_0161 record_0203 record_0245 record_0287 record_0329 record_0371 record_0413 record_0455 record_0497
record_0036 record_0078 record_0120 record_0162 record_0204 record_0246 record_0288 record_0330 record_0372 record_0414 record_0456 record_0498
record_0037 record_0079 record_0121 record_0163 record_0205 record_0247 record_0289 record_0331 record_0373 record_0415 record_0457 record_0499
record_0038 record_0080 record_0122 record_0164 record_0206 record_0248 record_0290 record_0332 record_0374 record_0416 record_0458 record_0500
record_0039 record_0081 record_0123 record_0165 record_0207 record_0249 record_0291 record_0333 record_0375 record_0417 record_0459
record_0040 record_0082 record_0124 record_0166 record_0208 record_0250 record_0292 record_0334 record_0376 record_0418 record_0460
record_0041 record_0083 record_0125 record_0167 record_0209 record_0251 record_0293 record_0335 record_0377 record_0419 record_0461
ghost4@breachlab:~/vault$ cat record_0001
[2026-03-28 02:01:01] STATUS: 41b952e38b4298e07ec671735d818a9d
Reading few of the files shows us that there is a certain pattern to their contents. So we run cat record_* | grep -v "STATUS" to search through all files in the directory. The -v flag is "invert-match" which tells grep to show us everything that does not contain the word STATUS. Reading the output reveals to us the password we need.
ghost4@breachlab:~/vault$ cat record_* | grep -v "STATUS"
[2026-03-28 02:47:13] password=OXJukpigxrek5Aij
[2026-03-28 02:47:13] password=lGkIOi0VAxYi9mWK
[CLASSIFIED] CREDENTIAL: Gr3p_F1nds_Truth
[2026-03-28 02:47:13] password=IToIl8UcTIkRC6cM
[2026-03-28 02:47:13] password=6nRicmB1WPUtRdIB
[2026-03-28 02:47:13] password=wH7v87lbQx9HTiqq
Password: Gr3p_F1nds_Truth
Level 5: The Listener | Network reconnaissance and banner grabbing. The opening move in every pentest. Use the password that you captured on the previous level, then: ssh ghost5@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login. Listing out available files shows a README file. Reading it gives us a clue on what is happening.
ghost5@breachlab:~$ ls
README
ghost5@breachlab:~$ cat README
ANALYST WORKSTATION — KAEL
Last active: 2026-03-28 02:47 UTC
Status: Abandoned
I left a service running on this box. Used to be my back channel —
two ports, one tells you how to talk, the other answers if you say
the right word.
I locked down `ss` and `netstat` weeks ago. Don't bother. The kernel
won't help you here. You'll have to knock on doors yourself.
`nc` and `curl` are still on the box. That's all you need.
Find the listener. Read what it tells you. Then answer it correctly.
— KAEL
So we run seq 1 65535 | xargs -P 250 -I {} bash -c '(echo > /dev/tcp/127.0.0.1/{}) 2>/dev/null && echo "Open port: {}"' to scan the localhost for open ports. seq 1 65535 generates a sequence of numbers from 1 to 65535, printing each number on a new line. xargs -P 250 -I {} reads the numbers coming through the pipe and passes them as arguments to a command. -P 250 controls concurrency by running 250 parallel processes at any given moment. -I {} creates a placeholder named {}. Everywhere {} appears in the following command, xargs will replace it with the current port numnber. /dev/tcp/127.0.0.1/{} means Bash attempts to open a TCP connection to 127.0.0.1 on the port replacing {}. echo > ... tries to send an empty line into that TCP socket. 2>/dev/null discards all error messages (like Connection refused or Connection timed out). Closed ports fail silently. && is a logical AND operator. The command after && runs only if the TCP connection attempt succeeded (exit status 0). echo "Open port: {}" prints the result to your terminal exclusively when a port successfully accepts the connection.
ghost5@breachlab:~$ seq 1 65535 | xargs -P 250 -I {} bash -c '(echo > /dev/tcp/127.0.0.1/{}) 2>/dev/null && echo "Open port: {}"'
Open port: 22
Open port: 30003
Open port: 30101
Open port: 30100
Open port: 31339
Open port: 34890
Open port: 37818
Open port: 41310
Open port: 41311
Open port: 41337
Open port: 49213
Now that we have the output, we loop through each of the ports to attempt getting the flag needed.
ghost5@breachlab:~$ for p in 30003 30100 30101 31339 34890 37818 41310 41311 41337 49213; do echo "=== Testing Port $p ==="; nc -w 1 127.0.0.1 $p; done
=== Testing Port 30003 ===
=== Testing Port 30100 ===
GHOST PROTOCOL — CHANNEL A
─────────────────────────────────────
This channel is informational only.
Authentication token: GHOST
Secure channel: port 30101
Send the token to receive your credential.
=== Testing Port 30101 ===
AUTHENTICATE: === Testing Port 31339 ===
Ghost Graduation Gatekeeper
===========================
Submit three shards in one line, pipe-separated, no spaces:
SHARD1:<val>|SHARD2:<val>|SHARD3:<val>
> === Testing Port 34890 ===
=== Testing Port 37818 ===
=== Testing Port 41310 ===
ghost credential-broker v1.2
usage: RETRIEVE <current-token>
=== Testing Port 41311 ===
=== Testing Port 41337 ===
[ CLASSIFIED — GHOST TRACK BONUS ]
───────────────────────────────────────────
You found the signal.
The official brief listed 22 levels.
You kept looking past the brief.
───────────────────────────────────────────
OPERATIVE KAEL — STATUS: ACTIVE
Last known location: PHANTOM network.
Final message before going dark:
"The machines you trust every day
are not what they appear to be.
Docker. Kubernetes. GitHub Actions.
The real breach starts in the pipeline."
───────────────────────────────────────────
NEXT TRACK: PHANTOM
Status: LIVE — 30 levels of Linux privesc.
See breachlab.org for the brief.
───────────────────────────────────────────
breachlab.org · Ghost Track · Bonus Level
=== Testing Port 49213 ===
With the latest information we have, we use nc localhost [PORT_NUMBER] to follow the hints and retrieve the flag.
ghost5@breachlab:~$ nc localhost 30100
GHOST PROTOCOL — CHANNEL A
─────────────────────────────────────
This channel is informational only.
Authentication token: GHOST
Secure channel: port 30101
Send the token to receive your credential.
nc localhost 30101
ghost5@breachlab:~$ nc localhost 30101
AUTHENTICATE: GHOST
Credential: P0rts_N3v3r_L13
Password: P0rts_N3v3r_L13
Level 6: Ghost In The Machine | Credential extraction. Environment variables are how secrets leak into process lists, crash logs, and CI pipelines every single day. Use the password that you captured on the previous level, then: ssh ghost6@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login. We run env to list all current environment variables.
ghost6@breachlab:~$ env
SHELL=/bin/bash
METRICS_ENABLED=false
REGION=eu-central-1
LOG_LEVEL=minimal
HISTSIZE=1000
API_DIGEST=M252X0wzNGtzXzN2M3J5dGgxbmc=
TRACE_SALT=bW9uaXRvcmluZ19rZXlfZGVsdGE3
PWD=/home/ghost6
LOGNAME=ghost6
MAX_RETRIES=3
NODE_ID=ghost-analyst-07
RUNTIME_TOKEN=c3lzdGVtX3Rva2VuX2dhbW1hX3Yz
MOTD_SHOWN=pam
HOME=/home/ghost6
LANG=C.UTF-8
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
SSH_CONNECTION=172.19.0.2 55676 172.19.0.3 22
DEPLOY_TAG=v2.1.4
CACHE_TTL=300
LESSCLOSE=/usr/bin/lesspipe %s %s
TERM=xterm-256color
HEALTH_INTERVAL=30
LESSOPEN=| /usr/bin/lesspipe %s
USER=ghost6
SHLVL=1
DB_POOL_SIZE=10
AVAILABILITY_ZONE=eu-central-1a
APP_VERSION=2.14.7
INSTANCE_TYPE=t3.micro
SSH_CLIENT=172.19.0.2 55676 22
SERVICE_PORT=8443
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
HISTFILESIZE=2000
RUNTIME_ENV=production
CACHE_SEED=bm90X2FfcmVhbF9jcmVkZW50aWFs
SSH_TTY=/dev/pts/1
BUILD_ID=a3f7b2c1
SESSION_HASH=d4e5f6a7b8
_=/usr/bin/env
ghost6@breachlab:~$ echo "M252X0wzNGtzXzN2M3J5dGgxbmc=" | base64 -d
3nv_L34ks_3v3ryth1ng
Notice that API_DIGEST looks like a secret. Decoding it reveals the password required.
Password: 3nv_L34ks_3v3ryth1ng
Level 7: Lost In Translation | Malware analysis. Real-world payloads are almost always encoded two or three times deep to evade simple detection. Use the password that you captured on the previous level, then: ssh ghost7@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login. List out the files in the current directory.
ghost7@breachlab:~$ ls
transmission.dat
ghost7@breachlab:~$ cat transmission.dat
00000000: 5244 4e6a 4d47 517a 587a 4279 5830 5178 RDNjMGQzXzByX0Qx
00000010: 4d77 3d3d 0a Mw==.
ghost7@breachlab:~$ xxd -r transmission.dat
RDNjMGQzXzByX0QxMw==
ghost7@breachlab:~$ base64 -d RDNjMGQzXzByX0QxMw==
base64: 'RDNjMGQzXzByX0QxMw==': No such file or directory
ghost7@breachlab:~$ echo "RDNjMGQzXzByX0QxMw==" | base64 -d
D3c0d3_0r_D13
When we read transmission.dat, we see a hex dump. Using xxd -r to convert the hex text back into actual binary data now results in a Base64 encoded string. So we pipe the output into base64 -d to decode it. A one-liner that works faster is this:
ghost7@breachlab:~$ cat transmission.dat | xxd -r | base64 -d
D3c0d3_0r_D13
Password: D3c0d3_0r_D13
Level 8: Something's Running | Fileless malware analysis and live incident response. This is what an IR engineer does at 3am when a box is already compromised and disk forensics is too slow. Use the password that you captured on the previous level, then: ssh ghost8@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login. Then run ps aux | grep ghost8 to list processes related to the current user.
ghost8@breachlab:~$ ps aux | grep ghost8
root 23 0.0 0.0 7040 2464 ? S Aug09 0:00 runuser -u ghost8 -p -- python3 /usr/local/bin/level8-daemon.py
root 25 0.0 0.0 7040 2464 ? S Aug09 0:00 runuser -u ghost8 -- python3 /usr/local/bin/level8-daemon.py
ghost8 39 0.0 0.0 13544 2360 ? S Aug09 0:00 python3 /usr/local/bin/level8-daemon.py
ghost8 40 0.0 0.0 13544 2316 ? S Aug09 0:00 python3 /usr/local/bin/level8-daemon.py
root 2349631 0.0 0.0 16976 10920 ? Ss 06:02 0:00 sshd: ghost8 [priv]
ghost8 2349654 0.0 0.0 17280 8280 ? S 06:02 0:00 sshd: ghost8@pts/1
ghost8 2349655 0.0 0.0 5048 4124 pts/1 Ss 06:02 0:00 -bash
ghost8 2350282 0.0 0.0 7484 3316 pts/1 R+ 06:03 0:00 ps aux
ghost8 2350283 0.0 0.0 4024 2268 pts/1 S+ 06:03 0:00 grep --color=auto ghost8
ghost8 2630946 0.0 0.0 13568 2336 ? S Aug10 0:00 python3 /usr/local/bin/level8-daemon.py
Every process has its own folder in /proc named after its PID. Inside that folder, the environ file contains the environment variables that specific process is using. Specific to the current context, we narrow our focus to processes running Python. Read each of them until we get the password we need.
ghost8@breachlab:~$ strings /proc/40/environ
HOSTNAME=breachlab
PWD=/
HOME=/root
SHLVL=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DEBIAN_FRONTEND=noninteractive
_=/usr/bin/env
ANALYST_KEY=Pr0c_T3lls_4ll
Password: Pr0c_T3lls_4ll
Level 9: Core Dump Use the password that you captured on the previous level, then: ssh ghost9@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 10: Binary Strings Use the password that you captured on the previous level, then: ssh ghost10@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 11: Wrapped Three Deep Use the password that you captured on the previous level, then: ssh ghost11@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 12: Key Not Password Use the password that you captured on the previous level, then: ssh ghost12@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 13: Port 3000 Use the password that you captured on the previous level, then: ssh ghost13@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 14: TLS, Not Plaintext Use the password that you captured on the previous level, then: ssh ghost14@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 15: Port Range Use the password that you captured on the previous level, then: ssh ghost15@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 16: Diff Use the password that you captured on the previous level, then: ssh ghost16@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 17: No Shell For You Use the password that you captured on the previous level, then: ssh ghost17@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 18: Wrong User Use the password that you captured on the previous level, then: ssh ghost18@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 19: Your First Script Use the password that you captured on the previous level, then: ssh ghost19@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 20: Cron Discovery Use the password that you captured on the previous level, then: ssh ghost20@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
Level 21: Git Archaeology Use the password that you captured on the previous level, then: ssh ghost21@204.168.229.209 -p 2222.
Steps: SSH to the given IP address and login.
.
Password:
See you in the next Hacking Lab.
@aaronamran
June 2026