HacknamStyle Plaid CTF write-up
-
Upload
vanhoefm -
Category
Technology
-
view
198 -
download
5
description
Transcript of HacknamStyle Plaid CTF write-up
HacknamStyle
Plaid CTF 2014 Write-ups
Reversing: g++
Reversing: g++
Reversing: g++
Reversing: g++
Reversing: g++
Reversing: g++
Makefile:
echo '${KEY}' | perl -p -e 's/(.)/<DEL>/ge' > key.h
Key.h:
K(0,116) // 't'
K(1,101) // 'e'
K(2,115) // 's'
K(3,116) // 't‘
Solveme.cpp:
template <int i> struct key { static int r = 0; };
#define K(i,v) template<> struct key<i> { S r = v; };
Reversing: g++
• Template metaprogramming
• Password verified during compilation
• “key<i>::r” gives i-th char of password
• Result printed at runtime
Reversing: g++
int main() {
if (!vv<0>::r)
// print 16 characters
else
std::cout << "Wrong\n";
}
Reversing: g++
Analyzing templates:
• vv<0>::r zero iff gg<i>::r zero (for 0 <= i < 16)
• gg<i>::r = hiddenkey<a, b> - makefilekey<a, b>
• Parameter `a` and `b` depend on `i`
• Hiddenkey is constant, extract value.
How is makefilekey constructed?
Calculation makefilekey<a, b>
Let g++ replace #define’s:
• g++ -E -o solveme2.cpp solveme.cpp
<boring reversing>
makefilekey<a,b> =
( lookup<a*4> * key<b>
+ lookup<a*4+1> * key<b+4>
+ lookup<a*4+2> * key<b+8>
+ lookup<a*4+3> * key<b+12>) % 257;
Solution
Method 1:
• Key can be bruteforced in groups of 4 chars
• Extract constants, implement algorithm
Method 2:
• Solve linear equations
Reversing: Tiffany
From Child's Play (Chucky)
Reversing: Tiffany
Initialization
Computation
Reversing: Tiffany
• Spawns 7 children, many ptrace calls
• Hint: “Each instance does a very simple thing”
• ltrace fails during initialization
• strace fails after computation
<DEMO>
strace ./tiffany 2>&1 | less
Parent spawns 7 children
getpid() = 15866 clone(...) = 15867 clone(...) = 15868 clone(...) = 15869 clone(...) = 15870 clone(...) = 15871 clone(...) = 15872 clone(...) = 15873 = 0x3e01 Child knows PID of parent and previous children.
Ptrace communication
• Parent sends messages to children using ptrace
• Similarly, children send each other messages using ptrace.
One of the reasons why the program is slow…
Ptrace communication
ptrace(PTRACE_ATTACH, 15823, 0, 0) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, NULL, 0, NULL) = 15823
ptrace(PTRACE_POKEDATA, 15823, 0x618180, 0x1) = 0
ptrace(PTRACE_POKEDATA, 15823, 0x618184, 0) = 0
ptrace(PTRACE_POKEDATA, 15823, 0x618188, 0) = 0
ptrace(PTRACE_POKEDATA, 15823, 0x61818c, 0x3e01) = 0
ptrace(PTRACE_DETACH, 15823, 0, SIG_0) = 0
kill(15823, SIGUSR1) = 0
Ptrace communication
ptrace(PTRACE_ATTACH, 15823, 0, 0) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, NULL, 0, NULL) = 15823
ptrace(PTRACE_POKEDATA, 15823, 0x618180, 0x1) = 0
ptrace(PTRACE_POKEDATA, 15823, 0x618184, 0) = 0
ptrace(PTRACE_POKEDATA, 15823, 0x618188, 0) = 0
ptrace(PTRACE_POKEDATA, 15823, 0x61818c, 0x3e01) = 0
ptrace(PTRACE_DETACH, 15823, 0, SIG_0) = 0
kill(15823, SIGUSR1) = 0
Ptrace communication
ptrace(PTRACE_ATTACH, 15823, 0, 0) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, NULL, 0, NULL) = 15823
ptrace(PTRACE_POKEDATA, 15823, POKE1, 0x1) = 0
ptrace(PTRACE_POKEDATA, 15823, POKE2, 0) = 0
ptrace(PTRACE_POKEDATA, 15823, POKE3, 0) = 0
ptrace(PTRACE_POKEDATA, 15823, 0x61818c, 0x3e01) = 0
ptrace(PTRACE_DETACH, 15823, 0, SIG_0) = 0
kill(15823, SIGUSR1) = 0
Child Message Handler
Command #0
0x618180 = POKE1 = 1 # message available
0x618184 = POKE2 = 0 # destination ID
0x618188 = POKE3 = 0 # command ID
0x61818C = ARGS = 0x3e01
kill(15823, SIGUSR1) # notify child
Parent sends CMD #0 to first child
Send PID of last child to the first child.
Command #1
• Copies large amount of data
• Child handler makes local copy
Each child is given unique data
Initialization Complete
Password now requested
Command #3
• Parent sends every char to first child
Child handler:
• Updates states according to char and local data
• Forwards char to previous child
• Last child informs parent to send next char
Every child gets char and “performs a step”
Parent sends command #2 to first child.
Password okay?
• Password OK if final `bitokay` is 1
• All children must “accept” the password
• Every child is a DFA
• Local data is state transition function
Extract DFA, intersect, find witness
Minimize DFA while intersecting!