Thanks to Deroko and some ARTeam members to play with CLGT. Below is the write up by Deroko posted on http://www.xchg.info/wiki/index.php?title=CodeGate2012_bin500
CodeGate2012 bin500
Challenge: Seeing that it is not all.
Link to challenge: http://deroko.phearless.org/codegate2012/bin/bin500.zip
This binary is double ReWolf vm, and python script for modified Olly by Immunity.
Script which comes with binary uses marshal.loads to load already compiled pyc code which was produced with marshal.dump
To get .pyc back we need to make some modification to our script:
Now C:test.pyc will have dump of python bytecode.
If you look carefully through script, some strings might look like a clue:
readMemory getRegs EIP Nice work, Key1 : But, Find Next Key! Nice work, Key2 : Input Key : Key1 + Key2 Nothing Found ...
So this script will probably try to read from current EIP some bytes (readMemory + EIP are good hint), and make key out of it. After modifying test.pyc to have proper layout:
00000000 03 f3 0d 0a dc dd e2 4c 63 00 00 00 00 00 00 00 |.......Lc.......| 00000010 00 02 00 00 00 40 00 00 00 73 22 00 00 00 64 00 |.....@...s"...d.| 00000020 00 64 01 00 6c 00 00 5a 00 00 64 02 00 84 00 00 |.d..l..Z..d.....|
Which is actually 4 bytes for python signature + 4 bytes for timestamp +marshal.dump() data we get .pyc file which we can decompile.
For sake of this solution, we will use some simple program to dump python byte-code, and one I found here:http://nedbatchelder.com/blog/200804/the_structure_of_pyc_files.html
After disassembling binary with this python script we get (I cut not important parts):
15 LOAD_ATTR 2 (readMemory) 18 LOAD_CONST 1 (4237456) 21 LOAD_CONST 2 (80) 24 CALL_FUNCTION 2
So from address 40A890 it will read 80 bytes and keep it in internal buffer.
Now comes interesting part when it actually gets keys:
19 54 LOAD_FAST 4 (regs) 57 LOAD_CONST 3 ('EIP') 60 BINARY_SUBSCR 61 LOAD_CONST 4 (4273157) 64 COMPARE_OP 2 (==) 67 POP_JUMP_IF_FALSE 161
and
23 >> 161 LOAD_FAST 4 (regs) 164 LOAD_CONST 3 ('EIP') 167 BINARY_SUBSCR 168 LOAD_CONST 15 (4278021) 171 COMPARE_OP 2 (==) 174 POP_JUMP_IF_FALSE 276
If you look at out.txt (in attachment) you may also see what’s read from where as this python script is not complicated, and python byte code is quite easy to understand.
So just set EIP to be 413405 and run script, and you will get 1st key. Then set EIP to be 414705 and run scrip again. If you did, everything correct you should see in Log of Immunity Debugger this:
So final key is Never_up_N3v3r_1n
Greetings
I would like to say tnx to my ARTeam mates, vnsecurity guys, and rd , and of course to superkhung for listening to my random blabing on skype during CTF :)
Author
deroko of ARTeam