Hackvent 2024: Day 19
[HV24.19] Santa's Workshop: A Technical Emergency
Santa's magical workshop is more modern than ever this year! In addition to the classic toys and presents, Santa has launched a major project: Old computers are to be repaired, cleaned and recycled for children all over the world. His aim is not only to spread the magic of Christmas, but also to protect the environment.
But just before the big celebration, there is a problem: One of the elves discovers that some of the computers have not been properly prepared. Confidential data from previous owners may have been left on them, and some devices are displaying strange error messages that could indicate hardware problems.
As the elves in the workshop have their hands full, Santa turns to you, his specialist in digital magic. You are given access to a magical virtual machine that simulates one of the affected computers. Your job is to make sure that the computer gets under the Christmas tree safely and on time.
After you start the PC, you can connect to it via SSH with the credentials root:santa on port 2222.
Start the service and get the flag.
Flag format: HV24{}
This challenge was written by darkstar. A web interface to control a VM that works out of the box, I'm happy.
Solution
Initial Analysis
We are granted root access to a virtual machine and are instructed to pay attention to hardware errors. We SSH into the machine and take some time to explore. The VM is a QEMU virtual machine with limited functionality. It is primarily powered by BusyBox.
We notice that the machine has a single disk with one partition:
$ fdisk -l /dev/sda
Found valid GPT with protective MBR; using GPT
Disk /dev/sda: 204800 sectors, 100M
Logical sector size: 512
Disk identifier (GUID): 2f6d5b26-1100-1e41-a58f-4b91958b3a0f
Partition table holds up to 128 entries
First usable sector is 2048, last usable sector is 204766
Number Start (sector) End (sector) Size Name
1 2048 204766 98.9M
After exploring the user directories, we notice an interesting .ack_history
file located at /home/Santa/.ack_history
, which contains a few commands the Santa
user attempted to run. We notice that Santa tried to run ddrescue
, suggesting there are issues with the disk. However, the ddrescue
binary is not present on the machine. We do have access to the dd
command though.
We run the following command to simulate dumping sectors from the /dev/sda
disk:
$ dd if=/dev/sda of=/dev/null bs=512
dd: reading `/dev/sda': Input/output error
We encounter an input/output error. When using dd
, we can also specify a count
and skip
parameter to skip over various sectors. Through trial and error, we discover that the disk errors only occur at the very end of the disk (the last few hundred sectors or so).
$ dd if=/dev/sda of=/tmp/data.img bs=512 count=20480 skip=0
$ dd if=/dev/sda of=/tmp/data.img bs=512 count=20480 skip=20480
...
$ dd if=/dev/sda of=/tmp/data.img bs=512 count=20480 skip=163840
$ dd if=/dev/sda of=/tmp/data.img bs=512 count=20480 skip=184320
dd: reading `/dev/sda': Input/output error
Further testing revealed the disk errors start shortly after the 198320
sector, which corresponds to the 101539840
byte offset. All sectors prior to this seem to be healthy.
Running ddrescue
Based on the fact that the Santa user ran ddrescue
and that we have disk errors, we attempt to run ddrescue
ourselves on the machine. To do this, we need to copy the ddrescue
binaries to the virtual machine. We use the WinSCP
application on Windows to complete the file transfer but scp
from the command line would have also worked well. The ddrescue
binary we used originated from a Ubuntu
machine. The binary had dynamic links to libstdc++.so.6
so we also copied this library over to avoid compiling a statically linked version.
After we have copied the files to the /tmp
directory, we run the commands:
$ cp /tmp/ddrescue /bin
$ chmod +x /bin/ddrescue
$ cp /tmp/libstdc++.so.6 /lib
We can now run ddrescue
, so we run the following command:
$ ddrescue -d -i 101539840 /dev/sda /dev/null /tmp/mapfile
GNU ddrescue 1.27
Press Ctrl-C to interrupt
ipos: 104792 kB, non-trimmed: 262144 B, current rate: 0 B/s
opos: 104792 kB, non-scraped: 0 B, average rate: 0 B/s
non-tried: 983040 B, bad-sector: 0 B, error rate: 0 B/s
rescued: 2072 kB, bad areas: 0, run time: 0s
pct rescued: 62.46%, read errors: 4, remaining time: n/a
time since last successful read: n/a
Copying non-tried blocks... Pass 1 (forwards)
ipos: 102498 kB, non-trimmed: 458752 B, current rate: 0 B/s
opos: 102498 kB, non-scraped: 0 B, average rate: 0 B/s
non-tried: 262144 B, bad-sector: 0 B, error rate: 0 B/s
rescued: 2596 kB, bad areas: 0, run time: 0s
pct rescued: 78.27%, read errors: 7, remaining time: n/a
time since last successful read: n/a
Copying non-tried blocks... Pass 2 (backwards)
ipos: 102957 kB, non-trimmed: 720896 B, current rate: 2596 kB/s
opos: 102957 kB, non-scraped: 0 B, average rate: 2596 kB/s
non-tried: 0 B, bad-sector: 0 B, error rate: 655 kB/s
rescued: 2596 kB, bad areas: 0, run time: 1s
pct rescued: 78.27%, read errors: 11, remaining time: 1s
time since last successful read: 0s
Copying non-tried blocks... Pass 5 (forwards)
ipos: 103117 kB, non-trimmed: 0 B, current rate: 2596 kB/s
opos: 103117 kB, non-scraped: 650752 B, average rate: 2596 kB/s
non-tried: 0 B, bad-sector: 1024 B, error rate: 655 kB/s
rescued: 2665 kB, bad areas: 2, run time: 1s
pct rescued: 80.35%, read errors: 13, remaining time: 1s
time since last successful read: 0s
Trimming failed blocks... (forwards)
ipos: 103117 kB, non-trimmed: 0 B, current rate: 24064 B/s
opos: 103117 kB, non-scraped: 0 B, average rate: 166 kB/s
non-tried: 0 B, bad-sector: 157184 B, error rate: 1536 B/s
rescued: 3160 kB, bad areas: 187, run time: 18s
pct rescued: 95.26%, read errors: 318, remaining time: 0s
time since last successful read: n/a
Scraping failed blocks... (forwards)
Finished
We specify an offset index of 101539840
bytes to speed up the process, knowing from our earlier trial and error that all the disk errors are beyond this point. We redirect the actual output to /dev/null
as otherwise the VM would crash due to low disk space or high CPU/RAM usage. Finally, we specify a location for the mapfile
which is the file of interest to solve this challenge.
After running the command we have a mapfile
which looks like this:
# Mapfile. Created by GNU ddrescue version 1.27
# Command line: ddrescue -d -i 101539840 /dev/sda /tmp/out.img /tmp/mapfile
# Start time: 2024-12-19 14:22:25
# Current time: 2024-12-19 14:22:42
# Finished
# current_pos current_status current_pass
0x06257200 + 1
# pos size status
0x00000000 0x060D6000 ?
0x060D6000 0x000E2400 +
0x061B8400 0x00000200 -
0x061B8600 0x00000600 +
0x061B8C00 0x00000200 -
0x061B8E00 0x00000200 +
0x061B9000 0x00000200 -
0x061B9200 0x00000800 +
0x061B9A00 0x00000200 -
0x061B9C00 0x00000400 +
0x061BA000 0x00000600 -
0x061BA600 0x00000800 +
0x061BAE00 0x00000600 -
0x061BB400 0x00000600 +
0x061BBA00 0x00000600 -
0x061BC000 0x00000A00 +
0x061BCA00 0x00000400 -
0x061BCE00 0x00000A00 +
0x061BD800 0x00000400 -
0x061BDC00 0x00000400 +
0x061BE000 0x00000200 -
0x061BE200 0x00001000 +
0x061BF200 0x00000400 -
0x061BF600 0x00000C00 +
0x061C0200 0x00000200 -
0x061C0400 0x00001E00 +
0x061C2200 0x00000800 -
0x061C2A00 0x00001400 +
0x061C3E00 0x00000200 -
0x061C4000 0x00000C00 +
0x061C4C00 0x00000600 -
0x061C5200 0x00002000 +
0x061C7200 0x00000400 -
0x061C7600 0x00000E00 +
0x061C8400 0x00000200 -
0x061C8600 0x00000600 +
0x061C8C00 0x00000200 -
0x061C8E00 0x00000200 +
0x061C9000 0x00000400 -
0x061C9400 0x00000600 +
0x061C9A00 0x00000200 -
0x061C9C00 0x00000200 +
0x061C9E00 0x00000200 -
0x061CA000 0x00000400 +
0x061CA400 0x00000200 -
0x061CA600 0x00000600 +
0x061CAC00 0x00000200 -
0x061CAE00 0x00000400 +
0x061CB200 0x00000400 -
0x061CB600 0x00000200 +
0x061CB800 0x00000200 -
0x061CBA00 0x00000400 +
0x061CBE00 0x00000200 -
0x061CC000 0x00000A00 +
0x061CCA00 0x00000400 -
0x061CCE00 0x00000A00 +
0x061CD800 0x00000200 -
0x061CDA00 0x00000600 +
0x061CE000 0x00000200 -
0x061CE200 0x00001000 +
0x061CF200 0x00000400 -
0x061CF600 0x00000C00 +
0x061D0200 0x00000200 -
0x061D0400 0x00002400 +
0x061D2800 0x00000200 -
0x061D2A00 0x00001400 +
0x061D3E00 0x00000200 -
0x061D4000 0x00000A00 +
0x061D4A00 0x00000200 -
0x061D4C00 0x00000400 +
0x061D5000 0x00000400 -
0x061D5400 0x00002200 +
0x061D7600 0x00000200 -
0x061D7800 0x00000C00 +
0x061D8400 0x00000200 -
0x061D8600 0x00000600 +
0x061D8C00 0x00000200 -
0x061D8E00 0x00000400 +
0x061D9200 0x00000200 -
0x061D9400 0x00000600 +
0x061D9A00 0x00000200 -
0x061D9C00 0x00000800 +
0x061DA400 0x00000200 -
0x061DA600 0x00000600 +
0x061DAC00 0x00000200 -
0x061DAE00 0x00000400 +
0x061DB200 0x00000400 -
0x061DB600 0x00000800 +
0x061DBE00 0x00000200 -
0x061DC000 0x00000800 +
0x061DC800 0x00000200 -
0x061DCA00 0x00000200 +
0x061DCC00 0x00000200 -
0x061DCE00 0x00000A00 +
0x061DD800 0x00000200 -
0x061DDA00 0x00000600 +
0x061DE000 0x00000200 -
0x061DE200 0x00000200 +
0x061DE400 0x00000400 -
0x061DE800 0x00000800 +
0x061DF000 0x00000200 -
0x061DF200 0x00000200 +
0x061DF400 0x00000200 -
0x061DF600 0x00000600 +
0x061DFC00 0x00000800 -
0x061E0400 0x00001400 +
0x061E1800 0x00000600 -
0x061E1E00 0x00000A00 +
0x061E2800 0x00000200 -
0x061E2A00 0x00000800 +
0x061E3200 0x00001400 -
0x061E4600 0x00000400 +
0x061E4A00 0x00000200 -
0x061E4C00 0x00000400 +
0x061E5000 0x00000400 -
0x061E5400 0x00000400 +
0x061E5800 0x00000200 -
0x061E5A00 0x00000200 +
0x061E5C00 0x00000400 -
0x061E6000 0x00000600 +
0x061E6600 0x00000600 -
0x061E6C00 0x00000A00 +
0x061E7600 0x00000200 -
0x061E7800 0x00000C00 +
0x061E8400 0x00000A00 -
0x061E8E00 0x00000400 +
0x061E9200 0x00000200 -
0x061E9400 0x00000400 +
0x061E9800 0x00000200 -
0x061E9A00 0x00000A00 +
0x061EA400 0x00000200 -
0x061EA600 0x00000600 +
0x061EAC00 0x00000200 -
0x061EAE00 0x00000200 +
0x061EB000 0x00000200 -
0x061EB200 0x00000200 +
0x061EB400 0x00000200 -
0x061EB600 0x00000800 +
0x061EBE00 0x00000200 -
0x061EC000 0x00000600 +
0x061EC600 0x00000200 -
0x061EC800 0x00000400 +
0x061ECC00 0x00000200 -
0x061ECE00 0x00000800 +
0x061ED600 0x00000200 -
0x061ED800 0x00000800 +
0x061EE000 0x00000400 -
0x061EE400 0x00000400 +
0x061EE800 0x00000200 -
0x061EEA00 0x00000400 +
0x061EEE00 0x00000200 -
0x061EF000 0x00000400 +
0x061EF400 0x00000200 -
0x061EF600 0x00000400 +
0x061EFA00 0x00000200 -
0x061EFC00 0x00000600 +
0x061F0200 0x00000200 -
0x061F0400 0x00001200 +
0x061F1600 0x00000200 -
0x061F1800 0x00000C00 +
0x061F2400 0x00000600 -
0x061F2A00 0x00000600 +
0x061F3000 0x00000400 -
0x061F3400 0x00000A00 +
0x061F3E00 0x00000200 -
0x061F4000 0x00000A00 +
0x061F4A00 0x00000200 -
0x061F4C00 0x00000200 +
0x061F4E00 0x00000200 -
0x061F5000 0x00000200 +
0x061F5200 0x00000200 -
0x061F5400 0x00000400 +
0x061F5800 0x00000400 -
0x061F5C00 0x00000400 +
0x061F6000 0x00000200 -
0x061F6200 0x00000200 +
0x061F6400 0x00000200 -
0x061F6600 0x00001000 +
0x061F7600 0x00000200 -
0x061F7800 0x00000C00 +
0x061F8400 0x00000200 -
0x061F8600 0x00000600 +
0x061F8C00 0x00000200 -
0x061F8E00 0x00000400 +
0x061F9200 0x00000400 -
0x061F9600 0x00000200 +
0x061F9800 0x00000200 -
0x061F9A00 0x00000800 +
0x061FA200 0x00000400 -
0x061FA600 0x00000600 +
0x061FAC00 0x00000400 -
0x061FB000 0x00000400 +
0x061FB400 0x00000200 -
0x061FB600 0x00000600 +
0x061FBC00 0x00000400 -
0x061FC000 0x00000600 +
0x061FC600 0x00000200 -
0x061FC800 0x00000400 +
0x061FCC00 0x00000200 -
0x061FCE00 0x00000600 +
0x061FD400 0x00000400 -
0x061FD800 0x00000800 +
0x061FE000 0x00000200 -
0x061FE200 0x00000600 +
0x061FE800 0x00000200 -
0x061FEA00 0x00000400 +
0x061FEE00 0x00000200 -
0x061FF000 0x00000400 +
0x061FF400 0x00000200 -
0x061FF600 0x00000400 +
0x061FFA00 0x00000200 -
0x061FFC00 0x00000600 +
0x06200200 0x00000200 -
0x06200400 0x00001400 +
0x06201800 0x00000200 -
0x06201A00 0x00000E00 +
0x06202800 0x00000400 -
0x06202C00 0x00000400 +
0x06203000 0x00000200 -
0x06203200 0x00000C00 +
0x06203E00 0x00000200 -
0x06204000 0x00000A00 +
0x06204A00 0x00000400 -
0x06204E00 0x00000400 +
0x06205200 0x00000200 -
0x06205400 0x00000400 +
0x06205800 0x00000200 -
0x06205A00 0x00000C00 +
0x06206600 0x00000200 -
0x06206800 0x00001000 +
0x06207800 0x00000400 -
0x06207C00 0x00000800 +
0x06208400 0x00000200 -
0x06208600 0x00000600 +
0x06208C00 0x00000200 -
0x06208E00 0x00000600 +
0x06209400 0x00000200 -
0x06209600 0x00000200 +
0x06209800 0x00000200 -
0x06209A00 0x00000600 +
0x0620A000 0x00000400 -
0x0620A400 0x00000800 +
0x0620AC00 0x00000200 -
0x0620AE00 0x00000600 +
0x0620B400 0x00000200 -
0x0620B600 0x00000400 +
0x0620BA00 0x00000400 -
0x0620BE00 0x00000600 +
0x0620C400 0x00000C00 -
0x0620D000 0x00000600 +
0x0620D600 0x00000200 -
0x0620D800 0x00000800 +
0x0620E000 0x00000200 -
0x0620E200 0x00000600 +
0x0620E800 0x00000200 -
0x0620EA00 0x00000200 +
0x0620EC00 0x00000C00 -
0x0620F800 0x00000200 +
0x0620FA00 0x00000200 -
0x0620FC00 0x00000600 +
0x06210200 0x00000200 -
0x06210400 0x00001600 +
0x06211A00 0x00000400 -
0x06211E00 0x00000C00 +
0x06212A00 0x00000200 -
0x06212C00 0x00000400 +
0x06213000 0x00000200 -
0x06213200 0x00000C00 +
0x06213E00 0x00000200 -
0x06214000 0x00000A00 +
0x06214A00 0x00000200 -
0x06214C00 0x00000600 +
0x06215200 0x00000200 -
0x06215400 0x00000400 +
0x06215800 0x00000200 -
0x06215A00 0x00000E00 +
0x06216800 0x00000400 -
0x06216C00 0x00000A00 +
0x06217600 0x00000200 -
0x06217800 0x00000C00 +
0x06218400 0x00000200 -
0x06218600 0x00000600 +
0x06218C00 0x00000200 -
0x06218E00 0x00000600 +
0x06219400 0x00000400 -
0x06219800 0x00000600 +
0x06219E00 0x00000400 -
0x0621A200 0x00000A00 +
0x0621AC00 0x00000200 -
0x0621AE00 0x00000400 +
0x0621B200 0x00000400 -
0x0621B600 0x00000200 +
0x0621B800 0x00000400 -
0x0621BC00 0x00001000 +
0x0621CC00 0x00000200 -
0x0621CE00 0x00000A00 +
0x0621D800 0x00000200 -
0x0621DA00 0x00000600 +
0x0621E000 0x00000200 -
0x0621E200 0x00000400 +
0x0621E600 0x00000400 -
0x0621EA00 0x00000A00 +
0x0621F400 0x00000200 -
0x0621F600 0x00000400 +
0x0621FA00 0x00000200 -
0x0621FC00 0x00000400 +
0x06220000 0x00000400 -
0x06220400 0x00001800 +
0x06221C00 0x00000400 -
0x06222000 0x00000800 +
0x06222800 0x00000200 -
0x06222A00 0x00000600 +
0x06223000 0x00000400 -
0x06223400 0x00000A00 +
0x06223E00 0x00000200 -
0x06224000 0x00000A00 +
0x06224A00 0x00000200 -
0x06224C00 0x00000400 +
0x06225000 0x00000400 -
0x06225400 0x00000400 +
0x06225800 0x00000200 -
0x06225A00 0x00001000 +
0x06226A00 0x00000400 -
0x06226E00 0x00000800 +
0x06227600 0x00000200 -
0x06227800 0x00000C00 +
0x06228400 0x00000200 -
0x06228600 0x00000600 +
0x06228C00 0x00000200 -
0x06228E00 0x00000600 +
0x06229400 0x00000400 -
0x06229800 0x00000600 +
0x06229E00 0x00000A00 -
0x0622A800 0x00000600 +
0x0622AE00 0x00000600 -
0x0622B400 0x00000400 +
0x0622B800 0x00000A00 -
0x0622C200 0x00000A00 +
0x0622CC00 0x00000200 -
0x0622CE00 0x00000A00 +
0x0622D800 0x00000200 -
0x0622DA00 0x00000600 +
0x0622E000 0x00000800 -
0x0622E800 0x00000C00 +
0x0622F400 0x00000200 -
0x0622F600 0x00000400 +
0x0622FA00 0x00000600 -
0x06230000 0x00000200 +
0x06230200 0x00000200 -
0x06230400 0x00001200 +
0x06231600 0x00000800 -
0x06231E00 0x00000400 +
0x06232200 0x00000600 -
0x06232800 0x00000A00 +
0x06233200 0x00000800 -
0x06233A00 0x00000600 +
0x06234000 0x00000600 -
0x06234600 0x00000600 +
0x06234C00 0x00000600 -
0x06235200 0x00000600 +
0x06235800 0x00000200 -
0x06235A00 0x00000A00 +
0x06236400 0x00000800 -
0x06236C00 0x00000A00 +
0x06237600 0x00000200 -
0x06237800 0x00006000 +
0x0623D800 0x00000200 -
0x0623DA00 0x00009C00 +
0x06247600 0x00000200 -
0x06247800 0x00006000 +
0x0624D800 0x00000400 -
0x0624DC00 0x00002A00 +
0x06250600 0x00000E00 -
0x06251400 0x00005E00 +
0x06257200 0x00000400 -
0x06257600 0x001A8A00 +
The CTF author hints to us that the mapfile
can be visualised. It turns out that GDDRescuebiew
is a useful graphical tool that can visualise a mapfile using blocks. We install this on our own Linux system and open our mapfile with the GUI tool. This displays a bunch of green and red blocks at the end of the file corresponding to good and bad sectors. By resizing our window to find the optimal arrangement of blocks we are able to see that the bad sectors (red blocks) spell out the flag for today:
Flag:
HV24{b4d_s3ct0rs}