/
ObadDecrypt.py
executable file
·113 lines (92 loc) · 3.49 KB
/
ObadDecrypt.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
112
113
# JEB script - demo AST API
# Obad, Part 1: Decrypt Obad strings before performing unreflection
# See www.android-decompiler.com/blog
import sys
import os
import time
from jeb.api import IScript
from jeb.api import EngineOption
from jeb.api.ui import View
from jeb.api.dex import Dex
from jeb.api.ast import Class, Field, Method, Call, Constant, StaticField, NewArray
class ObadDecrypt(IScript):
def run(self, jeb):
self.jeb = jeb
self.dex = self.jeb.getDex()
self.cstbuilder = Constant.Builder(jeb)
self.csig = 'Lcom/android/system/admin/OclIIOlC;'
self.encbytes = []
self.mname_decrypt = None
# the encryption keys could be determined by analyzing the decryption method
self.keys = [33, 96, -2] # (added to 'length', added to 'curChar', delta)
r = jeb.decompileClass(self.csig)
if not r:
print 'Could not find class "%s"' % csig
return
c = jeb.getDecompiledClassTree(self.csig)
wanted_flags = Dex.ACC_PRIVATE|Dex.ACC_STATIC|Dex.ACC_FINAL
for f in c.getFields():
fsig = f.getSignature()
if fsig.endswith(':[B'):
fd = self.dex.getFieldData(fsig)
if fd.getAccessFlags() & wanted_flags == wanted_flags:
print 'Found field:', fsig
findex = fd.getFieldIndex()
for mindex in self.dex.getFieldReferences(findex):
mname = self.dex.getMethod(mindex).getName(False)
if mname != '':
self.mname_decrypt = mname
for m2 in c.getMethods():
if m2.getName() == '':
s0 = m2.getBody().get(0)
if isinstance(s0.getLeft(), StaticField) and s0.getLeft().getField().getSignature() == f.getSignature():
array = s0.getRight()
if isinstance(array, NewArray):
for v in array .getInitialValues():
self.encbytes.append(v.getByte())
break
break
if len(self.encbytes) == 0:
print 'Encrypted strings byte array not found'
return
if not self.mname_decrypt:
print 'Decryption method was not found'
return
for m in c.getMethods():
print 'Decrypting strings in method: %s' % m.getName()
self.decryptMethodStrings(m)
def decryptMethodStrings(self, m):
block = m.getBody()
i = 0
while i < block.size():
stm = block.get(i)
self.checkElement(block, stm)
i += 1
def checkElement(self, parent, e):
if isinstance(e, Call):
mname = e.getMethod().getName()
if mname == self.mname_decrypt:
v = []
for arg in e.getArguments():
if isinstance(arg, Constant):
v.append(arg.getInt())
if len(v) == 3:
decrypted_string = self.decrypt(v[2], v[0], v[1])
parent.replaceSubElement(e, self.cstbuilder.buildString(decrypted_string))
print ' Decrypted string: %s' % repr(decrypted_string)
for subelt in e.getSubElements():
if isinstance(subelt, Class) or isinstance(subelt, Field) or isinstance(subelt, Method):
continue
self.checkElement(e, subelt)
def decrypt(self, length, curChar, pos):
length += self.keys[0]
curChar += self.keys[1]
r = ''
for i in range(length):
r += chr(curChar & 0xFF)
if pos >= len(self.encbytes):
break
curEncodedChar = self.encbytes[pos]
pos += 1
curChar = curChar + curEncodedChar + self.keys[2]
return r