26
Feb
2012

CODEGATE 2012 – Binary 500

In the challenge’s zipfile we find two files:
– vm2x.exe, a simple Win32 GUI program with a handful of buttons
– vm2x.dat, python bytecode wrapped in a regular python script

The python file (vm2x.dat) loads a chunk of embedded python bytecode (in variable __code) and executes it. Let’s disassemble it, for which we first need to strip the last two lines (which execute and subsequently delete the embedded bytecode object).

head -n -2 vm2x.dat > vm2x.py

Then, we use python in interactive mode to disassemble the embedded code:

$ python2 -i vm2x.py
>>> from dis import dis
>>> __code.co_consts
(-1, None,
<code object toString at 0x7fc493ee6830, file "C:\..\Immunity Inc\..\vm2x.py", line 3>,
<code object main at 0x7fc493ee6cb0, file "C:\..\vm2x.py", line 12>)
>>> dis(__code.co_consts[3])
 13           0 LOAD_GLOBAL              0 (immlib)
              3 LOAD_ATTR                1 (Debugger)
              6 CALL_FUNCTION            0
              9 STORE_FAST               1 (imm)

 15          12 LOAD_FAST                1 (imm)
             15 LOAD_ATTR                2 (readMemory)
             18 LOAD_CONST               1 (4237456)
             21 LOAD_CONST               2 (80)
             24 CALL_FUNCTION            2
             27 STORE_FAST               2 (a)

 16          30 LOAD_GLOBAL              3 (toString)
             33 LOAD_FAST                2 (a)
             36 CALL_FUNCTION            1
             39 STORE_FAST               3 (b)

 18          42 LOAD_FAST                1 (imm)
             45 LOAD_ATTR                4 (getRegs)
             48 CALL_FUNCTION            0
             51 STORE_FAST               4 (regs)

 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

 20          70 LOAD_FAST                3 (b)
             73 LOAD_CONST               5 (29)
             76 BINARY_SUBSCR       
             77 LOAD_FAST                3 (b)
             80 LOAD_CONST               6 (52)
             83 BINARY_SUBSCR       
             84 BINARY_ADD          
             85 LOAD_FAST                3 (b)
             88 LOAD_CONST               7 (69)
             91 BINARY_SUBSCR       
             92 BINARY_ADD          
             93 LOAD_FAST                3 (b)
             96 LOAD_CONST               6 (52)
             99 BINARY_SUBSCR       
            100 BINARY_ADD          
            101 LOAD_FAST                3 (b)
            104 LOAD_CONST               8 (65)
            107 BINARY_SUBSCR       
            108 BINARY_ADD          
            109 LOAD_FAST                3 (b)
            112 LOAD_CONST               9 (46)
            115 BINARY_SUBSCR       
            116 BINARY_ADD          
            117 LOAD_FAST                3 (b)
            120 LOAD_CONST              10 (68)
            123 BINARY_SUBSCR       
            124 BINARY_ADD          
            125 LOAD_FAST                3 (b)
            128 LOAD_CONST              11 (63)
            131 BINARY_SUBSCR       
            132 BINARY_ADD          
            133 STORE_FAST               5 (str1)

 21         136 LOAD_FAST                1 (imm)
            139 LOAD_ATTR                5 (log)
            142 LOAD_CONST              12 ('Nice work, Key1 : "')
            145 LOAD_FAST                5 (str1)
            148 BINARY_ADD          
            149 LOAD_CONST              13 ('"')
            152 BINARY_ADD          
            153 CALL_FUNCTION            1
            156 POP_TOP             

 22         157 LOAD_CONST              14 ('But, Find Next Key!')
            160 RETURN_VALUE        

 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

 24         177 LOAD_FAST                3 (b)
            180 LOAD_CONST               9 (46)
            183 BINARY_SUBSCR       
            184 LOAD_FAST                3 (b)
            187 LOAD_CONST               5 (29)
            190 BINARY_SUBSCR       
            191 BINARY_ADD          
            192 LOAD_FAST                3 (b)
            195 LOAD_CONST              16 (2)
            198 BINARY_SUBSCR       
            199 BINARY_ADD          
            200 LOAD_FAST                3 (b)
            203 LOAD_CONST               7 (69)
            206 BINARY_SUBSCR       
            207 BINARY_ADD          
            208 LOAD_FAST                3 (b)
            211 LOAD_CONST              16 (2)
            214 BINARY_SUBSCR       
            215 BINARY_ADD          
            216 LOAD_FAST                3 (b)
            219 LOAD_CONST               8 (65)
            222 BINARY_SUBSCR       
            223 BINARY_ADD          
            224 LOAD_FAST                3 (b)
            227 LOAD_CONST               9 (46)
            230 BINARY_SUBSCR       
            231 BINARY_ADD          
            232 LOAD_FAST                3 (b)
            235 LOAD_CONST              17 (0)
            238 BINARY_SUBSCR       
            239 BINARY_ADD          
            240 LOAD_FAST                3 (b)
            243 LOAD_CONST              18 (61)
            246 BINARY_SUBSCR       
            247 BINARY_ADD          
            248 STORE_FAST               6 (str2)

 25         251 LOAD_FAST                1 (imm)
            254 LOAD_ATTR                5 (log)
            257 LOAD_CONST              19 ('Nice work, Key2 : "')
            260 LOAD_FAST                6 (str2)
            263 BINARY_ADD          
            264 LOAD_CONST              13 ('"')
            267 BINARY_ADD          
            268 CALL_FUNCTION            1
            271 POP_TOP             

 26         272 LOAD_CONST              20 ('Input Key : Key1 + Key2')
            275 RETURN_VALUE        

 28     >>  276 LOAD_CONST              21 ('Nothing found ..')
            279 RETURN_VALUE        
            280 LOAD_CONST               0 (None)
            283 RETURN_VALUE        

From the disassembly we can tell that we’re dealing with a script for Immunity Debugger, so if you move vm2x.py to Immunity’s PyCommands directory, you can execute the script using !vm2x

Luckily, python disassembly as produced by dis is quite easy to read, and as such we can fairly easy deduce the script’s logic:

  • Read 80 bytes from 4237456 (0x40A890) and store these in b:
    ‘123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x00′

  • If EIP equals 4273157 (0x413405), print b[29] + b[52] + b[69] + b[52] + b[65] + b[46] + b[68] + b[63]
  • If EIP equals 4278021 (0x414705), print b[46] + b[29] + b[02] + b[69] + b[02] + b[65] + b[46] + b[00] + b[61]

We don’t even need to run the executable to grab the 80 bytes; they are located in the .rdata section (simply ignore the EIP checks):

0x40A890 – 0x400000 (ImageBase) = 0xA890, the physical offset at which we find our bytes.

>>> b = '123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x00'
>>> b[29] + b[52] + b[69] + b[52] + b[65] + b[46] + b[68] + b[63]
'Never_up'
>>> b[46] + b[29] + b[02] + b[69] + b[02] + b[65] + b[46] + b[00] + b[61]
>>> '_N3v3r_1n'

Flag: Never_up_N3v3r_1n

Comments are closed.