Tuesday 11 July 2017

Deobfuscating PjOrion using bytecode simplifier

Bytecode simplifier is a tool to de-obfuscate PjOrion protected python scripts. This post is a short tutorial to show how to use this module to deobfuscate a protected python script.

I have used the sample code below to demonstrate its usage. This is a small program to calculate the factorial of a number.

# Python program to find the factorial of a number using recursion
 
def recur_factorial(n):
   """Function to return the factorial
   of a number using recursion"""
   if n == 1:
       return n
   else:
       return n*recur_factorial(n-1)
 
 
# take input from the user
num = int(input("Enter a number: "))
 
# check is the number is negative
if num < 0:
   print("Sorry, factorial does not exist for negative numbers")
elif num == 0:
   print("The factorial of 0 is 1")
else:
   print("The factorial of",num,"is",recur_factorial(num))

I have first compiled the script and protected it as shown in Figure 1 & 2.

Compiling the script
Figure 1: Compiling the script
Figure 2: Protecting the generated pyc file
Figure 2: Protecting the generated pyc file
After protection, we get a large file example.pyc about 27 KiB in size. This is the file we will be working on.

The stock python interpreter does not have bytecode tracing facilities inbuilt. Hence we have to use a modified version of Python which supports bytecode tracing. I have provided a precompiled version of Python 2.7.13 with bytecode tracing support at Github. The python27.dll file has to be copied to  C:\Windows\System32\. Make sure to backup the existing dll so that you can revert when finished.

Step - 1: Unwrapping the layers


The first step is to unwrap the protection layers to get hold of the actual obfuscated code object. For this, we will be using the pjunwrapper module as shown below.

C:\pj-dump>python pjunwrapper.py --ifile=example.pyc
XXX lineno: 1, opcode: 156
[*] Dumped 1 code object
XXX lineno: 1, opcode: 213
XXX lineno: 1, opcode: 184
XXX lineno: 1, opcode: 240
XXX lineno: 1, opcode: 240
XXX lineno: 1, opcode: 240
XXX lineno: 1, opcode: 240
[*] Dumped 1 code object
XXX lineno: 1, opcode: 7
XXX lineno: 1, opcode: 45
[*] Dumped 1 code object
XXX lineno: 1, opcode: 161
Enter a number: ^D
Error in module '__main__': unexpected EOF while parsing (<string>, line 1)

PjUnwrapper requires the pystack extension module. Make sure that the extension is present in python path. Running this, some files having names of wrapper_ would be dumped. These are basically the wrapper layers over the actual obfuscated code. In our case, the obfuscated code has a file name wrapper_3.pyc as shown in Figure 3. In general, the highest numbered file contains the final obfuscated code.


Figure 3: Unwrapping the protection layers
Figure 3: Unwrapping the protection layers

Step - 2: Deobfuscating


The final step is to run bytecode_simplifier over wrapper_3.pyc as shown below.

C:\bytecode_simplifier\main.py --ifile=wrapper_3.pyc --ofile=wrapper_deobf.pyc
INFO:__main__:Opening file wrapper_3.pyc
INFO:__main__:Input pyc file header matched
DEBUG:__main__:Unmarshalling file
INFO:__main__:Processing code object \x0f\x1d\n\x00\x07\x0f\x0f
DEBUG:deobfuscator:Code entrypoint matched PjOrion signature v1
INFO:deobfuscator:Original code entrypoint at 269
INFO:deobfuscator:Starting control flow analysis...
DEBUG:disassembler:Finding leaders...
DEBUG:disassembler:Start leader at 269
DEBUG:disassembler:End leader at 272
DEBUG:disassembler:Start leader at 272
DEBUG:disassembler:End leader at 117
DEBUG:disassembler:Start leader at 117
DEBUG:disassembler:End leader at 82
DEBUG:disassembler:Start leader at 82
DEBUG:disassembler:End leader at 28
DEBUG:disassembler:Start leader at 28
DEBUG:disassembler:End leader at 177
DEBUG:disassembler:Start leader at 177
DEBUG:disassembler:End leader at 125
DEBUG:disassembler:Start leader at 125
DEBUG:disassembler:End leader at 155
DEBUG:disassembler:Start leader at 155
DEBUG:disassembler:End leader at 60
DEBUG:disassembler:Start leader at 60
DEBUG:disassembler:End leader at 165
DEBUG:disassembler:Start leader at 165
DEBUG:disassembler:End leader at 353
DEBUG:disassembler:Start leader at 353
DEBUG:disassembler:End leader at 303
DEBUG:disassembler:Start leader at 303
DEBUG:disassembler:End leader at 190
DEBUG:disassembler:Start leader at 190
DEBUG:disassembler:End leader at 235
DEBUG:disassembler:Start leader at 235
DEBUG:disassembler:Start leader at 235
DEBUG:disassembler:End leader at 51
DEBUG:disassembler:Start leader at 51
DEBUG:disassembler:End leader at 238
DEBUG:disassembler:Start leader at 238
DEBUG:disassembler:End leader at 313
DEBUG:disassembler:Start leader at 313
DEBUG:disassembler:End leader at 105
DEBUG:disassembler:Start leader at 105
DEBUG:disassembler:End leader at 246
DEBUG:disassembler:Start leader at 246
DEBUG:disassembler:End leader at 142
DEBUG:disassembler:Start leader at 142
DEBUG:disassembler:End leader at 71
DEBUG:disassembler:Start leader at 71
DEBUG:disassembler:End leader at 229
DEBUG:disassembler:Start leader at 229
DEBUG:disassembler:End leader at 33
DEBUG:disassembler:Start leader at 33
DEBUG:disassembler:Start leader at 33
DEBUG:disassembler:End leader at 44
DEBUG:disassembler:Start leader at 44
DEBUG:disassembler:End leader at 342
DEBUG:disassembler:Start leader at 342
DEBUG:disassembler:End leader at 36
DEBUG:disassembler:Start leader at 36
DEBUG:disassembler:End leader at 94
DEBUG:disassembler:Start leader at 94
DEBUG:disassembler:End leader at 17
DEBUG:disassembler:Start leader at 17
DEBUG:disassembler:End leader at 285
DEBUG:disassembler:Start leader at 285
DEBUG:disassembler:End leader at 295
DEBUG:disassembler:Start leader at 295
DEBUG:disassembler:End leader at 257
DEBUG:disassembler:Start leader at 257
DEBUG:disassembler:End leader at 197
DEBUG:disassembler:Start leader at 197
DEBUG:disassembler:End leader at 349
DEBUG:disassembler:End leader at 207
DEBUG:disassembler:Start leader at 207
DEBUG:disassembler:End leader at 361
DEBUG:disassembler:Start leader at 361
DEBUG:disassembler:End leader at 221
DEBUG:disassembler:Start leader at 221
DEBUG:disassembler:End leader at 332
DEBUG:disassembler:Start leader at 332
DEBUG:disassembler:End leader at 324
DEBUG:disassembler:Start leader at 324
DEBUG:disassembler:End leader at 134
DEBUG:disassembler:Start leader at 134
DEBUG:disassembler:End leader at 369
DEBUG:disassembler:Start leader at 369
DEBUG:disassembler:End leader at 6
DEBUG:disassembler:Start leader at 6
DEBUG:disassembler:End leader at 94
DEBUG:disassembler:Start leader at 94
DEBUG:disassembler:Found 81 leaders
DEBUG:disassembler:Constructing basic blocks...
DEBUG:disassembler:Creating basic block 0x24bd800 spanning from 5 to 6, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca558 spanning from 14 to 17, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca5d0 spanning from 25 to 28, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca648 spanning from 33 to 33, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca698 spanning from 36 to 36, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca6e8 spanning from 44 to 44, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca738 spanning from 51 to 51, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca788 spanning from 57 to 60, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca800 spanning from 68 to 71, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca878 spanning from 79 to 82, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca8f0 spanning from 93 to 94, end exclusive
DEBUG:disassembler:Creating basic block 0x24ca940 spanning from 94 to 94, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca990 spanning from 102 to 105, both inclusive
DEBUG:disassembler:Creating basic block 0x24caa30 spanning from 114 to 117, both inclusive
DEBUG:disassembler:Creating basic block 0x24caaf8 spanning from 122 to 125, both inclusive
DEBUG:disassembler:Creating basic block 0x24cabc0 spanning from 131 to 134, both inclusive
DEBUG:disassembler:Creating basic block 0x24cac88 spanning from 141 to 142, both inclusive
DEBUG:disassembler:Creating basic block 0x24cad50 spanning from 152 to 155, both inclusive
DEBUG:disassembler:Creating basic block 0x24cae18 spanning from 162 to 165, both inclusive
DEBUG:disassembler:Creating basic block 0x24caee0 spanning from 174 to 177, both inclusive
DEBUG:disassembler:Creating basic block 0x24cafa8 spanning from 187 to 190, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce0a8 spanning from 196 to 197, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce170 spanning from 204 to 207, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce238 spanning from 218 to 221, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce300 spanning from 228 to 229, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce3c8 spanning from 235 to 235, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce468 spanning from 238 to 238, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce508 spanning from 243 to 246, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce5d0 spanning from 254 to 257, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce698 spanning from 269 to 272, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce760 spanning from 282 to 285, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce828 spanning from 292 to 295, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce8f0 spanning from 300 to 303, both inclusive
DEBUG:disassembler:Creating basic block 0x24ce9b8 spanning from 310 to 313, both inclusive
DEBUG:disassembler:Creating basic block 0x24cea80 spanning from 321 to 324, both inclusive
DEBUG:disassembler:Creating basic block 0x24ceb48 spanning from 332 to 332, both inclusive
DEBUG:disassembler:Creating basic block 0x24cebe8 spanning from 342 to 342, both inclusive
DEBUG:disassembler:Creating basic block 0x24cec88 spanning from 349 to 349, both inclusive
DEBUG:disassembler:Creating basic block 0x24ced28 spanning from 350 to 353, both inclusive
DEBUG:disassembler:Creating basic block 0x24cedf0 spanning from 360 to 361, both inclusive
DEBUG:disassembler:Creating basic block 0x24ceeb8 spanning from 366 to 369, both inclusive
DEBUG:disassembler:41 basic blocks created
DEBUG:disassembler:Constructing edges between basic blocks...
DEBUG:disassembler:Adding explicit edge from block 0x24bd800 to 0x24ca8f0
DEBUG:disassembler:Adding explicit edge from block 0x24ca800 to 0x24ca648
DEBUG:disassembler:Adding explicit edge from block 0x24ce828 to 0x24cec88
DEBUG:disassembler:Adding explicit edge from block 0x24ca878 to 0x24ca5d0
DEBUG:disassembler:Adding explicit edge from block 0x24ce0a8 to 0x24cedf0
DEBUG:disassembler:Adding explicit edge from block 0x24ca940 to 0x24ce828
DEBUG:disassembler:Adding explicit edge from block 0x24ca6e8 to 0x24ca940
DEBUG:disassembler:Adding explicit edge from block 0x24ce170 to 0x24ce238
DEBUG:disassembler:Adding explicit edge from block 0x24ca990 to 0x24cac88
DEBUG:disassembler:Adding explicit edge from block 0x24ce9b8 to 0x24ce508
DEBUG:disassembler:Adding explicit edge from block 0x24caa30 to 0x24ca878
DEBUG:disassembler:Adding explicit edge from block 0x24cea80 to 0x24cabc0
DEBUG:disassembler:Adding explicit edge from block 0x24caaf8 to 0x24cad50
DEBUG:disassembler:Adding explicit edge from block 0x24ce300 to 0x24ca6e8
DEBUG:disassembler:Adding explicit edge from block 0x24ceb48 to 0x24ca940
DEBUG:disassembler:Adding implicit edge from block 0x24ce3c8 to 0x24ce468
DEBUG:disassembler:Adding explicit edge from block 0x24ce3c8 to 0x24ca738
DEBUG:disassembler:Adding explicit edge from block 0x24cabc0 to 0x24ceeb8
DEBUG:disassembler:Adding explicit edge from block 0x24cebe8 to 0x24ca558
DEBUG:disassembler:Adding explicit edge from block 0x24ce468 to 0x24ca990
DEBUG:disassembler:Adding explicit edge from block 0x24cac88 to 0x24ce300
DEBUG:disassembler:Adding explicit edge from block 0x24ce508 to 0x24ca800
DEBUG:disassembler:Adding explicit edge from block 0x24ced28 to 0x24ce8f0
DEBUG:disassembler:Adding explicit edge from block 0x24ce238 to 0x24cea80
DEBUG:disassembler:Adding explicit edge from block 0x24ca558 to 0x24ce5d0
DEBUG:disassembler:Adding explicit edge from block 0x24ce8f0 to 0x24cafa8
DEBUG:disassembler:Adding explicit edge from block 0x24ca5d0 to 0x24caee0
DEBUG:disassembler:Adding explicit edge from block 0x24ce5d0 to 0x24ce170
DEBUG:disassembler:Adding explicit edge from block 0x24cedf0 to 0x24ceb48
DEBUG:disassembler:Adding explicit edge from block 0x24cae18 to 0x24ced28
DEBUG:disassembler:Adding implicit edge from block 0x24ca648 to 0x24ca698
DEBUG:disassembler:Adding explicit edge from block 0x24ca648 to 0x24cebe8
DEBUG:disassembler:Adding explicit edge from block 0x24ca698 to 0x24ce760
DEBUG:disassembler:Adding explicit edge from block 0x24ceeb8 to 0x24bd800
DEBUG:disassembler:Adding explicit edge from block 0x24caee0 to 0x24caaf8
DEBUG:disassembler:Adding explicit edge from block 0x24ca738 to 0x24ce9b8
DEBUG:disassembler:Adding explicit edge from block 0x24ce760 to 0x24ce0a8
DEBUG:disassembler:Adding explicit edge from block 0x24ce698 to 0x24caa30
DEBUG:disassembler:Adding explicit edge from block 0x24ca788 to 0x24cae18
DEBUG:disassembler:Adding explicit edge from block 0x24cafa8 to 0x24ce3c8
DEBUG:disassembler:Adding explicit edge from block 0x24cad50 to 0x24ca788
INFO:deobfuscator:Control flow analysis completed.
INFO:deobfuscator:Starting simplication of basic blocks...
DEBUG:simplifier:Eliminating forwarders...
INFO:simplifier:Adding explicit edge from block 0x24ceb48 to 0x24ce828
INFO:simplifier:Adding explicit edge from block 0x24ca6e8 to 0x24ce828
INFO:simplifier:Adding implicit edge from block 0x24ca8f0 to 0x24ce828
DEBUG:simplifier:Forwarder basic block 0x24ca940 eliminated
INFO:simplifier:Adding explicit edge from block 0x24ce300 to 0x24ce828
DEBUG:simplifier:Forwarder basic block 0x24ca6e8 eliminated
INFO:simplifier:Adding explicit edge from block 0x24cedf0 to 0x24ce828
DEBUG:simplifier:Forwarder basic block 0x24ceb48 eliminated
INFO:simplifier:Adding explicit edge from block 0x24ca648 to 0x24ca558
DEBUG:simplifier:Forwarder basic block 0x24cebe8 eliminated
INFO:simplifier:Adding implicit edge from block 0x24ce3c8 to 0x24ca990
DEBUG:simplifier:Forwarder basic block 0x24ce468 eliminated
INFO:simplifier:Adding implicit edge from block 0x24ca648 to 0x24ce760
DEBUG:simplifier:Forwarder basic block 0x24ca698 eliminated
INFO:simplifier:Adding explicit edge from block 0x24ce3c8 to 0x24ce9b8
DEBUG:simplifier:Forwarder basic block 0x24ca738 eliminated
INFO:simplifier:7 basic blocks eliminated
DEBUG:simplifier:Merging basic blocks...
INFO:simplifier:Adding explicit edge from block 0x24ceeb8 to 0x24ca8f0
DEBUG:simplifier:Basic block 0x24bd800 merged with block 0x24ceeb8
INFO:simplifier:Adding explicit edge from block 0x24ce508 to 0x24ca648
DEBUG:simplifier:Basic block 0x24ca800 merged with block 0x24ce508
INFO:simplifier:Adding explicit edge from block 0x24caa30 to 0x24ca5d0
DEBUG:simplifier:Basic block 0x24ca878 merged with block 0x24caa30
INFO:simplifier:Adding explicit edge from block 0x24ce760 to 0x24cedf0
DEBUG:simplifier:Basic block 0x24ce0a8 merged with block 0x24ce760
INFO:simplifier:Adding implicit edge from block 0x24ceeb8 to 0x24ce828
DEBUG:simplifier:Basic block 0x24ca8f0 merged with block 0x24ceeb8
INFO:simplifier:Adding explicit edge from block 0x24ce5d0 to 0x24ce238
DEBUG:simplifier:Basic block 0x24ce170 merged with block 0x24ce5d0
INFO:simplifier:Adding explicit edge from block 0x24ce698 to 0x24ca5d0
DEBUG:simplifier:Basic block 0x24caa30 merged with block 0x24ce698
INFO:simplifier:Adding explicit edge from block 0x24ce238 to 0x24cabc0
DEBUG:simplifier:Basic block 0x24cea80 merged with block 0x24ce238
INFO:simplifier:Adding explicit edge from block 0x24caee0 to 0x24cad50
DEBUG:simplifier:Basic block 0x24caaf8 merged with block 0x24caee0
INFO:simplifier:Adding explicit edge from block 0x24cac88 to 0x24ce828
DEBUG:simplifier:Basic block 0x24ce300 merged with block 0x24cac88
DEBUG:simplifier:Basic block 0x24cec88 merged with block 0x24ce828
INFO:simplifier:Adding implicit edge from block 0x24cafa8 to 0x24ca990
INFO:simplifier:Adding explicit edge from block 0x24cafa8 to 0x24ce9b8
DEBUG:simplifier:Basic block 0x24ce3c8 merged with block 0x24cafa8
INFO:simplifier:Adding explicit edge from block 0x24ce238 to 0x24ceeb8
DEBUG:simplifier:Basic block 0x24cabc0 merged with block 0x24ce238
INFO:simplifier:Adding explicit edge from block 0x24ca990 to 0x24ce828
DEBUG:simplifier:Basic block 0x24cac88 merged with block 0x24ca990
INFO:simplifier:Adding explicit edge from block 0x24ce9b8 to 0x24ca648
DEBUG:simplifier:Basic block 0x24ce508 merged with block 0x24ce9b8
INFO:simplifier:Adding explicit edge from block 0x24cae18 to 0x24ce8f0
DEBUG:simplifier:Basic block 0x24ced28 merged with block 0x24cae18
INFO:simplifier:Adding explicit edge from block 0x24ce5d0 to 0x24ceeb8
DEBUG:simplifier:Basic block 0x24ce238 merged with block 0x24ce5d0
INFO:simplifier:Adding explicit edge from block 0x24cae18 to 0x24cafa8
DEBUG:simplifier:Basic block 0x24ce8f0 merged with block 0x24cae18
INFO:simplifier:Adding explicit edge from block 0x24ce698 to 0x24caee0
DEBUG:simplifier:Basic block 0x24ca5d0 merged with block 0x24ce698
INFO:simplifier:Adding explicit edge from block 0x24ca558 to 0x24ceeb8
DEBUG:simplifier:Basic block 0x24ce5d0 merged with block 0x24ca558
INFO:simplifier:Adding explicit edge from block 0x24ce760 to 0x24ce828
DEBUG:simplifier:Basic block 0x24cedf0 merged with block 0x24ce760
INFO:simplifier:Adding explicit edge from block 0x24ca788 to 0x24cafa8
DEBUG:simplifier:Basic block 0x24cae18 merged with block 0x24ca788
INFO:simplifier:Adding explicit edge from block 0x24ce9b8 to 0x24ca558
INFO:simplifier:Adding implicit edge from block 0x24ce9b8 to 0x24ce760
DEBUG:simplifier:Basic block 0x24ca648 merged with block 0x24ce9b8
INFO:simplifier:Adding implicit edge from block 0x24ca558 to 0x24ce828
DEBUG:simplifier:Basic block 0x24ceeb8 merged with block 0x24ca558
INFO:simplifier:Adding explicit edge from block 0x24ce698 to 0x24cad50
DEBUG:simplifier:Basic block 0x24caee0 merged with block 0x24ce698
INFO:simplifier:Adding explicit edge from block 0x24cad50 to 0x24cafa8
DEBUG:simplifier:Basic block 0x24ca788 merged with block 0x24cad50
INFO:simplifier:Adding implicit edge from block 0x24cad50 to 0x24ca990
INFO:simplifier:Adding explicit edge from block 0x24cad50 to 0x24ce9b8
DEBUG:simplifier:Basic block 0x24cafa8 merged with block 0x24cad50
INFO:simplifier:Adding implicit edge from block 0x24ce698 to 0x24ca990
INFO:simplifier:Adding explicit edge from block 0x24ce698 to 0x24ce9b8
DEBUG:simplifier:Basic block 0x24cad50 merged with block 0x24ce698
INFO:simplifier:28 basic blocks merged.
INFO:deobfuscator:Simplication of basic blocks completed.
INFO:deobfuscator:Beginning verification of simplified basic block graph...
INFO:deobfuscator:Verification succeeded.
INFO:deobfuscator:Assembling basic blocks...
DEBUG:assembler:Performing a DFS on the graph to generate the layout of the blocks.
DEBUG:assembler:Morphing some JUMP_ABSOLUTE instructions to make file decompilable.
DEBUG:assembler:Verifying generated layout...
DEBUG:assembler:Successfully verified layout.
DEBUG:assembler:Calculating addresses of basic blocks.
DEBUG:assembler:Calculating instruction operands.
DEBUG:assembler:Generating code...
INFO:deobfuscator:Successfully assembled. 
INFO:__main__:Successfully deobfuscated code object \x0f\x1d\n\x00\x07\x0f\x0f
INFO:__main__:Collecting constants for code object \x0f\x1d\n\x00\x07\x0f\x0f
INFO:__main__:Code object \x0f\x1d\n\x00\x07\x0f\x0f contains embedded code object recur_factorial
INFO:__main__:Processing code object recur_factorial
DEBUG:deobfuscator:Code entrypoint matched PjOrion signature v2
INFO:deobfuscator:Original code entrypoint at 161
INFO:deobfuscator:Starting control flow analysis...
DEBUG:disassembler:Finding leaders...
DEBUG:disassembler:Start leader at 161
DEBUG:disassembler:End leader at 164
DEBUG:disassembler:Start leader at 164
DEBUG:disassembler:End leader at 46
DEBUG:disassembler:Start leader at 46
DEBUG:disassembler:End leader at 141
DEBUG:disassembler:Start leader at 141
DEBUG:disassembler:End leader at 19
DEBUG:disassembler:Start leader at 19
DEBUG:disassembler:Start leader at 19
DEBUG:disassembler:End leader at 127
DEBUG:disassembler:Start leader at 127
DEBUG:disassembler:End leader at 22
DEBUG:disassembler:Start leader at 22
DEBUG:disassembler:End leader at 66
DEBUG:disassembler:Start leader at 66
DEBUG:disassembler:End leader at 105
DEBUG:disassembler:Start leader at 105
DEBUG:disassembler:End leader at 87
DEBUG:disassembler:Start leader at 87
DEBUG:disassembler:End leader at 126
DEBUG:disassembler:End leader at 154
DEBUG:disassembler:Start leader at 154
DEBUG:disassembler:End leader at 113
DEBUG:disassembler:Start leader at 113
DEBUG:disassembler:End leader at 93
DEBUG:disassembler:Start leader at 93
DEBUG:disassembler:End leader at 34
DEBUG:disassembler:Start leader at 34
DEBUG:disassembler:End leader at 11
DEBUG:disassembler:Start leader at 11
DEBUG:disassembler:End leader at 53
DEBUG:disassembler:Found 32 leaders
DEBUG:disassembler:Constructing basic blocks...
DEBUG:disassembler:Creating basic block 0x24ce3a0 spanning from 10 to 11, both inclusive
DEBUG:disassembler:Creating basic block 0x24bddc8 spanning from 19 to 19, both inclusive
DEBUG:disassembler:Creating basic block 0x24bda30 spanning from 22 to 22, both inclusive
DEBUG:disassembler:Creating basic block 0x24bdad0 spanning from 31 to 34, both inclusive
DEBUG:disassembler:Creating basic block 0x24bd9b8 spanning from 43 to 46, both inclusive
DEBUG:disassembler:Creating basic block 0x24bde68 spanning from 53 to 53, both inclusive
DEBUG:disassembler:Creating basic block 0x24bdc10 spanning from 63 to 66, both inclusive
DEBUG:disassembler:Creating basic block 0x24bdcb0 spanning from 84 to 87, both inclusive
DEBUG:disassembler:Creating basic block 0x24bd7d8 spanning from 92 to 93, both inclusive
DEBUG:disassembler:Creating basic block 0x24bdb98 spanning from 102 to 105, both inclusive
DEBUG:disassembler:Creating basic block 0x24bdf58 spanning from 110 to 113, both inclusive
DEBUG:disassembler:Creating basic block 0x24bdb48 spanning from 126 to 126, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca8a0 spanning from 127 to 127, both inclusive
DEBUG:disassembler:Creating basic block 0x24caf58 spanning from 138 to 141, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca7b0 spanning from 151 to 154, both inclusive
DEBUG:disassembler:Creating basic block 0x24ca670 spanning from 161 to 164, both inclusive
DEBUG:disassembler:16 basic blocks created
DEBUG:disassembler:Constructing edges between basic blocks...
DEBUG:disassembler:Adding explicit edge from block 0x24bdc10 to 0x24bdcb0
DEBUG:disassembler:Adding explicit edge from block 0x24ca7b0 to 0x24bdf58
DEBUG:disassembler:Adding explicit edge from block 0x24bda30 to 0x24bdb98
DEBUG:disassembler:Adding explicit edge from block 0x24ca670 to 0x24bd9b8
DEBUG:disassembler:Adding explicit edge from block 0x24ca8a0 to 0x24bdc10
DEBUG:disassembler:Adding explicit edge from block 0x24bdcb0 to 0x24ca7b0
DEBUG:disassembler:Adding explicit edge from block 0x24bdad0 to 0x24ce3a0
DEBUG:disassembler:Adding explicit edge from block 0x24bdf58 to 0x24bd7d8
DEBUG:disassembler:Adding explicit edge from block 0x24bdb98 to 0x24bdb48
DEBUG:disassembler:Adding explicit edge from block 0x24ce3a0 to 0x24bde68
DEBUG:disassembler:Adding explicit edge from block 0x24bd9b8 to 0x24caf58
DEBUG:disassembler:Adding implicit edge from block 0x24bddc8 to 0x24bda30
DEBUG:disassembler:Adding explicit edge from block 0x24bddc8 to 0x24ca8a0
DEBUG:disassembler:Adding explicit edge from block 0x24bd7d8 to 0x24bdad0
DEBUG:disassembler:Adding explicit edge from block 0x24caf58 to 0x24bddc8
INFO:deobfuscator:Control flow analysis completed.
INFO:deobfuscator:Starting simplication of basic blocks...
DEBUG:simplifier:Eliminating forwarders...
INFO:simplifier:Adding implicit edge from block 0x24bddc8 to 0x24bdb98
DEBUG:simplifier:Forwarder basic block 0x24bda30 eliminated
INFO:simplifier:Adding explicit edge from block 0x24bddc8 to 0x24bdc10
DEBUG:simplifier:Forwarder basic block 0x24ca8a0 eliminated
INFO:simplifier:2 basic blocks eliminated
DEBUG:simplifier:Merging basic blocks...
INFO:simplifier:Adding explicit edge from block 0x24bdcb0 to 0x24bdf58
DEBUG:simplifier:Basic block 0x24ca7b0 merged with block 0x24bdcb0
DEBUG:simplifier:Basic block 0x24bde68 merged with block 0x24ce3a0
INFO:simplifier:Adding explicit edge from block 0x24bdc10 to 0x24bdf58
DEBUG:simplifier:Basic block 0x24bdcb0 merged with block 0x24bdc10
INFO:simplifier:Adding explicit edge from block 0x24bd7d8 to 0x24ce3a0
DEBUG:simplifier:Basic block 0x24bdad0 merged with block 0x24bd7d8
DEBUG:simplifier:Basic block 0x24bdb48 merged with block 0x24bdb98
INFO:simplifier:Adding explicit edge from block 0x24bdc10 to 0x24bd7d8
DEBUG:simplifier:Basic block 0x24bdf58 merged with block 0x24bdc10
DEBUG:simplifier:Basic block 0x24ce3a0 merged with block 0x24bd7d8
INFO:simplifier:Adding explicit edge from block 0x24ca670 to 0x24caf58
DEBUG:simplifier:Basic block 0x24bd9b8 merged with block 0x24ca670
INFO:simplifier:Adding implicit edge from block 0x24caf58 to 0x24bdb98
INFO:simplifier:Adding explicit edge from block 0x24caf58 to 0x24bdc10
DEBUG:simplifier:Basic block 0x24bddc8 merged with block 0x24caf58
DEBUG:simplifier:Basic block 0x24bd7d8 merged with block 0x24bdc10
INFO:simplifier:Adding implicit edge from block 0x24ca670 to 0x24bdb98
INFO:simplifier:Adding explicit edge from block 0x24ca670 to 0x24bdc10
DEBUG:simplifier:Basic block 0x24caf58 merged with block 0x24ca670
INFO:simplifier:11 basic blocks merged.
INFO:deobfuscator:Simplication of basic blocks completed.
INFO:deobfuscator:Beginning verification of simplified basic block graph...
INFO:deobfuscator:Verification succeeded.
INFO:deobfuscator:Assembling basic blocks...
DEBUG:assembler:Performing a DFS on the graph to generate the layout of the blocks.
DEBUG:assembler:Morphing some JUMP_ABSOLUTE instructions to make file decompilable.
DEBUG:assembler:Verifying generated layout...
DEBUG:assembler:Successfully verified layout.
DEBUG:assembler:Calculating addresses of basic blocks.
DEBUG:assembler:Calculating instruction operands.
DEBUG:assembler:Generating code...
INFO:deobfuscator:Successfully assembled. 
INFO:__main__:Successfully deobfuscated code object recur_factorial
INFO:__main__:Collecting constants for code object recur_factorial
INFO:__main__:Generating new code object for recur_factorial
INFO:__main__:Generating new code object for \x0f\x1d\n\x00\x07\x0f\x0f
INFO:__main__:Writing deobfuscated code object to disk
INFO:__main__:Success

Running this we get back the deobfuscated code in the file wrapper_deobf.pyc. We can now run a python decompiler on this to get back our deobfuscated code as shown in Figure 4.

Figure 4: Decompiling the deobfuscated code
Figure 4: Decompiling the deobfuscated code

34 comments:

  1. Please record video and send mee , pishey16@gmail.com
    If you send me video tutioral, i sent you 200$

    ReplyDelete
    Replies
    1. Thanks for the comment but I do not plan to make a video at the moment. You can here write here in comments where you are stuck.

      Delete
  2. AnonymousJuly 17, 2017

    Stuck on Step one. What I'm I doing wrong.

    C:\PJOrion\Deobfuscate\pjunwrapper-master>python pjunwrapper.py --ifile=mod_updater.pyc
    XXX lineno: 1, opcode: 206
    [*] Dumped 1 code object
    XXX lineno: 1, opcode: 8
    XXX lineno: 1, opcode: 247
    Traceback (most recent call last):
    File "pjunwrapper.py", line 57, in
    eval(co)
    File "mod_updater", line 1, in
    File "mod_updater", line 1, in
    File "mod_updater", line 1, in

    ImportError: No module named BigWorld

    ReplyDelete
    Replies
    1. The script is protected using "Exec only in WOT" mode. For the moment you have to make sure that the script can import BigWorld module. Later I plan to figure out some way to fake the presence of that said module which will alleviate the need for this.

      Delete
    2. How do you import the BigWorld module to get round the"ImportError: No module named BigWorld" error?

      Thanks

      Delete
    3. Maybe it is will help https://github.com/jhakonen/wot-teamspeak-mod/blob/master/futes/fakes/BigWorld.py

      Delete
    4. Yes, I am aware of the wot-teamspeak-mod. However it needs some changes to be useful.

      Delete
  3. AnonymousJuly 20, 2017

    INFO:simplifier:564 basic blocks merged.
    INFO:deobfuscator:Simplification of basic blocks completed.
    INFO:deobfuscator:Beginning verification of simplified basic block graph...
    INFO:deobfuscator:Verification succeeded.
    INFO:deobfuscator:Assembling basic blocks...
    DEBUG:assembler:Performing a DFS on the graph to generate the layout of the blocks.
    DEBUG:assembler:Morphing some JUMP_ABSOLUTE instructions to make file decompilable.
    DEBUG:assembler:Verifying generated layout...
    INFO:assembler:Basic block 0x34e7648 uses a relative control transfer instruction to access block 0x34e7f08 located before it.
    INFO:assembler:Basic block 0x303cb98 uses a relative control transfer instruction to access block 0x40865f8 located before it.
    INFO:assembler:Basic block 0x3f44468 uses a relative control transfer instruction to access block 0x34ec080 located before it.
    DEBUG:assembler:Successfully verified layout.
    DEBUG:assembler:Calculating addresses of basic blocks.
    DEBUG:assembler:Calculating instruction operands.
    DEBUG:assembler:Generating code...
    INFO:deobfuscator:Successfully assembled.
    INFO:__main__:Successfully deobfuscated code object \x11\x06\x11\x0f\x19\x0e
    INFO:__main__:Collecting constants for code object \x11\x06\x11\x0f\x19\x0e
    INFO:__main__:Generating new code object for \x11\x06\x11\x0f\x19\x0e
    INFO:__main__:Code object \x17\x1b\x11\x17\x18\x16\x1b contains embedded code object 6q:s{~~h
    INFO:__main__:Processing code object 6q:s{~~h
    DEBUG:deobfuscator:Code entrypoint matched PjOrion signature v2
    INFO:deobfuscator:Original code entrypoint at 22037
    INFO:deobfuscator:Starting control flow analysis...
    DEBUG:disassembler:Finding leaders...
    DEBUG:disassembler:Start leader at 22037
    Traceback (most recent call last):
    File "main.py", line 72, in
    process(args.ifile, args.ofile)
    File "main.py", line 58, in process
    deob = parse_code_object(rootCodeObject)
    File "main.py", line 37, in parse_code_object
    mod_const.append(parse_code_object(const))
    File "main.py", line 37, in parse_code_object
    mod_const.append(parse_code_object(const))
    File "main.py", line 20, in parse_code_object
    co_codestring = deobfuscate(codeObject.co_code)
    File "C:\Python27\prog\bytecode_simplifier-master\deobfuscator.py", line 67, in deobfuscate
    disasm.find_leaders()
    File "C:\Python27\prog\bytecode_simplifier-master\disassembler.py", line 118, in find_leaders
    ins = dec.decode_at(addr)
    File "C:\Python27\prog\bytecode_simplifier-master\decoder.py", line 15, in decode_at
    assert offset < len(self.insBytes)
    AssertionError

    ReplyDelete
  4. AnonymousJuly 21, 2017

    pjunwrapper not working with pjorion 1.3.3

    ReplyDelete
  5. File "pjunwrapper.py", line 39, in trace
    marshal.dump(pystack.getStackItem(frame, 2), f)
    AttributeError: 'module' object has no attribute 'getStackItem'

    ReplyDelete
    Replies
    1. fixed

      but now I got this:

      F:\pjunwrapper-master>python pjunwrapper.py --ifile=mod.pyc
      XXX lineno: 1, opcode: 187
      XXX lineno: 1, opcode: 241
      XXX lineno: 1, opcode: 18

      F:\pjunwrapper-master>

      Delete
    2. This comment has been removed by the author.

      Delete
  6. Hey,
    Will I be able to do all this in Linux? I saw there is a requirement for some WoT library (BigWorld), I guess it's a python (i.e. cross-platform) library right? Which means I would be able to just it over from Windows

    ReplyDelete
  7. Hi,
    another anonymous, same problem: no module named BigWorld.
    Am I right to assume that the only way to overcome this currently would be to buy a license of the BigWorld engine? - Or could there be some magic trick with the game running in the background (sorry for the ignorant question, its just a desperate guess)? Thanks.

    ReplyDelete
    Replies
    1. I don't think a license of BigWorld is required. At runtime, PjOrion checks for the existence of BigWorld module before processing. So, it should be possible to create a fake BigWorld module to pass the check. Finding out how to do this is on my agenda, but again there are no promises when.

      In case you decide to have a look, note that the check is a bit more deep than just checking for the module's existence. You may need to create some fake variables, classes, functions etc in the fake module to successfully override the check.

      Delete
  8. python pjunwrapper.py --ifile=mod.pyc
    [*] Dumped 1 code object
    Traceback (most recent call last):
    File "pjunwrapper.py", line 57, in
    eval(co)
    File "hru-hru", line 2, in
    File "hru-hru", line 10, in
    File "hru-hru", line 14, in
    File "hru-hru", line 16, in
    File "hru-hru", line 5, in
    File "hru-hru", line 55, in
    File "hru-hru", line 55, in
    File "hru-hru", line 55, in
    File "hru-hru", line 55, in
    File "hru-hru", line 55, in
    ImportError: No module named BigWorld

    ReplyDelete
  9. I encountered the following error
    'pystack' has no 'getStackItem' member
    Please tell me which module to install?
    i just run pip install pystack

    ReplyDelete
    Replies
    1. pystack isn't available on PyPI. It's available at GitHub
      https://github.com/extremecoders-re/pystack

      Delete
    2. thank u

      Delete
  10. So, is there a trick to import BigWorld module in the script?
    It's sad to see this work stay as a proof of concept and not be able to use it for it's original purpose: deobfuscating pjorion protected wot mods...
    Any help would be much apreciated :)

    ReplyDelete
  11. I'm getting this error..

    I've installed the .pyd in "C:\Python27\Lib\site-packages" like I've seen to do online and I'm getting that error below. Any help is appreciated :)

    Error in module '__main__': No module named ResMgr

    ReplyDelete
  12. AnonymousJune 14, 2018

    Are there any news on the "BigWorld module" problem?
    I would really love to have the possibility to deobfuscate WoT mods.

    Thanks in advance!

    ReplyDelete
  13. Hello, I followed what you said and I almost succeed until I faced with this problem, can you suggest me any solution or idea about what to do ?

    INFO:deobfuscator:Successfully assembled.
    INFO:__main__:Successfully deobfuscated code object \x02\x16\x1f\r\x1b\x10\x0c\x01\x0f\x13\x10
    INFO:__main__:Collecting constants for code object \x02\x16\x1f\r\x1b\x10\x0c\x01\x0f\x13\x10
    INFO:__main__:Generating new code object for \x02\x16\x1f\r\x1b\x10\x0c\x01\x0f\x13\x10
    INFO:__main__:Code object \x18\r\x02\x05\x19\x0e\x18 contains embedded code object r7p~t#t{
    INFO:__main__:Processing code object r7p~t#t{
    WARNING:deobfuscator:Code entrypoint did not match PjOrion signature
    INFO:deobfuscator:Original code entrypoint at 0
    INFO:deobfuscator:Starting control flow analysis...
    DEBUG:disassembler:Finding leaders...
    DEBUG:disassembler:Start leader at 0
    DEBUG:disassembler:End leader at 0
    DEBUG:disassembler:Start leader at 0
    DEBUG:disassembler:Start leader at 0
    Traceback (most recent call last):
    File "C:\Users\me\Desktop\bytecode_simplifier-master\main.py", line 72, in
    process(args.ifile, args.ofile)
    File "C:\Users\me\Desktop\bytecode_simplifier-master\main.py", line 58, in process
    deob = parse_code_object(rootCodeObject)
    File "C:\Users\me\Desktop\bytecode_simplifier-master\main.py", line 37, in parse_code_object
    mod_const.append(parse_code_object(const))
    File "C:\Users\me\Desktop\bytecode_simplifier-master\main.py", line 37, in parse_code_object
    mod_const.append(parse_code_object(const))
    File "C:\Users\me\Desktop\bytecode_simplifier-master\main.py", line 20, in parse_code_object
    co_codestring = deobfuscate(codeObject.co_code)
    File "C:\Users\me\Desktop\bytecode_simplifier-master\deobfuscator.py", line 67, in deobfuscate
    disasm.find_leaders()
    File "C:\Users\me\Desktop\bytecode_simplifier-master\disassembler.py", line 118, in find_leaders
    ins = dec.decode_at(addr)
    File "C:\Users\me\Desktop\bytecode_simplifier-master\decoder.py", line 15, in decode_at
    assert offset < len(self.insBytes)
    AssertionError

    ReplyDelete
  14. How to fix it?

    ReplyDelete
  15. >>> import pystack

    Traceback (most recent call last):
    File "", line 1, in
    import pystack
    ImportError: DLL load failed: %1 не является приложением Win32.


    How to fix it?

    ReplyDelete
  16. Thanks for this blog post!

    Though I've question, I get error "application was unable to start correctly (0xc0000007b)" when launching python after replacing python27.dll with yours. Why does this happen?

    ReplyDelete
    Replies
    1. Ok I resolved this error by installing 32bit python. Now I can launch modified python but pjunrwapper doesnt work at all, no errors, but it doesnt generate files

      Delete
    2. Talking to myself yah, fixed this too on 64bit win10 machine by moving Author's DLL into SysWOW64 folder instead of System32

      Delete
  17. .......
    .......
    .......
    DEBUG:assembler:Calculating addresses of basic blocks.
    DEBUG:assembler:Calculating instruction operands.
    DEBUG:assembler:Generating code...
    INFO:deobfuscator:Successfully assembled.
    INFO:__main__:Successfully deobfuscated code object \x08\x00\x11\x1d
    INFO:__main__:Collecting constants for code object \x08\x00\x11\x1d
    INFO:__main__:Generating new code object for \x08\x00\x11\x1d
    INFO:__main__:Code object \x07\x07\x01\x16\x02\x1a\x19 contains embedded code ob
    ject .y-s1y7#
    INFO:__main__:Processing code object .y-s1y7#
    DEBUG:deobfuscator:Code entrypoint matched PjOrion signature v2
    INFO:deobfuscator:Original code entrypoint at 23069
    INFO:deobfuscator:Starting control flow analysis...
    DEBUG:disassembler:Finding leaders...
    DEBUG:disassembler:Start leader at 23069
    Traceback (most recent call last):
    File "main.py", line 72, in
    process(args.ifile, args.ofile)
    File "main.py", line 58, in process
    deob = parse_code_object(rootCodeObject)
    File "main.py", line 37, in parse_code_object
    mod_const.append(parse_code_object(const))
    File "main.py", line 37, in parse_code_object
    mod_const.append(parse_code_object(const))
    File "main.py", line 20, in parse_code_object
    co_codestring = deobfuscate(codeObject.co_code)
    File "C:\Python27\deobfuscator.py", line 67, in deobfuscate
    disasm.find_leaders()
    File "C:\Python27\disassembler.py", line 118, in find_leaders
    ins = dec.decode_at(addr)
    File "C:\Python27\decoder.py", line 15, in decode_at
    assert offset < len(self.insBytes)
    AssertionError

    ---------------------------
    how to fix the error ???
    ---------------------------

    ReplyDelete
  18. This comment has been removed by the author.

    ReplyDelete
  19. excatly the same to me!

    also error message

    ImportError: No module named ResMgr

    arise some time

    ============================================================
    Are there any news on the "BigWorld module" problem?
    I would really love to have the possibility to deobfuscate WoT mods.

    Thanks in advance!

    ReplyDelete
  20. I can't get past this error > Traceback (most recent call last):
    File "C:\Users\Owner\Downloads\Telegram Desktop\bytecode_simplifier-master\bytecode_simplifier-master\pjunwrapper.py", line 54, in
    co=marshal.load(f) ValueError: bad marshal data (unknown type code).

    I've pip installed setuptools still no avail. Running Python 3.9 on Win 10. Any help will be appreciated. Thank you!

    ReplyDelete
  21. Can someone help me deobfuscate just one .pyc file please? This is too techy for me and the learning curve to get this done is too steep at this point. Let me know where to send it and I'll quickly respond. Thanks in advance!

    ReplyDelete