Original writeups: https://lkmidas.github.io/posts/20210719-ggctf2021-writeups/
TL;DR:
- Analyze the main function -> pretty normal, can notice some unfamiliar printf formats.
- Analyze the init function -> learn that this program registers a bunch of new different printf formats.
- Analyze each handler function -> learn that most of them are used to create a register based VM.
- Write an emulator + disassembler to analyze it -> learn that the first block of VM code tries to decode a larger block of code using the first byte of our input.
- Because this is a format string VM, the first byte of the block of code must be % -> find out the first correct byte of the input is T.
- Use the emulator + disassembler to analyze the decrypted code block -> reach the check instruction.
- Insert z3 variables into the input bytes, change the emulator a bit -> let z3 solve the correct input automatically.
- Run the original program, pass in the correct input -> get flag