/
static_analysis.py
154 lines (131 loc) · 5.58 KB
/
static_analysis.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
152
153
154
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import os
import shutil
import subprocess as sp
from pathlib import Path
from xml.dom import minidom
import yaml
from django.conf import settings
from minio import Minio
from minio.error import (ResponseError)
from trackers.models import Tracker
def grep(folder, pattern):
cmd = '/bin/grep -r "%s" %s/*.dex %s/AndroidManifest.xml' % (pattern, folder, folder)
process = sp.Popen(cmd, shell=True, stdout=sp.PIPE, stderr=sp.STDOUT)
output = process.communicate()[0]
exitCode = process.returncode
return exitCode == 0
def download_and_put(url, destination_name):
import urllib.request, tempfile
try:
f = urllib.request.urlopen(url)
print("Downloading " + url)
with tempfile.NamedTemporaryFile(delete=True) as fp:
fp.write(f.read())
# Upload icon in storage
minio_client = Minio(settings.MINIO_URL,
access_key=settings.MINIO_ACCESS_KEY,
secret_key=settings.MINIO_SECRET_KEY,
secure=settings.MINIO_SECURE)
try:
minio_client.fput_object(settings.MINIO_BUCKET, destination_name, fp.name)
except ResponseError as err:
print(err)
return destination_name
except Exception as e:
print(e)
return ''
def getIcon(icon_name, handle, url=None):
from bs4 import BeautifulSoup
import urllib.request, tempfile
if url is None:
address = 'https://play.google.com/store/apps/details?id=%s' % handle
text = urllib.request.urlopen(address).read()
soup = BeautifulSoup(text, 'html.parser')
i = soup.find_all('img', {'class': 'cover-image', 'alt': 'Cover art'})
if len(i) > 0:
url = '%s'%i[0]['src']
if not url.startswith('http'):
url = 'https:%s' % url
else:
return ''
return download_and_put(url, icon_name)
def findTrackers(decoded_dir):
trackers = Tracker.objects.order_by('name')
found = []
for t in trackers:
for p in t.detectionrule_set.all():
if grep(decoded_dir, p.pattern):
found.append(t)
break
return found
def getVersion(decoded_dir):
yml = os.path.join(decoded_dir, 'apktool.yml')
yml_new = os.path.join(decoded_dir, 'apktool.yml.new')
cmd = '/bin/cat %s | /bin/grep -v "\!\!" > %s' % (yml, yml_new)
process = sp.Popen(cmd, shell=True, stdout=sp.PIPE, stderr=sp.STDOUT)
output = process.communicate()[0]
exitCode = process.returncode
if exitCode != 0:
return ''
with open(yml_new) as f:
dataMap = yaml.safe_load(f)
return dataMap['versionInfo']['versionName']
def getHandle(decoded_dir):
xmldoc = minidom.parse(os.path.join(decoded_dir, 'AndroidManifest.xml'))
man = xmldoc.getElementsByTagName('manifest')[0]
return man.getAttribute('package')
def getPermissions(decoded_dir):
xmldoc = minidom.parse(os.path.join(decoded_dir, 'AndroidManifest.xml'))
permissions = xmldoc.getElementsByTagName('uses-permission')
perms = []
for perm in permissions:
perms.append(perm.getAttribute('android:name'))
return perms
def getSha256Sum(apk_path):
cmd = '/usr/bin/sha256sum %s | head -c 64' % apk_path
process = sp.Popen(cmd, shell=True, stdout=sp.PIPE, stderr=sp.STDOUT)
return process.stdout.read()
def decodeAPK(apk_path, decoded_dir):
root_dir = os.path.dirname(os.path.realpath(__file__))
apktool = os.path.join(root_dir, "apktool.jar")
cmd = '/usr/bin/java -jar %s d %s -s -o %s/' % (apktool, apk_path, decoded_dir)
process = sp.Popen(cmd, shell=True, stdout=sp.PIPE, stderr=sp.STDOUT)
output = process.communicate()[0]
exitCode = process.returncode
return exitCode == 0
def getApplicationInfos(handle):
# Fix#12 - We have to remove the cached token :S
shutil.rmtree(os.path.join(str(Path.home()), '.cache/gplaycli/'), ignore_errors=True)
cmd = 'gplaycli -t -s %s -n 1' % handle
lines = []
with sp.Popen(cmd, shell=True, stdout=sp.PIPE, stderr=sp.STDOUT, universal_newlines=True) as p:
for line in iter(p.stdout):
if 'Traceback' in line or 'Error' in line:
return None
lines.append(line.replace('\n', ''))
if len(lines) != 2:
return None
columns = []
columns.append({'start':0, 'end':0, 'value':'', 'name':'title', 'text':'Title'})
columns.append({'start':0, 'end':0, 'value':'', 'name':'creator', 'text':'Creator'})
columns.append({'start':0, 'end':0, 'value':'', 'name':'size', 'text':'Size'})
columns.append({'start':0, 'end':0, 'value':'', 'name':'downloads', 'text':'Downloads'})
columns.append({'start':0, 'end':0, 'value':'', 'name':'update', 'text':'Last Update'})
columns.append({'start':0, 'end':0, 'value':'', 'name':'handle', 'text':'AppID'})
columns.append({'start':0, 'end':0, 'value':'', 'name':'version', 'text':'Version'})
columns.append({'start':0, 'end':0, 'value':'', 'name':'rating', 'text':'Rating'})
result = {}
for i in range(0,len(columns)):
v = columns[i]
v['start'] = lines[0].find(v['text'])
if i > 0:
c = columns[i-1]
c['end'] = v['start']
c['value'] = lines[1][c['start']:c['end']].strip(" ")
result[c['name']] = c['value']
if handle in result['handle']:
return result
else:
return None