/
DecompileFileCustom.py
111 lines (94 loc) · 4.07 KB
/
DecompileFileCustom.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#?description=Decompile a file provided to JEB
#?shortcut=
import os
import sys
import time
from java.util.regex import Pattern
from com.pnfsoftware.jeb.util.io import IO
from com.pnfsoftware.jeb.client.api import IScript, IGraphicalClientContext
from com.pnfsoftware.jeb.core.units import INativeCodeUnit, UnitUtil
from com.pnfsoftware.jeb.core.units.code import ICodeUnit, ICodeItem
from com.pnfsoftware.jeb.core.output.text import ITextDocument
from com.pnfsoftware.jeb.core.util import DecompilerHelper
from com.pnfsoftware.jeb.core.units.code.asm.decompiler import INativeSourceUnit
from com.pnfsoftware.jeb.core.units.code.android import IDexUnit, DexDecompilerExporter
from com.pnfsoftware.jeb.core.output.text import TextDocumentUtil
from com.pnfsoftware.jeb.util.base import ProgressCallbackAdapter
"""
Sample script for JEB Decompiler.
- This script decompiles all code units of the project
- If run on the command line, the provided input file will be analyzed
- It makes use of the 'decompiler exporter' objects to provide fast decompilation.
- The default settings (see below) is to decompile dex code only, not native code(s)
How to run (eg, on Windows):
$ jeb_wincon.bat -c --srv2 --script=DecompileFile.py -- INPUT_FILE OUTPUT_DIR
For additional details, refer to:
https://www.pnfsoftware.com/jeb/manual/faq/#can-i-execute-a-jeb-python-script-from-the-command-line
"""
class DecompileFileCustom(IScript):
def run(self, ctx):
print('Start decompilation...')
self.ctx = ctx
self.decompileDex = True
self.decompileNative = False
if not self.decompileDex and not self.decompileNative:
print('Warning! Both decompileDex and decompileNative are set to false. Adjust your script and run it again.')
return
if isinstance(ctx, IGraphicalClientContext):
self.outputDir = ctx.displayFolderSelector('Output folder')
if not self.outputDir:
print('Need an output folder')
return
else:
argv = ctx.getArguments()
if len(argv) < 2:
print('Provide an input file and the output folder')
return
inputFile = argv[0]
self.outputDir = argv[1]
print('Processing file: %s...' % inputFile)
ctx.open(inputFile)
prj = ctx.getMainProject()
assert prj, 'Need a project'
t0 = time.time()
for codeUnit in prj.findUnits(ICodeUnit):
# print(codeUnit)
self.decompileCodeUnit(codeUnit)
exectime = time.time() - t0
print('Exectime: %f' % exectime)
def decompileCodeUnit(self, codeUnit):
# make sure the code unit is processed
if not codeUnit.isProcessed():
if not codeUnit.process():
print('The code unit cannot be processed!')
return
decomp = DecompilerHelper.getDecompiler(codeUnit)
if not decomp:
print('There is no decompiler available for code unit %s' % codeUnit)
return
outdir = os.path.join(self.outputDir, codeUnit.getName() + '_decompiled')
print('Output folder: %s' % outdir) # created only if necessary, i.e. some contents was exported
if not((isinstance(codeUnit, INativeCodeUnit) and self.decompileNative) or (isinstance(codeUnit, IDexUnit) and self.decompileDex)):
print('Skipping code unit: %s' % UnitUtil.buildFullyQualifiedUnitPath(codeUnit))
return
# DecompilerExporter object
exp = decomp.getExporter()
exp.setOutputFolder(IO.createFolder(outdir))
# limit to 1 minute max per method
exp.setMethodTimeout(1 * 60000)
# limit to 15 minutes (total)
# exp.setTotalTimeout(2 * 60000)
pattern = Pattern.compile(".*/(cash|ali).*")
exp.setSignaturePattern(pattern)
# set a callback to output real-time information about what's being decompiled
class DecompCallback(ProgressCallbackAdapter):
def message(self, msg):
print('%d/%d: %s' % (self.getCurrent(), self.getTotal(), msg))
exp.setCallback(DecompCallback())
# decompile & export
if not exp.export(): # process
cnt = len(exp.getErrors())
i = 1
for sig, err in exp.getErrors().items():
print('%d/%d DECOMPILATION ERROR: METHOD %s: %s' % (i, cnt, sig, err))
i += 1