// HackTheBox  ·  writeup

Antarctica

HackTheBox Medium stringsobjdumpPythonbase64md5sum
Malware Analysis

Scenario

Antarctica, a stealthy Linux binary auto-starts via .profile, runs silently in the background, and may exfiltrate sensitive data through covert channels, compromising Station 97’s internal server activity. Your task is to analyze and reverse the binary file to find its internal logic, control flow, and hidden functionality. This will help you build practical skills in both static and dynamic analysis.

Executive Summary

Antarctica is a Go ELF backdoor built with garble, which scrambles function names and the Go runtime metadata but leaves string literals in plaintext. Static analysis of those strings and the code that references them exposed the full design. On start the binary takes a lock file so only one copy runs, then checks for VirtualBox through loaded kernel modules and DMI hardware strings. It plants an embedded SSH public key for persistent access, watches the user’s shell history with a filesystem notification API, and talks to its operator over DNS. The sample was analysed statically only and never executed.

Artifacts

Tooling note: garble randomises the pclntab magic and renames functions, so Go plugins for disassemblers will not recover symbols. The .rodata strings are still readable, and the code that uses them is found by following RIP-relative lea instructions in the main.* function range.

Execution

Q1 — What is the MD5 hash of the malware?

Hash the sample straight after extraction, before anything else touches the working directory.

md5sum antarctica
Click flag to reveal 6bba36e9f169c54e7e353163308a0abc
Q2 — The malware creates a lock on a file to ensure that only one instance of it is running. What is the full path of that file?

strings shows a Go binary with scrambled symbol names. Disassemble it, locate the main.* functions, and resolve each RIP-relative lea plus its length argument to the .rodata literal it loads. The entry code loads a path under /tmp right next to the file-lock setup, which is the single-instance guard.

objdump -d --no-show-raw-insn antarctica > main.asm
strings -a antarctica | grep -E '^/tmp/'

Tip: Go strings are not NUL-terminated, so plain strings output runs several literals together. The lea and length pair in the disassembly gives the exact value.

Click to reveal answer /tmp/file.lock

Defense Evasion

Q3 — The malware checks if a specific module is loaded as part of its anti-VM checks. What is the name of that module?

Loaded-module checks on Linux read /proc/modules. That path sits in the anti-VM function next to the name of a VirtualBox guest kernel module.

strings -a antarctica | grep -E 'proc/modules|vbox'
Click flag to reveal vboxguest
Q4 — The malware reads the content of files within a specific directory, searching for certain strings as part of its anti-VM checks. What is the full path of this directory?

A second anti-VM function reads hardware identity instead of modules. The DMI directory holds the vendor and product strings that give away a hypervisor, and its path literal is referenced from that function.

strings -a antarctica | grep -E 'sys/class/dmi'

Gotcha: The answer needs the trailing slash, because the malware builds file paths by appending names to this directory string.

Click to reveal answer /sys/class/dmi/id/

Persistence

Q5 — What is the SSH key that the malware added?

The key is a base64 blob in .rodata at offset 0x548b3d. It decodes to an ssh-rsa public key with the comment null@debian, the line the malware appends to authorized_keys for passwordless operator access. The blob length used below is simplified from the one-off extraction script.

dd if=antarctica bs=1 skip=$((0x548b3d)) count=752 2>/dev/null | base64 -d
Click flag to reveal ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCfCBTevpqxa0M8DzpdWfpTxEhbSf2/HjbYoIPlqGI4uNa23JpydpQFIlLRQh7Y+1dX2jmrZojE+uM6nQb+lkTR7fadCmKTOZZBAaQY2ld6OfSXfaxbfl2JXWGKtUf/Q+uLMazNhWR+4xXmJfeFkRMq/LZVTShB5NOZPHrEAK57QiQpD1Y+efK99z8gspMPk+YUEYYJQZBLXzm83nbOZVzNs7vIYAi03stTNA/tCyEkX7+854GI5LWLseoJWT/hSX7dzdIhED1pzleNho/zPA5E1X+encRGz/ln/HhYygaxAS+K3/j5A2a/Idiy9ZEdf/C6zVW+Qh8sMg54kniggRF4jozfL9CGdAMwBHH03+ivxn3EdMf1fQ2oEkEVdqIZxqcVGR7BG35B+WOQAyJIm2vJqK5OS1KoD70cf3EnnRhnnq66r9VUABswruPes48YRDHZOeNOKW+6e+/JxEcg5TPR2iQSYLirBpmbkBwa+0c6WNxRjAslbAOOP5rbQlv+BYs= null@debian

Credential Access

Q6 — What component of Linux does the malware use to watch for file changes?

The binary carries the IN_* event constants of the Go fsnotify package, which on Linux wraps the kernel’s inotify subsystem.

strings -a antarctica | grep -iE 'inotify|fsnotify'
Click to reveal answer inotify
Q7 — What file does the malware track for changes?

From Q6 we know a watcher exists, so find the function that registers it. It builds a %s/%s path from a base directory and a filename literal, and the filename is the user’s shell history. Following new lines as they are written lets the malware capture anything typed on the command line, including credentials.

strings -a antarctica | grep -F '.bash_history'
Click flag to reveal .bash_history

Command and Control

Q8 — What protocol does the malware use to exfiltrate data to its server?

The binary embeds a DNS client with EDNS handling and has no HTTP or raw-socket exfiltration strings. This answer was reasoned from that, not read from a single labelled artifact: a DNS library with its message handlers points to DNS as the covert channel, which also fits the scenario’s wording about covert channels.

strings -a antarctica | grep -iE 'edns|dns'
Click to reveal answer DNS
Q9 — What is the FQDN the malware tries to connect to?

With DNS as the transport (Q8), look for a hostname literal in the string table. One 20-character entry has the shape of a domain name. As with Q8, this was picked from the strings by shape and context rather than traced through the resolver call.

strings -a antarctica | grep -E '^[a-z0-9.-]+\.[a-z]+$'

Tip: .invalid is a reserved TLD that never resolves, so this looks like a placeholder value. It is still the indicator to hunt for.

Click flag to reveal myserver.invalid.com

Attack Summary

PhaseAction
ExecutionStarts from the user’s .profile and takes a lock file so only one instance runs
Defense EvasionChecks /proc/modules for a VirtualBox guest module and reads DMI files for hypervisor strings
PersistenceAppends an embedded ssh-rsa public key for the operator
Credential AccessWatches the user’s shell history through inotify
Command and ControlSends data to its server over DNS

IOCs

TypeValue
MD56bba36e9f169c54e7e353163308a0abc
File/tmp/file.lock
SSH key commentnull@debian
FQDNmyserver[.]invalid[.]com

MITRE ATT&CK

TechniqueIDDescription
Virtualization/Sandbox Evasion: System ChecksT1497.001Kernel module check and DMI reads for VirtualBox
Account Manipulation: SSH Authorized KeysT1098.004Embedded RSA public key added for persistent access
Unsecured Credentials: Bash HistoryT1552.003inotify watch on the shell history file
Application Layer Protocol: DNST1071.004DNS channel to the operator’s FQDN

Defender Takeaways

Writes to authorized_keys by a non-SSH process are worth alerting on. The embedded key gives access that survives password changes. File integrity monitoring on ~/.ssh/authorized_keys and a baseline of approved keys would catch it, and the null@debian comment is an easy hunting string.

Shell profile persistence needs its own watch. The scenario has the binary launched from .profile, which runs at every login and needs no privileges. Monitor changes to .profile, .bashrc and similar files, and treat new background processes started from them as suspicious.

Obfuscation did not hide the strings. garble broke symbol recovery but left the lock path, module names, key and domain readable in .rodata. Static string extraction is a cheap first pass on obfuscated Go, and the same strings make good YARA material.

DNS egress should be constrained and logged. A host that speaks DNS to an arbitrary resolver for a name nobody recognises is the covert channel the scenario describes. Force DNS through monitored resolvers and alert on rare domains and unusual query volume per host.

Conclusion

Antarctica gives its operator a lasting SSH foothold, a view of what users type, and a quiet DNS path out, all from one lightweight Go binary. Obfuscating the symbols was not enough, because the indicators sat in plain strings the whole time.