app:yuanrenxuem109.apk

接口:https://appmatch.yuanrenxue.cn/app1

解析流程:

第一题未作双向认证,所以可以正常抓包,多次抓包发现,需要解决的参数只有sign,page是页数,t是时间戳

image-20230519171947102

正常使用jadx打开,app未加壳,直接搜索“sign”,点进第一个看一下,发现一个类似路由一样的东西,也指明了路由app1,应该就是i这里了,看一下OooO00o方法是什么,点击右键,查找用例,再点进去看一下

image-20230519172730114

image-20230519172821634

image-20230519172937232

在这里可以看到sb是一个字符串,然后sign方法中传入的是sb转字节数组,我们再看一下sign方法什么

image-20230519173146117

sign方法传入一个字节数组后,进行了一系列操作,我们直接用frida看一下传入的参数是什么,再看下返回了什么

image-20230519173452868

由于传入的是一个字节数组,所以我们需要先转换成字符串才知道传入的参数是什么

1
2
3
4
5
6
7
8
9
10
11
12
function bin2String(array) {
return String.fromCharCode.apply(String, array)
}

Java.perform(function () {
Java.use("com.yuanrenxue.match2022.security.Sign").sign.implementation = function (bArr) {
console.log(bin2String(bArr));
let res = this.sign(bArr);
console.log(res);
return res;
}
});

经过frida调试,我们可以看到,传入的参数是 page + t 就是页数加时间戳

image-20230519175231586

我们这里直接使用frida rpc调用sign方法,来获取返回值,因为我们传入的是字符串,所以需要将数据转成字节数组才行

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
function StringToByte(str) {
var re = [], idx;
for (var i = 0; i < str.length; i++) {
idx = str.charCodeAt(i);
if (idx & 0xff00) {
re.push(idx >> 8);
re.push(idx & 0xff);
} else {
re.push(idx)
}
}
return re;
}
//主动调用
function invokesign(data){
var result = null;
Java.perform(function () {
// Java.choose(className, callback),在内存中扫描java堆
Java.choose("com.yuanrenxue.match2022.security.Sign",{
// 找到匹配对象
onMatch:function (instance){
// console.log(instance);
result = instance.sign(StringToByte(data));
// 扫描完成调用
},onComplete:function (){}
})
});
return result;
}

// 将对象暴露出来
rpc.exports = {
invokesig:invokesign,
}

在使用python来调用frida参与请求

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
session = frida.get_remote_device().attach("猿人学2022")
with open('./1..js', encoding='utf-8') as f:
script = session.create_script(f.read())

script.on('message', on_message)
script.load()
# print(script.exports.invokesig("page=11684157134"))
# sys.stdin.read() # 标准化输出??

total = 0
for i in range(1, 101):
headers = {
'Host': 'appmatch.yuanrenxue.cn',
'accept-language': 'zh-CN,zh;q=0.8',
'user-agent': 'Mozilla/5.0 (Linux; U; Android 12; zh-cn; Pixel 3a Build/SP2A.220505.008) AppleWebKit/533.1 (KHTML, like Gecko) Version/5.0 Mobile Safari/533.1',
'content-type': 'application/x-www-form-urlencoded',
'cache-control': 'no-cache',
}
data = {
'page': i,
't': int(time.time()),
}
data['sign'] = script.exports.invokesig(f"page={data['page']}{data['t']}")
print(data['sign'])
response = requests.post('https://appmatch.yuanrenxue.cn/app1', headers=headers, data=data).json()
for num in response['data']:
total += int(num['value'])

print(total)

最后请求成功,获取到了100页的数据之和

image-20230519175805552