约单app导游模块分析
# 抓包
这里使用 postern + charles 抓包
# 静态分析
通过抓包结果可知响应是加密的,请求参数也需要看一下。经过 jadx 静态反编译可以得知:
参数 | 分析结果 |
---|---|
GET | 请求方式 |
/api3.0/user/box | api{https://and.iyuedan.com/api3.0/user/box} |
?tdid=388b6b40d00b627ce448595e2910f28d6 | |
&time=1618816116054 | 时间戳 |
&oaid=null | 写死 |
&token=1650097369I622d07d4e9IW66029678 | deviceId 写死 |
&role=1 | 写死 |
&version=6.1.6 | 写死 |
&sversion=1 | 写死 |
&client=android | 写死 |
&device=Nexus 5X | 写死 |
&appname=yuedan | 写死 |
&market=xiaomi | 写死 |
&os_version=27 | 写死 |
&new_work=27 | 写死 |
&lang=cn | 写死 |
&ydmd=tmBmKE!VuK>H>E!_^K>H> | 母鸡,写死 |
&and_class_name=Activity_UserInfo_V2 | 写死 |
&user_id=53745578 | 用户 id 写死 |
&position=2 | 写死 |
&ydtoken=6f9e3deb3afa8e2ccd4f015ca06fcef9 | |
HTTP/1.1 | http 协议 |
经过分析,tdid 是不变化的,也有可能是登陆时候生成的 (没有分析), 接下来搜索 ydtoken
进过分析这里最为可疑,然后点进去看一下
可以看到这里是 MD5 加密,但是还是需要开启 objection 看一下.
但是在网页端使用 MD5 加密将原本的字符串加密之后结果并不一样,怀疑加盐了或者是自写的 MD5 加密,(但是一般不会是自写算法). 我第一次在找盐的时候想错了。简单方法可以直接 hook 这个 md5 算法这样就会知道了
接着分析响应加密
具体怎么找到的我也忘记了,只记得先找到了这个 decrypt 函数
然后写 frida 脚本测试一下是可以调用成功的,但是在把算法抠出来写入却始终报错,然后再试了试 hook convert
.
将这里的 sohoKeyMap
和 devKeyMap
重写,这样解密算法就完成了
至于如何做成接口调用这不是有手就行?
使用 springboot (不得不说 java 的代码是真的繁琐)
# tips
脱壳
我使用的是 yang 神的脱壳工具 https://github.com/lasting-yang/frida_dump
合并 dex
合并 dex 的方法有多种方法,我使用的是
https://github.com/Simp1er/AndroidSec/blob/master/dex2apk.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
82import os
import zipfile
import argparse
def rename_class(path):
files = os.listdir(path)
dex_index = 0
if path.endswith('/'):
path = path[:-1]
print(path)
for i in range(len(files)):
if files[i].endswith('.dex'):
old_name = path + '/' + files[i]
if dex_index == 0:
new_name = path + '/' + 'classes.dex'
else:
new_name = path + '/' + 'classes%d.dex' % dex_index
dex_index += 1
if os.path.exists(new_name):
continue
os.rename(old_name, new_name)
print('[*] 重命名完毕')
def extract_META_INF_from_apk(apk_path, target_path):
r = zipfile.is_zipfile(apk_path)
if r:
fz = zipfile.ZipFile(apk_path, 'r')
for file in fz.namelist():
if file.startswith('META-INF'):
fz.extract(file, target_path)
else:
print('[-] %s 不是一个APK文件' % apk_path)
def zip_dir(dirname, zipfilename):
filelist = []
if os.path.isfile(dirname):
if dirname.endswith('.dex'):
filelist.append(dirname)
else:
for root, dirs, files in os.walk(dirname):
for dir in dirs:
# if dir == 'META-INF':
# print('dir:', os.path.join(root, dir))
filelist.append(os.path.join(root, dir))
for name in files:
# print('file:', os.path.join(root, name))
filelist.append(os.path.join(root, name))
z = zipfile.ZipFile(zipfilename, 'w', zipfile.ZIP_DEFLATED)
for tar in filelist:
arcname = tar[len(dirname):]
if ('META-INF' in arcname or arcname.endswith('.dex')) and '.DS_Store' not in arcname:
# print(tar + " -->rar: " + arcname)
z.write(tar, arcname)
print('[*] APK打包成功,你可以拖入APK进行分析啦!' )
z.close()
def parse_args():
parser = argparse.ArgumentParser(description='repackage dumped dex to apk for jeb/jadx analysis.')
parser.add_argument('-a', '--apk_path', required=True, type=str,
help='apk for extracting META-INF')
parser.add_argument('-i', '--dex_path', required=True, type=str,
help='path of dumped dex')
parser.add_argument('-o', '--output', type=str, default="repacked.apk",
help='apk path after zip')
args = parser.parse_args()
#print(args.apk_path)
return args
if __name__ == '__main__':
args = parse_args()
rename_class(args.dex_path)
extract_META_INF_from_apk(args.apk_path, args.dex_path)
# zip_file(args.dex_path)
zip_dir(args.dex_path, args.output)
但是有时候我们也许不要合并,使用 ls -Sr
将 dex 按照大小排列,1.2.0 版本的 jadx 可以使用 add files
将 dex 添加到项目中但是我添加了 6 个之后就崩了,但是不影响分析.