This is the another interesting flareon challenge for me as it involves python memory, python debugger and maths solver library. Given a wopr.exe executable which requires user to enter some command and by given a correct launching code, flag was given.
Main steps involved:
- Determine the type of executable and compiler used
- Extract the executable using suitable tools
- Using memory forensic tools to find out the hidden code
- Using python debugger (pdb) to get the correct value that found in the compare string function
- Using maths solver tools to solve the linear XOR equation
- Enter launch code (Flag Get!)
Determine the type of executable and compiler used
In CFF explorer, it found that the executable file is compiled using python2exe program as there have some python related strings (python37.dll & *.pyd etc.) in the hex view.
Extract the executable using suitable tools
Using this tool to unpack the python exe.
Go into extracted folder and decompile the entry point of the python files (in this case pyiboot02_cleanup) using this link.
*Manual Decompilation check here.
Before put the file into the decompiler, rename and add .pyc extention into it. The pyc decompiled code:
From the code above, the pointer of print() and exec() was changed. So, all the print() function actually is exec(). Hmm so simple obfuscation. 🐱👤
The io.BytesIO() will read and write data within the memory bytestream buffer. Therefore, i cannot simply using the print() to read the value in memory and trace it. 😪
Then continue analysis, I saw something interesting in exec(lzma.decompress()) and it will cause error when i run it.
...
leg = io.BytesIO()
...print((lzma.decompress(fire(eye(__doc__.encode()), bytes([i]) + BOUNCE), format=lzma.FORMAT_XZ)))
...
However, the exec() will leave a trace in the memory dump when it execute some something. So, I execute the code and record the memory dump using the dumpIt.exe (Explaination here)
Then, using volatility to run pslist to find out the child wopr.exe process as the main code mostly running those library loading stuffs.
After identified the PID of the wopr.exe, run the volatility memdump to dump out the relevent child wopr.exe process and the compressed code was found.
This linear xor equation catched my eyes as this is the launch code need to get the flag.
b[0] = x[2] ^ x[3] ^ x[4] ^ x[8] ^ x[11] ^ x[14]
b[1] = x[0] ^ x[1] ^ x[8] ^ x[11] ^ x[13] ^ x[14]
b[2] = x[0] ^ x[1] ^ x[2] ^ x[4] ^ x[5] ^ x[8] ^ x[9] ^ x[10] ^ x[13] ^ x[14] ^ x[15]
b[3] = x[5] ^ x[6] ^ x[8] ^ x[9] ^ x[10] ^ x[12] ^ x[15]
b[4] = x[1] ^ x[6] ^ x[7] ^ x[8] ^ x[12] ^ x[13] ^ x[14] ^ x[15]
b[5] = x[0] ^ x[4] ^ x[7] ^ x[8] ^ x[9] ^ x[10] ^ x[12] ^ x[13] ^ x[14] ^ x[15]
b[6] = x[1] ^ x[3] ^ x[7] ^ x[9] ^ x[10] ^ x[11] ^ x[12] ^ x[13] ^ x[15]
b[7] = x[0] ^ x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[8] ^ x[10] ^ x[11] ^ x[14]
b[8] = x[1] ^ x[2] ^ x[3] ^ x[5] ^ x[9] ^ x[10] ^ x[11] ^ x[12]
b[9] = x[6] ^ x[7] ^ x[8] ^ x[10] ^ x[11] ^ x[12] ^ x[15]
b[10] = x[0] ^ x[3] ^ x[4] ^ x[7] ^ x[8] ^ x[10] ^ x[11] ^ x[12] ^ x[13] ^ x[14] ^ x[15]
b[11] = x[0] ^ x[2] ^ x[4] ^ x[6] ^ x[13]
b[12] = x[0] ^ x[3] ^ x[6] ^ x[7] ^ x[10] ^ x[12] ^ x[15]
b[13] = x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7] ^ x[11] ^ x[12] ^ x[13] ^ x[14]
b[14] = x[1] ^ x[2] ^ x[3] ^ x[5] ^ x[7] ^ x[11] ^ x[13] ^ x[14] ^ x[15]
b[15] = x[1] ^ x[3] ^ x[5] ^ x[9] ^ x[10] ^ x[11] ^ x[13] ^ x[15]
if b != h:
However, we need to get the correct h value as the h value is depends on the
trust = windll.kernel32.GetModuleHandleW(None)
since the base pointer of kernel32.dll is different from the binary and our machine, so we cannot just simply run it the get the h value.
Using python debugger (pdb) to get the correct value that found in the compare string function
Since the base pointer of kernel32.dll is different from the binary and our machine, so we cannot just simply run it the get the h value. Here, I’m using the python debugger (pdb) to get the correct h value.
Steps taken in picuture above:
- Set Breakpoint in CreateProcessW
- Run until the breakpoint
- Go to temp file created (most of the python file will drop this in temp file with _MEI<random num>)
- Go into this -> __init__.py and paste the code from memory with pdb.set_trace()
- Continue the process in debugger.
- Step few time and then h value get.
Using maths solver tools to solve the linear XOR equation
To solve the linear XOR equation? Easy, use z3 Solver 🙌
Launch code get. Now just play around with the wopr.exe and insert the launch code then the flag is on your hands now 🐱🚀. Done~
Correct me if something is incorrect. 😬
Reference
https://hshrzd.wordpress.com/2018/01/26/solving-a-pyinstaller-compiled-crackme/
https://docs.python.org/3/library/pdb.html
https://github.com/Z3Prover/z3
https://www.fireeye.com/content/dam/fireeye-www/blog/pdfs/FlareOn6_Challenge7_Solution_WOPR.pdf