-
Notifications
You must be signed in to change notification settings - Fork 1
/
rebuild_apk.py
125 lines (111 loc) · 3.75 KB
/
rebuild_apk.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
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : rebuild_apk.py
@Time : 2020/10/14 10:39:02
@Author : Lateautumn4lin
@Version : 1.0
@Contact : Lateautumn4lin
@License : (C)Copyright 2020
@Desc : None
'''
from pathlib import Path
import shutil
import zipfile
import argparse
"""
将脱壳后的dex重打包成新的apk文件,使用范例如下:
python rebuild_apk.py -A 新华字典v0.9.0.apk -D cn.dictcn.android.digitize.swg_xhzd_21003/ -O 新华字典v0.9.0_new.apk
"""
class RebuildApk:
def __init__(self, args):
self.args = args
self.dex_temp = Path(__file__).absolute().parent / "dex_temp"
if not self.dex_temp.exists():
self.dex_temp.mkdir()
def normalization_class(self) -> None:
dex_index = 0
try:
for idx, _file in enumerate(Path(self.args.dex_path).iterdir()):
if _file.suffix == ".dex":
if not dex_index:
normalization_path = self.dex_temp/"classes.dex"
else:
normalization_path = self.dex_temp / \
f"classes{dex_index}.dex"
if not normalization_path.exists():
if self.args.debug:
print(
f"[*] {idx} {_file.name} replace {normalization_path.name}")
shutil.copy(_file, normalization_path)
dex_index += 1
except Exception as e:
print(e)
else:
print("[*] normalization_class success")
def normalization_source(self) -> None:
if zipfile.is_zipfile(self.args.apk_path):
apk_zip_dir = zipfile.ZipFile(self.args.apk_path, 'r')
for _file in apk_zip_dir.namelist():
if _file.startswith('META-INF'):
if self.args.debug:
print(f"[*] insert META-INF {_file}")
apk_zip_dir.extract(_file, self.dex_temp)
print("[*] normalization_source success")
else:
print(f"[*] {self.args.apk_path} format error")
def rebuild(self) -> None:
with zipfile.ZipFile(
self.args.output, 'w', zipfile.ZIP_DEFLATED) as rebuild_apk_zip_dir:
for idx, _file in enumerate(self.dex_temp.iterdir()):
if self.args.debug:
print(f"[*] insert no.{idx} file {_file}")
if _file.is_dir():
for _sub_file in _file.iterdir():
rebuild_apk_zip_dir.write(
_sub_file,
f"{_file.name}\{_sub_file.name}"
)
rebuild_apk_zip_dir.write(_file, _file.name)
print("[*] apk rebuild success")
def start(self):
self.normalization_class()
self.normalization_source()
self.rebuild()
def parse_args():
parser = argparse.ArgumentParser(
description="Rebuild apk from dex dir about after shelling for analysis"
)
parser.add_argument(
"--debug",
type=str,
default=True,
help="turn on debug"
)
parser.add_argument(
"-A",
"--apk_path",
required=True,
type=str,
help="Specify apk path"
)
parser.add_argument(
"-D",
"--dex_path",
required=True,
type=str,
help="Specify dex dir path"
)
parser.add_argument(
"-O",
"--output",
type=str,
default="rebuild.apk",
help="Specify rebuild apk path"
)
args = parser.parse_args()
return args
if __name__ == '__main__':
args = parse_args()
rebuilder = RebuildApk(args)
rebuilder.start()