Classdump
Classdump
Platform: spbctf | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-07-05 | Status: Solved Techniques: ipa_extraction, class_dump_analysis, radare2_disassembly, swift_string_initialization_tracing, video_frame_analysis
Summary
Task: iOS app (GimmeFlag.ipa) with class dump showing FirstFlagViewController with a 'secret' property; demo video shows correct secret entered but flag hidden by simulator detection. Solution: disassembled the init method with radare2 to find the hardcoded 19-byte secret string 'REDACTED' at address 0x100011f40, which is concatenated into the flag format.
Classdump — spbctf
Description
Now look at the classes and watch the demo.
An iOS application GimmeFlag.ipa is provided along with a class dump (classdump.txt), a preview screenshot (gimme_flag_preview.png), and a demo video (first_task_demo.mov). The class dump reveals three view controllers: FirstFlagViewController, SecondFlagViewController, ThirdFlagViewController. This writeup covers the first flag (the one demonstrated in the video).
Analysis
Binary identification: Extracted the IPA (which is just a ZIP) to get Payload/GimmeFlag.app/GimmeFlag — a Mach-O 64-bit arm64 Swift binary.
Class dump analysis: The classdump.txt (generated by class-dump 3.5) revealed the key class:
_TtC9GimmeFlag23FirstFlagViewController— has propertiesinput(UITextField),flag_1, andsecret(both String). Has methodfirstFlagWithFirstFlagBtn:.
The preview screenshot showed the First task UI: a text field labeled "Input secret here" and a "Give me first flag" button.
Strings output: Found key strings including "flag is spbctf{", "secret: ", "Wrong secret, try again", "Success", and a URL http://jay-from-future.xyz/get_flag.html (for the third task).
Demo video analysis: Extracted frames with ffmpeg. The demo showed:
- A secret being pasted into the password field (dots visible, 8+ characters)
- Banner: "GimmeFlag pasted from CoreSimulatorBridge" (clipboard paste)
- Alert: "Success — Secret is correct, but simulator detected" — the correct secret was entered but the flag is hidden on the simulator due to an anti-simulator check.
Disassembly of firstFlag function (radare2): The main logic function at 0x10000a8f4 (1908 bytes):
- Reads
self.input.text(user input from UITextField) - Compares it against
self.secretusing Swift String equality at0x10000acfc - On match (success branch at
0x10000ad1c): concatenates"flag is spbctf{"(at0x100012010, len 15) + the secret value +"}"(at0x100012020, len 1), displays result in alert - On mismatch (failure branch at
0x10000ae70): displays alert with title"Error"and message"Wrong secret, try again"
Solution
The key insight is that the secret is hardcoded in the FirstFlagViewController.init method.
Finding the hardcoded secret in the initializer: Disassembled FirstFlagViewController.init at 0x10000bbb4:
- At
0x10000bc68: loads a string literal from address0x100011f40with length0x13(19 bytes) - Stores it into
self.secret(via the Swift property offset table at0x10001a000+0x6b8) - The 19-byte string at
0x100011f40:REDACTED(leetspeak for "catch decoded value")
Since the success branch builds "flag is spbctf{" + secret + "}", and the secret is REDACTED:
python read-only • copy allowed#!/usr/bin/env python3 # Reconstruct the flag from the hardcoded secret secret = "REDACTED" # 19 bytes at 0x100011f40 flag = f"spbctf{{{secret}}}" print(flag) # spbctf{REDACTED}