Coffee Invocation
hackthebox
Task: Stripped ELF64 binary that boots a JVM via JNI, loads embedded Java classes, and mutates boxed primitive caches to validate a flag. Solution: Carved Java classes from ELF, reversed native lookup tables and character remaps, detected Boolean.TRUE/FALSE swap to bypass Tinfoil decoy.
$ ls tags/ techniques/
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Coffee Invocation — Hack The Box
Description
Our new crazy conspiracy theorist intern, has blocked everyone from the coffee machine because he saw that aliens were trying to steal the "out of the world" secret recipe. Your mission is to unveil the secrets that lie behind his profound madness and teach him a javaluable lesson.
This is a native reverse-engineering challenge with embedded Java, not a web challenge and not a vulnerable Java application. The binary is a stripped ELF64 PIE that boots a JVM through JNI, loads hidden class files from its own image, sabotages Java runtime internals, and uses the modified semantics to validate the flag.
Analysis
The main hints are already in the title and strings:
- Coffee and javaluable strongly suggest Java.
- The ELF imports
JNI_CreateJavaVM, which confirms native-to-Java embedding. - Strings reference
Verify1,Verify2, staged verification messages, and theHTB{flag prefix.
So the correct mental model is:
- reverse the native ELF,
- recover the embedded Java classes,
- understand how JNI modifies Java behavior,
- invert both verification stages.
Extracting the hidden Java classes
binwalk would normally be a quick way to scan for embedded artifacts, but it was broken in this environment due to a Python imp import issue. Instead, I carved the classes directly by searching for the Java class magic 0xCAFEBABE.
The helper script extract_classes.py parses class-file structure so it can recover each full blob cleanly instead of dumping arbitrary bytes.
Relevant offsets found inside the ELF:
0x5180→Verify1.class0x5680→Verify2.class
The extraction logic is straightforward:
sig = b"\xca\xfe\xba\xbe" while True: i = data.find(sig, i) if i < 0: break end = parse_class_end(data, i) chunk = data[i:end]
...
$ grep --similar
Similar writeups
- [reverse][Pro]Challenge7— tamuctf
- [reverse][Pro]Huffpuff— spbctf
- [reverse][free]cf madness— pingctf2026
- [reverse][free]roulette— umdctf
- [reverse][Pro]Reverse Me— taipanbyte