Skip to content

Commit 1afad57

Browse files
author
psachdev
committed
python static analyser
0 parents  commit 1afad57

12 files changed

+1194
-0
lines changed

DbManager.py

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
'''
2+
Created on Dec 8, 2012
3+
4+
@author: psachdev
5+
'''
6+
import MySQLdb as db
7+
from MySQLdb.constants import FIELD_TYPE
8+
9+
class DBManagerClass:
10+
'''
11+
classdocs
12+
'''
13+
14+
15+
def __init__(self):
16+
self.username = 'root'
17+
self.password = 'root'
18+
self.host = '127.0.0.1'
19+
self.dbname = 'staticanalysisresults'
20+
self.dbport = 3306
21+
self.table_externalPackage = '3rd_party_packages'
22+
self.custom_conv = { FIELD_TYPE.BIT: int }
23+
self.connectToDb()
24+
self.createTables()
25+
26+
def connectToDb (self):
27+
self.dbconn = db.Connect(self.host, self.username, self.password, self.dbname, self.dbport, conv=self.custom_conv)
28+
29+
def createTables (self):
30+
cur = self.dbconn.cursor ()
31+
cur.execute("CREATE TABLE IF NOT EXISTS \
32+
Test_3rd_party_packages (Id INT PRIMARY KEY AUTO_INCREMENT, packagename VARCHAR(255), filename VARCHAR(255), category VARCHAR(255), 3rd_party_package VARCHAR(255))")
33+
cur.execute("CREATE TABLE IF NOT EXISTS \
34+
Test_permissionlist (Id INT PRIMARY KEY AUTO_INCREMENT, packagename VARCHAR(255), appfilename VARCHAR(255), permission VARCHAR(255), is_external INT, dest VARCHAR(255), 3rd_party_package VARCHAR(255), src VARCHAR(255))")
35+
cur.execute("CREATE TABLE IF NOT EXISTS \
36+
Test_linkurl (Id INT PRIMARY KEY AUTO_INCREMENT, packagename VARCHAR(255), appfilename VARCHAR(255), link_url VARCHAR(255), is_external INT, triggered_by_code VARCHAR(255), 3rd_party_package VARCHAR(255))")
37+
38+
def insert3rdPartyPackageInfo (self, packagename, filename, externalpackagename, category):
39+
cur = self.dbconn.cursor()
40+
escape_packagename = str (self.dbconn.escape_string(packagename))
41+
escape_filename = str (self.dbconn.escape_string(filename))
42+
escape_externalpackagename = str (self.dbconn.escape_string(externalpackagename))
43+
escape_category = str (self.dbconn.escape_string(category))
44+
rows_affected = cur.execute("INSERT INTO Test_3rd_party_packages (packagename, filename, category, 3rd_party_package) VALUES('%s', '%s', '%s', '%s')" % (escape_packagename, escape_filename, escape_category, escape_externalpackagename))
45+
self.dbconn.commit()
46+
#print "Rows affected after inserting 3rdpartypackage - " + str (rows_affected)
47+
48+
49+
def insertPermissionInfo (self, packagename, filename, permission, is_external, dest, externalpackagename, src):
50+
cur = self.dbconn.cursor()
51+
escape_packagename = str (self.dbconn.escape_string(packagename))
52+
escape_filename = str (self.dbconn.escape_string(filename))
53+
escape_externalpackagename = str (self.dbconn.escape_string(externalpackagename))
54+
escape_permission = str (self.dbconn.escape_string(permission))
55+
escape_dest = str (self.dbconn.escape_string(dest))
56+
escape_src = str (self.dbconn.escape_string(src))
57+
58+
rows_affected = cur.execute("INSERT INTO Test_permissionlist (packagename, appfilename, permission, is_external, dest, 3rd_party_package, src) VALUES('%s', '%s', '%s', '%i', '%s', '%s', '%s')" % (escape_packagename, escape_filename, escape_permission, is_external, escape_dest, escape_externalpackagename, escape_src))
59+
self.dbconn.commit()
60+
#print "Rows affected after inserting permission - " + str (rows_affected)
61+
62+
def insertLinkInfo (self, packagename, filename, link_url, is_external, triggered_by_code, externalpackagename):
63+
cur = self.dbconn.cursor()
64+
escape_packagename = str (self.dbconn.escape_string(packagename))
65+
escape_filename = str (self.dbconn.escape_string(filename))
66+
escape_triggered_by_code = str (self.dbconn.escape_string( triggered_by_code))
67+
escape_externalpackagename = str (self.dbconn.escape_string(externalpackagename))
68+
escape_url = str (self.dbconn.escape_string(link_url))
69+
rows_affected = cur.execute("INSERT INTO Test_linkurl (packagename, appfilename, link_url, is_external, triggered_by_code, 3rd_party_package) VALUES('%s', '%s', '%s', '%d', '%s', '%s')" % (escape_packagename, escape_filename, escape_url, is_external, escape_triggered_by_code, escape_externalpackagename))
70+
self.dbconn.commit()
71+
#print "Rows affected after inserting permission - " + str (rows_affected)
72+
73+
def deleteEntry (self, apkname):
74+
cur = self.dbconn.cursor()
75+
escape_apkname = str (self.dbconn.escape_string(apkname))
76+
rows_affected = cur.execute("DELETE FROM Test_linkurl WHERE packagename='%s'" % (escape_apkname))
77+
print "Rows affected after deletion - " + str (rows_affected)
78+
rows_affected = cur.execute("DELETE FROM Test_permissionlist WHERE packagename='%s'" % (escape_apkname))
79+
print "Rows affected after deletion - " + str (rows_affected)
80+
rows_affected = cur.execute("DELETE FROM Test_3rd_party_packages WHERE packagename='%s'" % (escape_apkname))
81+
print "Rows affected after deletion - " + str (rows_affected)
82+
self.dbconn.commit()
83+
84+
85+
86+

DirStructHandler.py

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'''
2+
Created on Oct 7, 2012
3+
4+
@author: psachdev
5+
'''
6+
7+
class DirEntry:
8+
'''
9+
This structure is used to hold references to subdirectories
10+
The tree formed in namespackeanalyzer used this structure to hold
11+
node information
12+
'''
13+
14+
def __init__(self):
15+
'''
16+
Constructor
17+
'''
18+
self.DirName = ""
19+
self.ChildRef = []
20+
21+
def AddDirName (self, name):
22+
self.DirName = name
23+
24+
def AddChildRef (self, ref):
25+
self.ChildRef.append(ref)
26+
27+
def IsRefPresent (self, refName):
28+
for name in self.ChildRef:
29+
if name.DirName == refName:
30+
return True
31+
else:
32+
return False
33+
def IsEqual (self, ref):
34+
if ref.DirName == self.DirName:
35+
return True
36+
else :
37+
return False

PackageRules.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
'''
2+
Created on Oct 7, 2012
3+
4+
@author: psachdev
5+
'''
6+
import DirStructHandler
7+
8+
class Rules:
9+
'''
10+
This class is used to create static rules. Following are rules
11+
All the directories starting with org or com are assigned number 2 means to be read recursively
12+
All the directories starting with google are assigned -1 means they shouldn't be printed
13+
All the directories with name length < 4 are treated as noise and are assigned number -2 (number based on analysis)
14+
Remaining are assigned number 1
15+
'''
16+
17+
def __init__(self, rootEntry, main_package_name):
18+
'''
19+
Constructor
20+
'''
21+
self.rootName = rootEntry.DirName
22+
self.main_package_name = main_package_name
23+
self.packageLevel = 0
24+
self.FormRule ()
25+
26+
def GetTokens (self, string):
27+
28+
tokens = []
29+
for name in string.split ('.'):
30+
tokens.append(name)
31+
32+
return tokens
33+
34+
def FormRule (self):
35+
if self.rootName == "org" or self.rootName == "Lorg":
36+
self.packageLevel = 2 #org.apache.*
37+
return
38+
elif self.rootName == "com" or self.rootName == "Lcom":
39+
tokens = self.GetTokens(self.main_package_name)
40+
if tokens [1] == "google":
41+
self.packageLevel = -1 #indicating its google_apk
42+
else:
43+
self.packageLevel = 2 #com.bayview.*or com.googlex.*
44+
else:
45+
if self.rootName == "ti" or self.rootName == "Lti":
46+
self.packageLevel = 3
47+
elif self.rootName.find(';')!=-1 or self.rootName.find('$')!=-1 or (len(self.rootName) <= 3) or ('w3c' in self.rootName) or ('apache' in self.rootName) or ('xml' in self.rootName) or ('junit' in self.rootName) or ('sun' in self.rootName) or ('android' in self.rootName) or ('dalvik' in self.rootName) or ('json' in self.rootName) :
48+
self.packageLevel = -2 #noise
49+
else:
50+
self.packageLevel = 1

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Project Name - python project to statically analyze the androidApps
2+
Author - Prateek Sachdeva

SearchIntents.py

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
'''
2+
Created on Oct 24, 2012
3+
4+
@author: psachdev
5+
'''
6+
from androguard.core.bytecodes import apk
7+
from androguard.core.bytecodes import dvm
8+
from androguard.core.analysis.analysis import *
9+
10+
class Intents:
11+
'''
12+
1. Create a regular expression to filter out http links
13+
2. Get the list of the tainted strings used in apk using dalvik analysis
14+
3. Apply the filter to every entry read if it matched the regular expression then print it in file
15+
4. Using the package array containing list of all packages found in apk print the corresponding package in which link is formed
16+
This is using Path Variable analysis
17+
When you read the tainted string you also the address at which its present
18+
Use that address to get the class name
19+
and then see under which package that class name belongs
20+
'''
21+
22+
def findandprint (self, packages, dst_class_name):
23+
for package in packages:
24+
if package in dst_class_name:
25+
###self.outHandle.write ("\n PackageName - ")
26+
###self.outHandle.write (package)
27+
return package
28+
return "NA"
29+
30+
def __init__(self, infile, outfile, packages, dbMgr, noprefixfilename, a, d, dx):
31+
'''
32+
Constructor
33+
'''
34+
###a = apk.APK(infile)
35+
###d = dvm.DalvikVMFormat (a.get_dex())
36+
###dx = uVMAnalysis (d)
37+
38+
self.outHandle = open (outfile, 'a+')
39+
40+
ex1 = re.compile ("http://")
41+
mpn = a.get_package()
42+
'''
43+
Keeping main package name within range of mysql datatype
44+
'''
45+
if len(mpn) > 250 :
46+
self.main_package_name = (mpn[:200] + '..')
47+
else:
48+
self.main_package_name = mpn
49+
50+
51+
###self.outHandle.write ("\n")
52+
###self.outHandle.write ("---Package Name---\n")
53+
#print self.main_package_name
54+
55+
56+
'''
57+
Keeping main package name within range of mysql datatype
58+
'''
59+
if len(noprefixfilename) > 250 :
60+
self.fileName = (noprefixfilename[:200] + '..')
61+
else:
62+
self.fileName = noprefixfilename
63+
64+
###self.outHandle.write(infile)
65+
print self.main_package_name
66+
ex3 = re.compile (self.main_package_name)
67+
68+
self.dbMgr = dbMgr
69+
#print 'URL - '
70+
x = dx.get_tainted_variables().get_strings()
71+
analysis = dx.get_vm()
72+
#cm = analysis.get_class_manager()
73+
###self.outHandle.write ('\n')
74+
75+
for full in x:
76+
s,_ = full
77+
string = repr(s.get_info())
78+
if ex1.search (string) != None:
79+
paths = s.get_paths()
80+
81+
for path in paths:
82+
m_idx = path[1]
83+
method = analysis.get_cm_method( m_idx )
84+
###self.outHandle.write (" %s->%s %s" % (method[0], method[1], method[2][0] + method[2][1]))
85+
86+
'''
87+
Keeping external package within range of mysql datatype
88+
'''
89+
xpackage = self.findandprint (packages, method[0])
90+
if len(xpackage) > 250 :
91+
xpck = (xpackage[:200] + '..')
92+
else:
93+
xpck = xpackage
94+
95+
96+
'''
97+
Keeping destination class within range of mysql datatype
98+
'''
99+
if len(method[0]) > 250 :
100+
dst = (method[0][:200] + '..')
101+
elif method[0].find('$')!=-1 :
102+
dst = "NA"
103+
else:
104+
dst = method[0]
105+
106+
107+
#print method
108+
if ex3.search(method[0]) != None:
109+
_,link = full
110+
#print " APP - ", link
111+
if ('.png' in link) or ('127.0.0.1' in link) or ('www.w3.org' in link):
112+
continue
113+
###self.outHandle.write (" APP - ")
114+
###self.outHandle.write (link)
115+
###self.outHandle.write ('\n')
116+
if len(link) > 250 :
117+
strlink = (link[:200] + '..')
118+
else:
119+
strlink = link
120+
121+
122+
self.dbMgr.insertLinkInfo(self.main_package_name, self.fileName, strlink, False, dst, xpck)
123+
124+
else:
125+
_,link = full
126+
#print "EXTERNAL - ", link
127+
if ('.png' in link) or ('127.0.0.1' in link) or ('www.w3.org' in link):
128+
continue
129+
###self.outHandle.write (" EXTERNAL - ")
130+
###self.outHandle.write (link)
131+
###self.outHandle.write ('\n')
132+
if len(link) > 250 :
133+
strlink = (link[:200] + '..')
134+
else:
135+
strlink = link
136+
137+
138+
self.dbMgr.insertLinkInfo(self.main_package_name, self.fileName, strlink, True, dst, xpck)
139+
140+
#access, idx = path[0]
141+
###self.outHandle.write ('\n\n')
142+
self.outHandle.close()
143+

job.sh

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
3+
numapks=`find $1 -name "*.apk" | wc -l`
4+
apksdone=`awk '{x++}END{ print x}' /home/ubuntu/out/filelist.txt`
5+
while test $numapks!=$apksdone:
6+
do
7+
returnvalue=$(python /home/ubuntu/code/staticAnalyzer/src/staticanalyzer/main.py $1)
8+
#echo "---------------------------------" >> jobout.txt
9+
#echo "number of apks listed :" >> jobout.txt
10+
#echo $numapks >> jobout.txt
11+
#echo "apks tested so far :" >> jobout.txt
12+
#echo $apksdone >> jobout.txt
13+
#echo "Return value of python script" >> jobout.txt
14+
#echo $? >> jobout.txt
15+
#echo "---------------------------------" >> jobout.txt
16+
`tail -n 1 /home/ubuntu/out/filelist.txt >> /home/ubuntu/out/problemfiles.txt`
17+
apksdone=`awk '{x++}END{ print x}' /home/ubuntu/out/filelist.txt`
18+
done

job_LargeVM.sh

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/sh
2+
3+
numapks=`cat /home/ubuntu/out/problemfiles_forLargeVM.txt | wc -l`
4+
apksdone=`awk '{x++}END{ print x}' /home/ubuntu/out/filelist_forLargeVM.txt`
5+
#while test $numapks!=$apksdone:
6+
#do
7+
returnvalue=$(python /home/ubuntu/code/staticAnalyzer/src/staticanalyzer/main_LargeVM.py $1)
8+
#echo "---------------------------------" >> jobout.txt
9+
#echo "number of apks listed :" >> jobout.txt
10+
echo $numapks
11+
#echo "apks tested so far :" >> jobout.txt
12+
echo $apksdone
13+
#echo "Return value of python script" >> jobout.txt
14+
#echo $? >> jobout.txt
15+
#echo "---------------------------------" >> jobout.txt
16+
`tail -n 1 /home/ubuntu/out/filelist_forLargeVM.txt >> /home/ubuntu/out/problemfiles.txt`
17+
#x=0
18+
apksdone=`awk '{x++}END{ print x}' /home/ubuntu/out/filelist_forLargeVM.txt`
19+
#done

0 commit comments

Comments
 (0)