// HackTheBox  ·  writeup

Loggy

HackTheBox Easy unzipfilesha256sumstringsobjdump
Malware Analysis

Scenario

Janice from accounting is beside herself! She was contacted by the SOC to tell her that her work credentials were found on the dark web by the threat intel team. We managed to recover some files from her machine and sent them to the our REM analyst.

Executive Summary

Janice ran a program she believed only took screenshots. Static analysis showed a Go binary that pulls in a screen-capture library and an FTP client library. It records keystrokes to a text file, saves periodic screenshots as image files, and ships the lot to an attacker-controlled FTP host with credentials hardcoded in the binary. The keystroke log held the password Janice typed when she changed it, which explains how her work credentials ended up for sale. The screenshots then showed what she had open the last time the tool ran.

Artifacts

Timestamp note: none of the questions ask for timestamps. The screenshot filenames carry an epoch value, which is the order to use when deciding which capture is the latest.

Execution

Q1 — What is the SHA-256 hash of this malware binary?

Unpack the archive, confirm with file that Loggy.exe is a PE executable, and hash it. Hash the extracted binary, not the zip.

unzip danger.zip && file Loggy.exe && sha256sum Loggy.exe
Click flag to reveal 6acd8a362def62034cbd011e6632ba5120196e2011c83dc6045fcb28b590457c
Q2 — What programming language (and version) is this malware written in?

Go binaries embed the toolchain version as a plain string, and a mass of github.com/... import paths is the other giveaway. A go1. grep over the strings gives the exact build version.

strings Loggy.exe | grep -E 'go1\.[0-9]+'

Tip: The answer format is the language name followed by the version, so expand go to the full language name.

Click to reveal answer Golang 1.22.3

Collection

Q4 — What dependency, expressed as a GitHub repo, supports Janice’s assertion that she thought she downloaded something that can just take screenshots?

Janice’s story is that the tool only takes screenshots, so look for the third-party library that does it. The import paths in the binary’s strings include a screen-capture package, which is the legitimate-looking cover for the rest of the behaviour.

strings Loggy.exe | grep -i 'github.com'
Click to reveal answer github.com/kbinani/screenshot
Q5 — Which function call suggests that the malware produces a file after execution?

The format mask is nine characters, and the malware both captures screens and logs keys, so it has to write them out somewhere. WriteFile fits the mask and the behaviour. This answer was reasoned from the mask and the observed output files, not read from a named call site in the disassembly.

Click flag to reveal WriteFile
Q8 — What file keeps getting written to disk?

The same strings pass shows a fixed filename that is written to repeatedly. It sits next to the keystroke-handling code, and it is the file recovered from Janice’s machine as the keystroke log.

strings Loggy.exe | grep -iE '\.(txt|png)'
Click to reveal answer keylog.txt
Q10 — What app did Janice have open the last time she ran the "screenshot app"?

The screenshots are named with an epoch timestamp, so the highest value is the last run. Open that image: the window in the foreground is the answer, shown as Solitaire & Casual Games.

ls screenshot_*.png | sort

Tip: The answer is the app’s short name, so take it from the window title rather than the full Store listing text.

Click flag to reveal Solitaire

Credential Access

Q9 — When Janice changed her password, this was captured in a file. What is Janice's username and password?

Read keylog.txt from the recovered files and find the stretch where she typed a username followed by a password change. The log repeats keys and does not preserve letter case, so the capitalisation of the password was reasoned rather than read directly. The deduplicated keypresses pointed to this value and the platform accepted it.

cat keylog.txt

Gotcha: Keystroke logs drop case and double up held keys, so the raw text will not match the real password character for character. Deduplicate the keypresses first.

Click to reveal answer janice:Password123

Exfiltration

Q3 — There are multiple GitHub repos referenced in the static strings. Which GitHub repo would be most likely suggest the ability of this malware to exfiltrate data?

Of the imported packages, one is an FTP client. A screenshot library and a keyboard hook only collect data; an FTP client is what moves it off the host.

strings Loggy.exe | grep -i 'github.com'
Click flag to reveal github.com/jlaffaye/ftp
Q6 — You observe that the malware is exfiltrating data over FTP. What is the domain it is exfiltrating data to?

From Q3 the FTP library is the exfil path, so find its caller. The function main.sendFilesViaFTP contains the hardcoded dial string with the port appended, gotthem.htb:21. The answer is the host part only.

strings Loggy.exe | grep -E ':21'
Click to reveal answer gotthem.htb
Q7 — What are the threat actor’s credentials?

The login credentials are not a single string. Go strings are pointer-and-length pairs packed together in .rdata, so strings shows them run together. Disassemble main.sendFilesViaFTP and follow the arguments to the FTP Login call: the username is at 0x650828 with length 11 and the password at 0x653417 with length 17. The lengths split the packed text correctly.

objdump -d Loggy.exe | grep -A60 'main.sendFilesViaFTP>:'

Gotcha: Without the lengths from the disassembly you cannot tell where one string ends and the next begins. Check the argument order of the Login call too, since username comes first.

Click flag to reveal NottaHacker:Cle@rtextP@ssword

Attack Summary

PhaseAction
ExecutionJanice runs a binary presented as a screenshot tool
CollectionScreenshots are taken with the kbinani screenshot library and saved as image files
CollectionKeystrokes are appended to keylog.txt
Credential AccessJanice’s password change is captured in the keylog
Exfiltrationmain.sendFilesViaFTP logs in to gotthem.htb:21 with hardcoded credentials and uploads the files

IOCs

TypeValue
SHA-2566acd8a362def62034cbd011e6632ba5120196e2011c83dc6045fcb28b590457c
FileLoggy.exe
Filekeylog.txt
Domaingotthem[.]htb
FTP credentialsNottaHacker:Cle@rtextP@ssword
Go dependencygithub.com/jlaffaye/ftp
Go dependencygithub.com/kbinani/screenshot

MITRE ATT&CK

TechniqueIDDescription
Screen CaptureT1113Periodic screenshots through the kbinani screenshot library
Input Capture: KeyloggingT1056.001Keystrokes recorded to keylog.txt, including Janice’s new password
Data Staged: Local Data StagingT1074.001Captures kept on disk until the upload
Exfiltration Over Alternative Protocol: Exfiltration Over Unencrypted Non-C2 ProtocolT1048.003Plain FTP upload to gotthem.htb with hardcoded credentials

Defender Takeaways

A “screenshot tool” that imports an FTP client is not a screenshot tool. Dependency lists are cheap to read on a Go binary, because the import paths are embedded as strings. Pairing a capture library with a network client library is a quick triage signal before any disassembly.

Plain FTP out of a workstation should be blocked or alerted on. The malware used an unencrypted FTP session on port 21 to a single host. Egress filtering that only allows web traffic from user endpoints would have stopped the upload, and a DNS or proxy alert on a rarely seen domain would have flagged it.

Hardcoded credentials in malware are a gift to the defender. The FTP username and password sit in the binary, so they can be shared as IOCs and used to find other victims on the same drop server. Go’s packed strings hide them from strings, so pull them out from the call site instead.

Keyloggers turn every password change into a leak. Janice’s new password was written to disk in the clear. Credential-theft exposure from endpoint malware is why leaked credentials show up on the dark web, so reset passwords after any keylogger find and enforce MFA so a stolen password is not enough.

Conclusion

A tool sold as a screenshot utility logged Janice’s keystrokes and screens and sent them to an attacker’s FTP server using credentials baked into the binary. The binary’s own import list gave the capability away, and its hardcoded credentials gave defenders a ready-made indicator.