TSG CTF 2024 Reverse WriteUp
Champion 🥇
Misbehave
The logic of program is simple. The flag xor with a number generated by gen_rand
function.
It is worth noting that the memcmp
in PLT is modified to sub_13A3
during the operation. The encrypted flag will xor with the state of random number generator before the comparison.
It can help you avoid many unnecessary mistakes using the c code generated by IDA directly.
1 |
|
Warmup SQLite
Firstly, we need to decompile the bytecode of SQLite. According to this site, we can get the meaning of each command.
1 | | id | opcode | p1 | p2 | p3 | p4 | p5 | Comment | |
By analyzing the bytecode, it just splits the flag into characters, transforms them into unicode, and modifies each value $x$ to $(7x + 2) \bmod 256$.
1 | flag_enc = [100, 115, 39, 99, 100, 54, 27, 115, 69, 220, 69, 99, 100, 191, 56, 161, 131, 11, 101, 162, 191, 54, 130, 175, 205, 191, 222, 101, 162, 116, 147, 191, 55, 24, 69, 130, 69, 191, 252, 101, 102, 101, 252, 189, 82, 116, 41, 147, 161, 147, 132, 101, 162, 82, 191, 220, 9, 205, 9, 100, 191, 38, 68, 253] |
TSGDBinary
First of all, we need to deobfuscate the tsgdbinary.py
to check what it does during the operation.
1 | import gdb |
The program will break before calling the memcmp
. The flag input will be modified by the debugger and then the program will jump to 0x404340
. The code at 0x404340
in binary is encrypted, we need to decrypt it first.
1 | code = idc.get_bytes(0x404340, 0x6000) |
The code at 0x404340
is sevaral mapping functions. We can find the original value manually and then decrypt the flag.
1 | import struct |
serverless
We extract all the regex rules from the compose.yaml
and divide them into two parts: ones are expanding the length, and the others are reducing.
Focus on the reducing part first.
1 | [ |
It is easy to find that the rules are removing an uppercase letter with a corresponding lowercase letter. We know the flag starts with TSGCTF
. If we want to remove all the characters, we need to construct (f)(t)(c)(g)(s)(t)
within {}
.
Pay attention to the expanding part next.
1 | [ |
It can be noticed that an underscore _
will be replaced by )(
, which creates a new group. If we want to create 6 groups, we need to contain 5 underscores with in {}
. The regex rules will generate a /
right after the {
, using it to replate the pattern one by one from left to right.
The pattern rules can be divided into three categories:
- Replace a pattern to
(a)(b)(c)DEF
. - Replace a pattern to
(a)(b)(c)
, which is the end of a group. - Replace a pattern to
aDEF
, which is the start of a group.
We can build a graph to represent the rules and use BFS to find the path.
1 | rules = [ |