-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathnum2name.py
executable file
·157 lines (129 loc) · 5.18 KB
/
num2name.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env python
__author__ = '[email protected]'
import re
import os
import sys
from common import Smali
from common import Java
from common import File
from common import AccessSmali
from common import Method
from common import DataFile
# method pattern
patternMethodBegin = re.compile(r'\.method static synthetic access\$(?P<accessnum>\d+)\((?P<parameterlist>.*?)\)(?P<returntype>.*?)\s', re.S)
patternMethodAnnotation = re.compile(r' *\.| *$', re.S)
patternMethodCall = re.compile(r'\s*(?P<operation>iput|iget|sput|sget|aput|aget|invoke).*? (?P<classname>L.*?);->(?P<operationobject>.*?)(:|\(.*\))', re.S)
patternMethodEnd = re.compile(r'\.end method', re.S)
class NumToName:
def __init__(self, name, path, smaliList):
self.name = name
self.path = path
self.smaliList = smaliList
self.accessSmaliSet = {}
self.getAccessSmaliSet()
def getAccessSmaliSet(self):
""" check smalilist to build access num to name map """
for s in self.smaliList:
sName = Smali.getSmaliName(s)
aSmali = AccessSmali(sName)
mode = 0
method = ""
for line in open(os.path.join(self.path, s), 'r'):
if (mode == 0):
match = patternMethodBegin.match(line)
if(match):
method = Method(match.group("accessnum"), match.group("parameterlist"), match.group("returntype"))
mode = 1
elif (mode == 1):
match = patternMethodEnd.match(line)
if(match):
method.endMethod()
mode = 0
aSmali.addMethod(method.accessNum, method.accessName)
else:
match = patternMethodAnnotation.match(line)
if(match):
continue
match = patternMethodCall.match(line)
if(match):
method.addCallLine(match.group("operation"), match.group("operationobject"), match.group(0))
else:
method.addMethodLine(line)
if (aSmali.getMethodNumSetLen() > 0):
aSmali.createNumMap()
self.accessSmaliSet[sName] = aSmali
def printAccessSmaliSet(self):
for sName in self.accessSmaliSet.keys():
self.accessSmaliSet[sName].printMethodNumSet()
def doNumToName(self):
allMethodCallNumMap = {}
for sName in self.accessSmaliSet.keys():
callNumMap = self.accessSmaliSet[sName].methodCallNumMap
for callNum in callNumMap.keys():
if callNum not in allMethodCallNumMap.keys():
allMethodCallNumMap[callNum] = callNumMap[callNum]
else:
raise ValueError("method call num map duplicate")
for s in self.smaliList:
sFile = File(os.path.join(self.path, s))
sName = Smali.getSmaliName(s)
if sName in self.accessSmaliSet.keys():
sFile.replaces(self.accessSmaliSet[sName].methodDefNumMap)
sFile.replaces(allMethodCallNumMap)
def dumpMap(self):
"""
smalirootname.data:
smaliname accessname accessnum
"""
dumpStr = ""
for sName in self.accessSmaliSet.keys():
nameSet = self.accessSmaliSet[sName].methodNameSet
for name in nameSet.keys():
dumpStr=(dumpStr+sName+" "+name+" "+nameSet[name]+"\n")
File(os.path.join(self.path, self.name+".data")).dump(dumpStr)
#End of NumToName
def NumToNameForOneFile(path):
if Smali.isSmali(path):
path = Smali.getSmaliMainPath(path)
else:
return
if os.path.exists(path):
fDir = os.path.dirname(path)
if cmp(fDir, "") == 0:
fDir = "."
name = Smali.getSmaliRoot(path)
else:
return
if os.path.exists(os.path.join(fDir, name)+".data"):
if False: print "NumToName: "+os.path.join(fDir, name)+".data is exist, ignore!"
return os.path.join(fDir, name) + ".data"
java = Java(fDir, name)
#java.printJava()
if java.getListLen() == 0:
if False: print "Can not find smali file: "+os.path.join(java.path, java.name)+"*.smali"
return
toName = NumToName(java.name, java.path, java.smaliList)
#toName.printAccessSmaliSet()
toName.doNumToName()
toName.dumpMap()
return os.path.join(java.path, java.name) + ".data"
def Usage():
print "Usage: num2name.py aa/bb/A.smali"
print " num2name.py aa/bb/B$1.smali"
print " num2name.py aa/bb"
if __name__ == '__main__':
argLen = len(sys.argv)
if argLen == 2:
path = sys.argv[1]
if Smali.isSmali(path):
NumToNameForOneFile(path)
elif os.path.isdir(path):
for root, dirs, files in os.walk(path):
for sfile in files:
fPath = os.path.join(root, sfile)
if Smali.isRootSmali(fPath):
NumToNameForOneFile(fPath)
else:
Usage()
else:
Usage()