白乐天

道阻且长,行则将至。

悦野圈app参数逆向及获取话题信息

App信息

包名:com.baicorv.yueyequan

抓包分析数据

进入全部话题,刷新进行抓包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
url: https://customer.yueyequan.cn/comu-core/v1.0/topic/appList

params: {
"pageSize": "20",
"pageNum": "1"
}

headers: {
"br_interactive_uuid": "79a9766d-babe-43c4-9c85-ea5ee8fdfc06",
"User-Agent": "okhttp/4.2.0 (Android 10; google Pixel 3 Build/6506677 3.1.0 30100 release baic-orv-app-android baicorvApp baic-orv-app-android)",
"appInfo": "{\"appVersion\":\"3.1.0\",\"osVersion\":\"Android 10\",\"appType\":\"Android\",\"deviceId\":\"cf116fa8a23dd83ab14a3c3a384ecc0b@1739449447801\",\"deviceName\":\"google Pixel 3\"}",
"appTheme": "AQUA",
"Cookie": ";;;;",
"Cache-Control": "no-cache",
"Accept-Encoding": "identity",
"userid": "",
"ice-auth-appkey": "37893",
"ice-auth-sign": "e58dc1fb0153151edb583d13142a0039df046e447a899fe0406bd61434b394248f0f31a54dbef7adea4a89bd779a09c0ac32bdb891901019c1455ce33c6cb0cc",
"ice-auth-timestamp": "1740129904523",
"Host": "customer.yueyequan.cn",
"Connection": "Keep-Alive"
}

这里面要逆向的参数是ice-auth-sign

逆向分析

反编译搜索ice-auth-sign,并没有相关信息,尝试其他思路。

根据数据长度分析,ice-auth-sign的长度是128个字节,这128字节应该是转为hex之后的长度,原长度是64字节,可能是sha512算法

hook RegisterNatives()

也是出于尝试的心理,猜测它是在so中生成的

恰好就找到了与sign有关的函数

对里面的签名算法进行hook

1
2
3
4
5
6
7
8
9
10
11
12
function hook_sign(){
Java.perform(function(){
let SignatureUtils = Java.use("com.tencent.cloud.iov.signature.SignatureUtils");
SignatureUtils["getEncryptSign"].implementation = function (str, str2, str3) {
console.log(`SignatureUtils.getEncryptSign is called: str=${str}, str2=${str2}, str3=${str3}`);
let result = this["getEncryptSign"](str, str2, str3);
console.log(`SignatureUtils.getEncryptSign result=${result}`);
return result;
};
})
};
hook_sign();

hook到的签名与抓到的数据包中的签名是一样的,那就说明找到了对应的位置

hook NewStringUTF()

还有一种方式也是出于猜测的方式,通过hook字符串,指定长度为128,打印相关信息及调用栈

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
function hook_NewStringUTF(){

let symbols = Module.enumerateSymbolsSync("libart.so");

let addrNewStringUTF = null;

for(let i=0;i<symbols.length;i++){
let symbol = symbols[i];

if(symbol.name.indexOf("NewStringUTF")!=-1 && symbol.name.indexOf("CheckJNI")==-1){

addrNewStringUTF = symbol.address;
console.log("NewStringUTF's addr:",symbol.address," name:",symbol.name);
break
}
}

if(addrNewStringUTF != null){
Interceptor.attach(addrNewStringUTF,{
onEnter:function(args){
var c_string = args[1];
var dataString = c_string.readCString();
if(dataString){
if(dataString.length===128){
console.log("dataString:",dataString);

console.log(Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')+"\n");
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
}
}
},
onLeave:function(){
}
})
}
}

hook_NewStringUTF()

也可以打印出相关信息

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
dataString: 1f28d7d65c10c3af2d5c53d46772064ae16bdcac33880f394a351edbe957701562e4fc47dd344a02657e15bdec3054bf40da3c50df79049467955f7075fc12da
0x7432720728 libsignature.so!_ZN6Helper11toLowerCaseEP7_JNIEnvP8_jstring+0x78
0x7432727110 libsignature.so!getEncryptSign+0x378
0x750ed64354 libart.so!art_quick_generic_jni_trampoline+0x94
0x750ed5b338 libart.so!art_quick_invoke_stub+0x228
0x750ed6a070 libart.so!_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+0xf8
0x750ef040d8 libart.so!_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_11ShadowFrameEtPNS_6JValueE+0x184
0x750eeff3b8 libart.so!_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+0x394
0x750f1bebe8 libart.so!MterpInvokeDirect+0x194
0x750ed55918 libart.so!mterp_op_invoke_direct+0x18
0x750f1bcb58 libart.so!MterpInvokeVirtual+0x59c
0x750ed55818 libart.so!mterp_op_invoke_virtual+0x18
0x750f1beee8 libart.so!MterpInvokeDirect+0x494
0x750ed55918 libart.so!mterp_op_invoke_direct+0x18
0x750f1be34c libart.so!MterpInvokeInterface+0x6d0
0x750ed55a18 libart.so!mterp_op_invoke_interface+0x18
0x750f1bcb58 libart.so!MterpInvokeVirtual+0x59c

java.lang.Throwable
at com.tencent.cloud.iov.signature.SignatureUtils.getEncryptSign(Native Method)
at com.tencent.cloud.iov.signature.SignatureUtils.getSign(SignatureUtils.java:4)
at com.tencent.cloud.baicorv.base.kernel.interceptor.SignatureInterceptor.handleRequestSign(SignatureInterceptor.java:115)
at com.tencent.cloud.baicorv.base.kernel.interceptor.SignatureInterceptor.intercept(SignatureInterceptor.java:46)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
at com.tencent.cloud.baicorv.base.kernel.interceptor.CacheInterceptor.intercept(CacheInterceptor.java:59)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
at com.tencent.cloud.baicorv.base.kernel.interceptor.CookieInterceptor.intercept(CookieInterceptor.java:38)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
at com.tencent.cloud.baicorv.base.kernel.interceptor.StatusInterceptor.intercept(StatusInterceptor.java:43)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
at com.tencent.cloud.baicorv.base.kernel.interceptor.StatisticsInterceptor.intercept(StatisticsInterceptor.java:77)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:184)
at okhttp3.RealCall.execute(RealCall.kt:66)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:204)
at com.bonree.sdk.agent.engine.external.Retrofit2Instrumentation.execute(SourceFile:177)
at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:46)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:35)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableObserveOn.subscribeActual(ObservableObserveOn.java:45)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)

反编译分析

getEncryptSign()

查找用例是在getSign()中被调用的,同时getEncryptSign也是一个native函数

getSign()

hook getSign()

1
2
3
4
5
6
7
8
9
10
11
12
13
function hook_getsign(){
Java.perform(function(){
let SignatureUtils = Java.use("com.tencent.cloud.iov.signature.SignatureUtils");
SignatureUtils["getSign"].implementation = function (str, str2, str3) {
console.log(`SignatureUtils.getSign is called: str=${str}, str2=${str2}, str3=${str3}`);
let result = this["getSign"](str, str2, str3);
console.log(`SignatureUtils.getSign result=${result}`);
return result;
};
})
}

hook_getsign();

结果

1
2
SignatureUtils.getSign is called: str=GET, str2=/comu-core/v1.0/topic/appList, str3=pagenum=1pagesize=20
SignatureUtils.getSign result={ice-auth-appkey=37893, ice-auth-sign=339baf42f164b52d260c14f33aae1201986553643f2fc691ea329ef3f74edf21c8ec42ccc62f35a355c15bf6418e7cf3fb09c2d7f013e6791851be9b1cf93e3b, ice-auth-timestamp=1740131269790}

发现ice-auth-sign是从这个方法返回的

call_getEncryptSign()

在分析so之前,写一个主动调用getEncryptSign()的函数,用于固定参数,后面分析的时候参数是固定的

1
2
3
4
5
6
7
8
9
function call_getEncryptSign(){
Java.perform(function(){
let SignatureUtils = Java.use("com.tencent.cloud.iov.signature.SignatureUtils").$new();
let ret = SignatureUtils.getEncryptSign("GET","/comu-core/v1.0/topic/appList","name=pagenum=1pagesize=10");
console.log("ret",ret);
})
}

// call_getEncryptSign();

so分析

使用IDA反编译找到getEncryptSign()进行分析

sub_9F368()

看到一个函数sub9F368

这里hook一下查看参数及返回值

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
function hook_9f368() {
let addr = Module.findBaseAddress("libsignature.so");
Interceptor.attach(addr.add(0x9f368), {
onEnter: function (args) {
console.log("9f368 onEnter");
console.log("9f368 arg0:",args[0].readCString());
console.log("9f368 arg1:",args[1]);
console.log("9f368 arg2:",args[2]);
console.log("9f368 arg3:",args[3].readCString());
console.log("9f368 arg4:",args[4].readCString());
console.log("9f368 arg5:",args[5].readCString());
console.log("9f368 arg6:",args[6].readCString());
console.log("9f368 arg7:",args[7].readCString());
console.log("9f368 arg8:",args[8].readCString());
console.log("9f368 arg9:",args[9].readCString());
console.log("9f368 arg10:",args[10].readCString());
console.log("9f368 arg11:",args[11].readCString());
console.log("9f368 arg12:",args[12].readCString());
console.log("9f368 arg13:",args[13].readCString());
this.arg0 = args[0];
},
onLeave: function (retval) {


console.log("9f368 ret:",retval);
console.log("9f368 ret arg0:",this.arg0.readCString());
console.log("9f368 onLeave");
}
});
}

hook_9f368();

hook结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
9f368 onEnter
9f368 arg0:
9f368 arg1: 0xffffffffffffffff
9f368 arg2: 0xaf
9f368 arg3: %s%s%s%s%s%s%s%s%s%s
9f368 arg4: GET
9f368 arg5: /comu-core/v1.0/topic/appList
9f368 arg6: ice-auth-appkey
9f368 arg7: :
9f368 arg8: 37893
9f368 arg9: ice-auth-timestamp
9f368 arg10: :
9f368 arg11: 1740194564948
9f368 arg12: name=pagenum=1pagesize=10
9f368 arg13: e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
9f368 ret: 0xae
9f368 ret arg0: GET/comu-core/v1.0/topic/appListice-auth-appkey:37893ice-auth-timestamp:1740194564948name=pagenum=1pagesize=10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
9f368 onLeave

这里是在原来的参数里拼接了ice-auth-appkeyice-auth-timestampe494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7

这里面的ice-auth-appkeye494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7都是定值,但是ice-auth-timestamp这个时间戳是会变动的,所以会导致后面输出的结果也会变动

通过打印内存可以查看ice-auth-appkeye494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7

1
2
3
4
5
6
function temp_call(){
let signSecretResultChar = Module.findExportByName("libsignature.so","signSecretResultChar");
let signIdChar = Module.findExportByName("libsignature.so","signIdChar");
console.log("signSecretResultChar:",signSecretResultChar.readPointer().readCString());
console.log("signIdChar:",signIdChar.readPointer().readCString());
}

urlEncode()

进入到一个函数urlEncode()

hook一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function hook_urlcode(){
let addr = Module.findExportByName("libsignature.so","_ZN6Helper9urlEncodeEPKcPc");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("urlcode is called");
console.log("urlcode arg0:",args[0].readCString());
console.log("urlcode arg1:",args[1].readCString());
console.log("urlcode arg2:",args[2]);
this.arg0 = args[0];
this.arg1 = args[1];
this.arg2 = args[2];
},
onLeave:function(ret){
console.log("urlcode ret:",ret.readCString());
console.log("urlcode ret arg0:",this.arg0.readCString());
console.log("urlcode ret arg1:",this.arg1.readCString());
console.log("urlcode ret arg2:",this.arg2);
}
})
}

hook_urlcode();

结果

1
2
3
4
5
6
7
8
urlcode is called
urlcode arg0: GET/comu-core/v1.0/topic/appListice-auth-appkey:37893ice-auth-timestamp:1740201456983name=pagenum=1pagesize=10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
urlcode arg1:
urlcode arg2: 0x3962333162616634
urlcode ret: null
urlcode ret arg0: GET/comu-core/v1.0/topic/appListice-auth-appkey:37893ice-auth-timestamp:1740201456983name=pagenum=1pagesize=10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
urlcode ret arg1: GET%2Fcomu-core%2Fv1.0%2Ftopic%2FappListice-auth-appkey%3A37893ice-auth-timestamp%3A1740201456983name%3Dpagenum%3D1pagesize%3D10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
urlcode ret arg2: 0x3962333162616634

这里就是进行了url编码

BIO_set_fun_update()

url编码之后就来到了BIO_set_fun_update()函数里

对它进行hook

可以根据符号名或地址进行hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function hook_updateout(){
let addr = Module.findExportByName("libsignature.so","_Z18BIO_set_fun_updatePKcPc");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("updateout is called");
console.log("updateout arg0:",args[0].readCString());
console.log("updateout arg1:",args[1].readCString());
},
onLeave:function(ret){
console.log("updateout ret:",ret.readCString());
}
})
}

hook_updateout();

hook 结果

1
2
3
4
updateout is called
updateout arg0: GET%2Fcomu-core%2Fv1.0%2Ftopic%2FappListice-auth-appkey%3A37893ice-auth-timestamp%3A1740201914497name%3Dpagenum%3D1pagesize%3D10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
updateout arg1: 0b06
updateout ret: 13184d65bf7401d1e3332cd7f9d087c242b30831a2b00553fce87ebdbe44fe00c74a5d686f63c62c1b440f449e64e6175b85d21c36d63b421d29468b364db9d7

这里返回值是签名的值

进入BIO_set_fun_update()函数进行分析

又出现了两个BIO_set_fun_update()

不一样的是这里的符号名和地址与前面的不一样

这里在hook一下,我用out和inner把两个BIO_set_fun_update()区分开了

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
function hook_updateout(){
let addr = Module.findExportByName("libsignature.so","_Z18BIO_set_fun_updatePKcPc");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("updateout is called");
console.log("updateout arg0:",args[0].readCString());
console.log("updateout arg1:",args[1].readCString());
},
onLeave:function(ret){
console.log("updateout ret:",ret.readCString());
}
})
}

hook_updateout();

function hook_updateinner(){
let addr = Module.findExportByName("libsignature.so","_Z18BIO_set_fun_updatePKci");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("updateinner is called");
console.log("updateinner arg0:",args[0].readCString());
console.log("updateinner arg1:",args[1]);
},
onLeave:function(ret){
console.log("updateinner ret:",ret.readCString());
}
})
}

hook_updateinner();

结果

1
2
3
4
5
6
7
8
9
10
11
12
updateout is called
updateout arg0: GET%2Fcomu-core%2Fv1.0%2Ftopic%2FappListice-auth-appkey%3A37893ice-auth-timestamp%3A1740202427152name%3Dpagenum%3D1pagesize%3D10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
updateout arg1: 0b06
updateinner is called
updateinner arg0: GET%2Fcomu-core%2Fv1.0%2Ftopic%2FappListice-auth-appkey%3A37893ice-auth-timestamp%3A1740202427152name%3Dpagenum%3D1pagesize%3D10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
updateinner arg1: 0xb
updateinner ret: fca577ba9ea4937181e79751dbb793380f693877bbd3dabcafa43b8d04e71180
updateinner is called
updateinner arg0: fca577ba9ea4937181e79751dbb793380f693877bbd3dabcafa43b8d04e71180
updateinner arg1: 0x6
updateinner ret: 796171f9d45b2cab31cf389004704e74582b05a34cff479dcef5137b5e90879dd9cf629d73e850d43a85b821a047c4ea3b78ed7b95a98e8c29463032f8ce2181
updateout ret: 796171f9d45b2cab31cf389004704e74582b05a34cff479dcef5137b5e90879dd9cf629d73e850d43a85b821a047c4ea3b78ed7b95a98e8c29463032f8ce2181

updateinner被调用了两次,它的第二个参数一个是0xb,另一个是0x6,好像是一种标识

根据它的源码进行分析,如下,它是用来做switch判断的

firstKeyIndex和secondKeyIndex

其实在传参的时候就可以看到这两个值

通过打印内存查看这两个变量的值

1
2
3
4
5
6
function temp_call(){
let firstKeyIndex = Module.findExportByName("libsignature.so","firstKeyIndex");
let secondKeyIndex = Module.findExportByName("libsignature.so","secondKeyIndex");
console.log("firstKeyIndex:",firstKeyIndex.readInt());
console.log("secondKeyIndex:",secondKeyIndex.readInt());
}

结果如下

case 11

先调用EVP_sha3_256()然后根据返回值判断是否跳转到LABEL_4

先来hook一下

1
2
3
4
5
6
7
8
9
10
11
12
13
function hook_EVP_sha3_256(){
let addr = Module.findExportByName("libsignature.so","EVP_sha3_256");
Interceptor.attach(addr,{
onEnter:function(){
console.log("EVP_sha3_256 is called");
},
onLeave:function(ret){
console.log("EVP_sha3_256 ret:",ret.readCString());
}
})
}

hook_EVP_sha3_256();

结果

1
2
EVP_sha3_256 is called
EVP_sha3_256 ret: I

返回值是I,那就回跳转到LABEL_4

这里会调用calculateHash

calculateHash()

这里就直接hook一下他

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function hook_calculatehash(){
let addr = Module.findExportByName("libsignature.so","_ZN7Encrypt13calculateHashEPKcmP9evp_md_st");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("calculatehash is called");
console.log("calculatehash arg0:",args[0].readCString());
console.log("calculatehash arg1:",args[1]);
console.log("calculatehash arg2:",args[2].readCString());
},
onLeave:function(ret){
console.log("calculatehash ret:",ret.readCString());
}
})
}

hook_calculatehash();

结果

1
2
3
4
5
calculatehash is called
calculatehash arg0: GET%2Fcomu-core%2Fv1.0%2Ftopic%2FappListice-auth-appkey%3A37893ice-auth-timestamp%3A1740203515344name%3Dpagenum%3D1pagesize%3D10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
calculatehash arg1: 0xc0
calculatehash arg2: I
calculatehash ret: f9be3947aad06dcb75c8dd42625dd45477a311fed475806a4cf216cb037e6736

经过测试,这是一个sha3-256算法

如下验证

这里执行完之后会跳转到下一个BIO_set_fun_update()里,然后到case 6分支里

case 6

这里执行的是sha512

hook 一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function hook_sha512(){
let addr = Module.findExportByName("libsignature.so","_ZN7Encrypt6sha512EPKc");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("sha512 is called");
console.log("sha512 arg0:",args[0].readCString());
console.log("sha512 arg1:",args[1]);
},
onLeave:function(ret){
console.log("sha512 ret:",ret.readCString());
}
})
}

hook_sha512();

结果

1
2
3
4
sha512 is called
sha512 arg0: ea4f905597257683f159bb8103b78b8cca161260abfc58cfaaccc1902daff4f2
sha512 arg1: 0x6
sha512 ret: 0dab1fa52babb4820e36f7c83474d4436fa08d705132ed4dc84d6607f86a1ffc8b8ba31b4825f263696fc315354ec453ff2512aac3c5abd04b7ed0eb59801fe0

验证是否为标准的sha512,如下可以确定是标准的sha512

把这些代码整合一下放一起进行hook

代码整合

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
155
156
157
158
159
160
function hook_getEncryptSign(){
Java.perform(function(){
let SignatureUtils = Java.use("com.tencent.cloud.iov.signature.SignatureUtils");
SignatureUtils["getEncryptSign"].implementation = function (str, str2, str3) {
console.log(`SignatureUtils.getEncryptSign is called: str=${str}, str2=${str2}, str3=${str3}`);
let result = this["getEncryptSign"](str, str2, str3);
console.log(`SignatureUtils.getEncryptSign result=${result}`);
return result;
};
})
}

hook_getEncryptSign();


function hook_updateout(){
let addr = Module.findExportByName("libsignature.so","_Z18BIO_set_fun_updatePKcPc");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("updateout is called");
console.log("updateout arg0:",args[0].readCString());
console.log("updateout arg1:",args[1].readCString());
},
onLeave:function(ret){
console.log("updateout ret:",ret.readCString());
}
})
}

hook_updateout();

function hook_updateinner(){
let addr = Module.findExportByName("libsignature.so","_Z18BIO_set_fun_updatePKci");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("updateinner is called");
console.log("updateinner arg0:",args[0].readCString());
console.log("updateinner arg1:",args[1]);
},
onLeave:function(ret){
console.log("updateinner ret:",ret.readCString());
}
})
}

hook_updateinner();

function hook_calculatehash(){
let addr = Module.findExportByName("libsignature.so","_ZN7Encrypt13calculateHashEPKcmP9evp_md_st");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("calculatehash is called");
console.log("calculatehash arg0:",args[0].readCString());
console.log("calculatehash arg1:",args[1]);
console.log("calculatehash arg2:",args[2].readCString());
},
onLeave:function(ret){
console.log("calculatehash ret:",ret.readCString());
}
})
}

hook_calculatehash();


function hook_sha512(){
let addr = Module.findExportByName("libsignature.so","_ZN7Encrypt6sha512EPKc");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("sha512 is called");
console.log("sha512 arg0:",args[0].readCString());
console.log("sha512 arg1:",args[1]);
},
onLeave:function(ret){
console.log("sha512 ret:",ret.readCString());
}
})
}

hook_sha512();

function hook_EVP_sha3_256(){
let addr = Module.findExportByName("libsignature.so","EVP_sha3_256");
Interceptor.attach(addr,{
onEnter:function(){
console.log("EVP_sha3_256 is called");
},
onLeave:function(ret){
console.log("EVP_sha3_256 ret:",ret.readCString());
}
})
}

hook_EVP_sha3_256();

function hook_urlcode(){
let addr = Module.findExportByName("libsignature.so","_ZN6Helper9urlEncodeEPKcPc");
Interceptor.attach(addr,{
onEnter:function(args){
console.log("urlcode is called");
console.log("urlcode arg0:",args[0].readCString());
console.log("urlcode arg1:",args[1].readCString());
console.log("urlcode arg2:",args[2]);
this.arg0 = args[0];
this.arg1 = args[1];
this.arg2 = args[2];
},
onLeave:function(ret){
console.log("urlcode ret:",ret.readCString());
console.log("urlcode ret arg0:",this.arg0.readCString());
console.log("urlcode ret arg1:",this.arg1.readCString());
console.log("urlcode ret arg2:",this.arg2);
}
})
}

hook_urlcode();

function hook_9f368() {
let addr = Module.findBaseAddress("libsignature.so");
Interceptor.attach(addr.add(0x9f368), {
onEnter: function (args) {
console.log("9f368 onEnter");
console.log("9f368 arg0:",args[0].readCString());
this.arg0 = args[0];
console.log("9f368 arg1:",args[1]);
console.log("9f368 arg2:",args[2]);
console.log("9f368 arg3:",args[3].readCString());
console.log("9f368 arg4:",args[4].readCString());
console.log("9f368 arg5:",args[5].readCString());
console.log("9f368 arg6:",args[6].readCString());
console.log("9f368 arg7:",args[7].readCString());
console.log("9f368 arg8:",args[8].readCString());
console.log("9f368 arg9:",args[9].readCString());
console.log("9f368 arg10:",args[10].readCString());
console.log("9f368 arg11:",args[11].readCString());
console.log("9f368 arg12:",args[12].readCString());
console.log("9f368 arg13:",args[13].readCString());
},
onLeave: function (retval) {


console.log("9f368 ret:",retval);
console.log("9f368 ret arg0:",this.arg0.readCString());
console.log("9f368 onLeave");
}
});
}

hook_9f368();

function call_getEncryptSign(){
Java.perform(function(){
let SignatureUtils = Java.use("com.tencent.cloud.iov.signature.SignatureUtils").$new();
let ret = SignatureUtils.getEncryptSign("GET","/comu-core/v1.0/topic/appList","name=pagenum=1pagesize=10");
console.log("ret",ret);
})
}

// call_getEncryptSign();

hook结果

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
SignatureUtils.getEncryptSign is called: str=GET, str2=/comu-core/v1.0/topic/appList, str3=name=pagenum=1pagesize=10
9f368 onEnter
9f368 arg0:
9f368 arg1: 0xffffffffffffffff
9f368 arg2: 0xaf
9f368 arg3: %s%s%s%s%s%s%s%s%s%s
9f368 arg4: GET
9f368 arg5: /comu-core/v1.0/topic/appList
9f368 arg6: ice-auth-appkey
9f368 arg7: :
9f368 arg8: 37893
9f368 arg9: ice-auth-timestamp
9f368 arg10: :
9f368 arg11: 1740211161424
9f368 arg12: name=pagenum=1pagesize=10
9f368 arg13: e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
9f368 ret: 0xae
9f368 ret arg0: GET/comu-core/v1.0/topic/appListice-auth-appkey:37893ice-auth-timestamp:1740211161424name=pagenum=1pagesize=10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
9f368 onLeave
urlcode is called
urlcode arg0: GET/comu-core/v1.0/topic/appListice-auth-appkey:37893ice-auth-timestamp:1740211161424name=pagenum=1pagesize=10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
urlcode arg1:
urlcode arg2: 0x3962333162616634
urlcode ret: null
urlcode ret arg0: GET/comu-core/v1.0/topic/appListice-auth-appkey:37893ice-auth-timestamp:1740211161424name=pagenum=1pagesize=10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
urlcode ret arg1: GET%2Fcomu-core%2Fv1.0%2Ftopic%2FappListice-auth-appkey%3A37893ice-auth-timestamp%3A1740211161424name%3Dpagenum%3D1pagesize%3D10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
urlcode ret arg2: 0x3962333162616634
updateout is called
updateout arg0: GET%2Fcomu-core%2Fv1.0%2Ftopic%2FappListice-auth-appkey%3A37893ice-auth-timestamp%3A1740211161424name%3Dpagenum%3D1pagesize%3D10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
updateout arg1: 0b06
updateinner is called
updateinner arg0: GET%2Fcomu-core%2Fv1.0%2Ftopic%2FappListice-auth-appkey%3A37893ice-auth-timestamp%3A1740211161424name%3Dpagenum%3D1pagesize%3D10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
updateinner arg1: 0xb
EVP_sha3_256 is called
EVP_sha3_256 ret: I
calculatehash is called
calculatehash arg0: GET%2Fcomu-core%2Fv1.0%2Ftopic%2FappListice-auth-appkey%3A37893ice-auth-timestamp%3A1740211161424name%3Dpagenum%3D1pagesize%3D10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7
calculatehash arg1: 0xc0
calculatehash arg2: I
calculatehash ret: e11d22f0ec05913e6b8c605793354f38cfd5c747a68b58c5b8ccf3e6a5bd43a3
updateinner ret: e11d22f0ec05913e6b8c605793354f38cfd5c747a68b58c5b8ccf3e6a5bd43a3
updateinner is called
updateinner arg0: e11d22f0ec05913e6b8c605793354f38cfd5c747a68b58c5b8ccf3e6a5bd43a3
updateinner arg1: 0x6
sha512 is called
sha512 arg0: e11d22f0ec05913e6b8c605793354f38cfd5c747a68b58c5b8ccf3e6a5bd43a3
sha512 arg1: 0x6
sha512 ret: cdb64ffbd625bb5ff4fefd9cfa8404d6ec845ce8ddb5f75cc73ddecc1d9df2a30f9ad15dc17d930d6048c842eb6199a0e3e18dfa586d7ca37619ff040bfecffd
updateinner ret: cdb64ffbd625bb5ff4fefd9cfa8404d6ec845ce8ddb5f75cc73ddecc1d9df2a30f9ad15dc17d930d6048c842eb6199a0e3e18dfa586d7ca37619ff040bfecffd
updateout ret: cdb64ffbd625bb5ff4fefd9cfa8404d6ec845ce8ddb5f75cc73ddecc1d9df2a30f9ad15dc17d930d6048c842eb6199a0e3e18dfa586d7ca37619ff040bfecffd
SignatureUtils.getEncryptSign result={ice-auth-appkey=37893, ice-auth-sign=cdb64ffbd625bb5ff4fefd9cfa8404d6ec845ce8ddb5f75cc73ddecc1d9df2a30f9ad15dc17d930d6048c842eb6199a0e3e18dfa586d7ca37619ff040bfecffd, ice-auth-timestamp=1740211161424}
ret {ice-auth-appkey=37893, ice-auth-sign=cdb64ffbd625bb5ff4fefd9cfa8404d6ec845ce8ddb5f75cc73ddecc1d9df2a30f9ad15dc17d930d6048c842eb6199a0e3e18dfa586d7ca37619ff040bfecffd, ice-auth-timestamp=1740211161424}

python生成ice-auth-sign

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import time
import urllib.parse
import hashlib

timestamp = str(int(time.time() * 1000))
timestamp = "1740211161424"
# print(timestamp)

def sha3_256(data):
return hashlib.sha3_256(data.encode()).hexdigest()

def sha512(data):
return hashlib.sha512(data.encode()).hexdigest()

def g_ice_auth_sign(timestamp):
data = "GET/comu-core/v1.0/topic/appListice-auth-appkey:37893ice-auth-timestamp:"+timestamp+"pagenum=1pagesize=10e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7"
ice_auth_sign = sha512(sha3_256(urllib.parse.quote_plus(data)))
return ice_auth_sign


print(g_ice_auth_sign(timestamp))
# cdb64ffbd625bb5ff4fefd9cfa8404d6ec845ce8ddb5f75cc73ddecc1d9df2a30f9ad15dc17d930d6048c842eb6199a0e3e18dfa586d7ca37619ff040bfecffd

Python请求获取话题数据

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
import requests
import time
import urllib.parse
import hashlib

timestamp = str(int(time.time() * 1000))
# timestamp = "1740211161424"
# timestamp = "1740129904523"
# print(timestamp)

def sha3_256(data):
return hashlib.sha3_256(data.encode()).hexdigest()

def sha512(data):
return hashlib.sha512(data.encode()).hexdigest()

def g_ice_auth_sign(timestamp):
data = "GET/comu-core/v1.0/topic/appListice-auth-appkey:37893ice-auth-timestamp:"+timestamp+"pagenum=1pagesize=100e494454bb61acae31109befb58aa774386b646035af606e9314fab13b9adffe7"
ice_auth_sign = sha512(sha3_256(urllib.parse.quote_plus(data)))
return ice_auth_sign


print(g_ice_auth_sign(timestamp))

url = "https://customer.yueyequan.cn/comu-core/v1.0/topic/appList"

params = {
"pageSize": "100",
"pageNum": "1"
}

headers = {
"br_interactive_uuid": "79a9766d-babe-43c4-9c85-ea5ee8fdfc06",
"User-Agent": "okhttp/4.2.0 (Android 10; google Pixel 3 Build/6506677 3.1.0 30100 release baic-orv-app-android baicorvApp baic-orv-app-android)",
"appInfo": "{\"appVersion\":\"3.1.0\",\"osVersion\":\"Android 10\",\"appType\":\"Android\",\"deviceId\":\"cf116fa8a23dd83ab14a3c3a384ecc0b@1739449447801\",\"deviceName\":\"google Pixel 3\"}",
"appTheme": "AQUA",
"Cookie": ";;;;",
"Cache-Control": "no-cache",
"Accept-Encoding": "identity",
"userid": "",
"ice-auth-appkey": "37893",
"ice-auth-sign": g_ice_auth_sign(timestamp),# "e58dc1fb0153151edb583d13142a0039df046e447a899fe0406bd61434b394248f0f31a54dbef7adea4a89bd779a09c0ac32bdb891901019c1455ce33c6cb0cc",
"ice-auth-timestamp": timestamp,# "1740129904523",
"Host": "customer.yueyequan.cn",
"Connection": "Keep-Alive"
}

response = requests.get(url, params=params, headers=headers)
print(response.text)
print(response.status_code)