Description
A compiled SafeOpener.class supposedly reveals the forgotten safe code. Either strings analysis or Java decompilation uncovers the embedded flag.
Fast path: strings on the .class file. The flag is in the constant pool as plain UTF-8.
Constant-pool peek without a GUI: javap -c -p SafeOpener.
If you want decompiled Java, jd-gui or jadx renders SafeOpener.java.
wget https://artifacts.picoctf.net/c/290/SafeOpener.classstrings SafeOpener.class | grep picojavap -c -p SafeOpenerSolution
Walk me through it- Step 1Strings is the fast pathJava string constants live in the .class constant pool as plain UTF-8, so strings + grep reveals the flag in one command.bash
strings SafeOpener.class | grep -oE 'picoCTF\{[^"}]*\}'Learn more
Java .class files are JVM bytecode. Unlike stripped native binaries, .class files retain a great deal of structure: class names, method names, field names, and string constants all live in the constant pool, a UTF-8 table at the top of the file.
strings SafeOpener.class | grep picohits that table directly.String constants survive obfuscation because the runtime needs them. ProGuard and similar tools rename classes to
a.classand methods toa(), but a literal like"picoCTF{...}"must remain intact forString.equalsto work, so it stays in the constant pool. That is why grepping for the flag prefix beats most light obfuscation. - Step 2Peek the constant pool with javapjavap -c -p prints disassembled bytecode plus the constant pool. No GUI needed and it ships with the JDK.bash
javap -c -p SafeOpenerLearn more
javapis the standard JDK disassembler.-cshows method bytecode and-pincludes private members. The output is the closest thing to running "objdump on Java": everyldcinstruction loads a string from the constant pool, and each load is annotated with the literal it resolves to. So scanning the disassembly forldc "picoCTFgives you both the value and the method that uses it. - Step 3Optional: decompile to Java sourcejd-gui or jadx reconstruct SafeOpener.java. Once you have the .java file, grep -oE 'picoCTF[^"]*' extracts the literal cleanly.bash
sudo apt install -y jd-guibashjd-gui SafeOpener.classbashgrep -oE 'picoCTF[^"]*' SafeOpener.javaLearn more
jd-gui is a graphical Java decompiler that reconstructs near-original Java source from bytecode. Variable names are usually replaced with synthetic identifiers like
paramString1, but string literals stay intact, which is all this challenge needs.Once you have the decompiled
SafeOpener.java, the surgical grep isgrep -oE 'picoCTF[^"]*' SafeOpener.java:-oprints only the match (not the whole line) and the character class[^"]*stops at the closing quote of the literal. That is more robust than splitting on backslashes (the oldcut -d "\""recipe), which breaks the moment the source contains escape sequences.For heavier lifting, Ghidra handles both .class files and native binaries with one decompiler view, and bytecode-viewer bundles multiple Java decompilers (jd, jadx, CFR, Procyon) so you can compare their output side-by-side when one of them produces garbled control flow.
Flag
picoCTF{SAf3_0p3...8a993}
No dynamic execution is required; the challenge is purely static analysis.