-
Notifications
You must be signed in to change notification settings - Fork 115
/
Copy pathapk-diff.py
executable file
·91 lines (67 loc) · 2.83 KB
/
apk-diff.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
#!/usr/bin/python3
import re
import sys
import pyfiglet
import argparse
import difflib
from filecmp import dircmp
from pathlib import Path
sys.path.append('..')
from utils import *
pwd = Path(__file__).parent
tools_path = Path(__file__).absolute().parents[1].joinpath('tools')
ignore_name = 'R\$|.*(align|apktool.yml|pak|MF|RSA|SF|bin|so)'
ignore_file = '.*(google|androidx|kotlin|apktool_smali/res|apktool_smali/original)'
count = 0
result = ''
def diff_apk(apk1, apk2):
report_file = pwd.joinpath('diff_apk.txt')
diffuse = tools_path.joinpath('diffuse.jar')
cmd = f'java -jar {diffuse} diff {apk1} {apk2} --text {report_file}'
output, ret_code = shell_cmd(cmd)
if not report_file.exists():
with open(f'{report_file}.error', 'w+') as f:
f.write(output)
print_focus('Diffing APKs -> diff_apk.txt')
return ret_code
def diff_code(folder1, folder2):
compared = dircmp(folder1, folder2)
diff(compared)
with open(pwd.joinpath('diff_smali.txt'), 'w+') as f:
f.write(result)
print_focus(f'Diffing smali -> diff_smali.txt\t{str(count)} files are different')
def diff(compared):
for name in compared.diff_files:
if not re.match(ignore_name, name) and not re.match(ignore_file, str(compared.left)):
with open(f'{compared.left}/{name}', 'r', encoding='utf8', errors='ignore') as f:
content1 = f.read().splitlines(True)
with open(f'{compared.right}/{name}', 'r', encoding='utf8', errors='ignore') as f:
content2 = f.read().splitlines(True)
lines = []
for line in difflib.unified_diff(content1, content2):
line = line.strip()
if line[:1] in ['+', '-'] and len(line) != 1 and line[:3] not in ['+++', '---'] \
and not re.match('.*(\.line\s\d|return-void)', line):
lines.append(line)
if all('const' in i or '0x7f' in i for i in lines):
continue
global result, count
result += f'[{name}] {compared.right}\n'+'\n'.join(lines)+'\n\n'
count += 1
for sd in compared.subdirs.values():
diff(sd)
def argument():
parser = argparse.ArgumentParser()
parser.add_argument('apk1', metavar='apk1', help='Location of the first APK.')
parser.add_argument('apk2', metavar='apk2', help='Location of the second APK.')
return parser.parse_args()
if __name__ == '__main__':
print(pyfiglet.figlet_format('apk-diff'))
args = argument()
diff_apk(args.apk1, args.apk2)
smali1 = Path(args.apk1).parent.joinpath('apktool_smali')
smali2 = Path(args.apk2).parent.joinpath('apktool_smali')
diff_code(smali1, smali2)
# java1 = Path(args.apk1).parent.joinpath('jadx_java')
# java2 = Path(args.apk2).parent.joinpath('jadx_java')
# diff_code(java1, java2)