样本地址: aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzc0NjE5NDg=
ssl pinning 绕过
首先抓包直接打开是没有网络的,我用算法助手的升级版 trustMe 也不行,说明普通的 ssl pinning 是没用的,说明可能是在 so 层做的防护,hook 一下 dlopen,看一下哪些 so 在最前面进行加载的,也不说最前面吧,相对靠前

大名鼎鼎的六神,网上一搜就知道是 libsscronet.so 中对 so 进行的 ssl pinning 校验的,拖到 ida 中分析一下
问一下 ai,对于这种 so,我应该关注哪些函数

进去之后在导入函数中搜一下
SSL_CTX_set_custom_verify 这个函数就很像啊,跟刚才 gpt 跟我说的不能说有点类似,只能说一模一样了,进去看一下
1
2
3
4
5
|
// attributes: thunk
__int64 SSL_CTX_set_custom_verify()
{
return __imp_SSL_CTX_set_custom_verify();
}
|
发现就是个跳板函数,会跳转到 __imp_SSL_CTX_set_custom_verify 这个函数,这个函数继续往下跟发现跟不到个啥了,导入函数,C 语言中应该有相应的代码实现,直接问下 gpt 有没有相关的原型函数
1
2
3
4
5
|
void SSL_CTX_set_custom_verify(
SSL_CTX *ctx,
int mode,
enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert)
);
|
其中的这个 mode 一般有以下取值
1
2
3
4
5
|
SSL_VERIFY_NONE // 0x00
SSL_VERIFY_PEER // 0x01
SSL_VERIFY_FAIL_IF_NO_PEER_CERT // 0x02
SSL_VERIFY_PEER_IF_NO_OBC // 0x04
SSL_VERIFY_CLIENT_ONCE // 0x08
|
其他的都不重要,知道 mode 为 0 是不进行强校验就够了,也就是说我可以直接 hook 这个函数,返回 0 就可以了,可以使用 frida 脚本,进行 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
|
function hook_dlopen(module_name, fun) {
var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
if (android_dlopen_ext) {
Interceptor.attach(android_dlopen_ext, {
onEnter: function (args) {
var pathptr = args[0];
if (pathptr) {
this.path = (pathptr).readCString();
if (this.path.indexOf(module_name) >= 0) {
this.canhook = true;
}
}
},
onLeave: function (retval) {
if (this.canhook) {
let verifyadd = Module.getExportByName("libsscronet.so","SSL_CTX_set_custom_verify");
Interceptor.attach(verifyadd,{
onEnter(args){
Interceptor.attach(args[2],{
onLeave(retval){
console.log("Hook成功!强制verify返回 0x0");
retval.replace(0x0);
}
})
}
})
}
}
});
}
}
hook_dlopen("libsscronet.so");
|
接着,我是直接抓的登录包,毕竟抓这个包最明显

参数也确实挺多的,这就是大名鼎鼎的六神吗
这种大型的 app,这种关键参数涉及到的算法不太可能是在 Java 层生成的(因为我刚才搜索字段,直接给 jadx 卡死了,占22G 内存,总共才 32G 啊),那就只能是在 native 层生成的,像请求头这种东西,一般是在发包请求之前进行构造的吧,还是继续分析 libsscronet.so 这个库,那它是在哪儿添加的请求头呢?
参考了一下大佬的文章,发现是在 http_request_headers.cc 这个文件中进行添加的

跳转过去,对这个函数进行 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
|
const soName = "libsscronet.so";
const base = Module.findBaseAddress(soName);
if (base === null) {
console.log("[-] module not found");
} else {
const idaBase = 0x0;
const funcOffset = 0x37ED64;
const target = base.add(funcOffset - idaBase);
Interceptor.attach(target, {
onEnter(args) {
var key = args[1].readPointer().readCString();
var value = args[2].readPointer().readCString();
// console.log("\n==== sub_37ED64 called ====");
// console.log("key = " + key);
// console.log("value = " + value);
if(key == "X-Gorgon"){
console.log("X-Gorgon堆栈信息如下")
console.log(key,'==>',value);
console.log('SetHeaders called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n');
}
},
onLeave(retval) {
// console.log("ret = " + retval);
}
});
}
|
得到的信息如下:

跳转到偏移 0x47abc8 处,看一下

这里的 v153 代表 key,v157 代表 value,从这里看不太可能是在这个网络库中进行生成的,继续往上进行溯源

而当我看到 v73 的时候,直接给我引向了 X23 寄存器

在之前的 frida 代码中继续看一下这个寄存器指向的值是在哪儿,找 gpt 给我写了一份 frida hook 的代码,hook 结果如下(不得不多,ai 真是太好用了):
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
|
[Pixel 2::抖音 ]->
========== BLR X23 ==========
[target ] 0x79a67f3e38
[module ] `libmetasec_ml`.so
[offset ] 0x2a6e38
[symbol ] 0x79a67f3e38 libmetasec_ml.so!0x2a6e38
[x0/v74] 0x7a7a468e40 -> https://log0-misc-lf.amemv.com/service/2/app_log/?version_code=380000&device_platform=android&device_id=4285258443570425&aid=1128&iid=4285258442771721&tt_data=a
[x1/v75] 0x787c223d00 -> cookie
passport_csrf_token=43311270ac30c95568130c5db23a83e8; passport_csrf_token_default=43311270ac30c95568130c5db23a83e8; store-region=cn-yn; store-region-src=did; install_id=4285258442771721; ttreq=1$3b3ffd2e9bc05d9f58d58ec2561b0f25fdd413ad; odin_tt=87d6142c75744770c2aaf6011f3cf458125cc74125923869cf45448563276f68a5a773584bb305de007f5969b3438c1990a2abf706b965e1cbb08f7c8d61ac37c433ecd67ea7464b5c0d52815eade962
log-encode-type
zstd
log-encode-token
0
x-tt-dt
AAATEBUCNJWPC5KV7FWGOTXDPYJ2DVUKD6KCB5EDEEPLX3HZ4C76BU46M2VJYG2YUF2T45VSXEBAN37FBI2UI54KJBCLRTPUHJF3AT63PL4ITCVG555LCHHJVVTU7FGX3G7E277OXE364WWTTKSMN3Y
activity_now_client
1773932331119
x-ss-req-ticket
1773932379205
x-vc-bdturing-sdk-version
4.1.1.cn
sdk-version
2
passport-sdk-settings
device_transfer_s_0,device_transfer_ab_0
passport-sdk-version
601581
content-type
application/octet-stream;tt-data=a
x-ss-stub
86245E39DA5BFEC362A9DD92634D85C1
content-length
7942
x-tt-store-region
cn-yn
x-tt-store-region-src
did
x-tt-request-tag
s=-1;p=0
x-ss-dp
1128
x-tt-trace-id
01-069bfdeb0df396b7b4cbcf95f2e10468-069bfdeb0df396b7-00
user-agent
com.ss.android.ugc.aweme/380001 (Linux; U; Android 10; zh_CN_#Hans; Pixel 2; Build/QQ3A.200805.001; Cronet/TTNetVersion:6f1e308d 2025-12-08 QuicVersion:21ac1950 2025-11-18)
accept-encoding
gzip, deflate, br
---- target enter ----
[arg0] 0x7a7a468e40 -> https://log0-misc-lf.amemv.com/service/2/app_log/?version_code=380000&device_platform=android&device_id=4285258443570425&aid=1128&iid=4285258442771721&tt_data=a
[arg1] 0x787c223d00 -> cookie
passport_csrf_token=43311270ac30c95568130c5db23a83e8; passport_csrf_token_default=43311270ac30c95568130c5db23a83e8; store-region=cn-yn; store-region-src=did; install_id=4285258442771721; ttreq=1$3b3ffd2e9bc05d9f58d58ec2561b0f25fdd413ad; odin_tt=87d6142c75744770c2aaf6011f3cf458125cc74125923869cf45448563276f68a5a773584bb305de007f5969b3438c1990a2abf706b965e1cbb08f7c8d61ac37c433ecd67ea7464b5c0d52815eade962
log-encode-type
zstd
log-encode-token
0
x-tt-dt
AAATEBUCNJWPC5KV7FWGOTXDPYJ2DVUKD6KCB5EDEEPLX3HZ4C76BU46M2VJYG2YUF2T45VSXEBAN37FBI2UI54KJBCLRTPUHJF3AT63PL4ITCVG555LCHHJVVTU7FGX3G7E277OXE364WWTTKSMN3Y
activity_now_client
1773932331119
x-ss-req-ticket
1773932379205
x-vc-bdturing-sdk-version
4.1.1.cn
sdk-version
2
passport-sdk-settings
device_transfer_s_0,device_transfer_ab_0
passport-sdk-version
601581
content-type
application/octet-stream;tt-data=a
x-ss-stub
86245E39DA5BFEC362A9DD92634D85C1
content-length
7942
x-tt-store-region
cn-yn
x-tt-store-region-src
did
x-tt-request-tag
s=-1;p=0
x-ss-dp
1128
x-tt-trace-id
01-069bfdeb0df396b7b4cbcf95f2e10468-069bfdeb0df396b7-00
user-agent
com.ss.android.ugc.aweme/380001 (Linux; U; Android 10; zh_CN_#Hans; Pixel 2; Build/QQ3A.200805.001; Cronet/TTNetVersion:6f1e308d 2025-12-08 QuicVersion:21ac1950 2025-11-18)
accept-encoding
gzip, deflate, br
[ret ] 0x7962937600 -> X-Perseus # 1
eaeee5ynOZskw1llR2hm8+lJKhgcJPtKXM6OkB1vcOil+HVeDQiP+Ut/EXHY4DxpD9rXqytpWqczMCvDv2roCE/eRlLg1x6GgYLRp2JjHNQv4jOyzqnsRn1XRkvrtg9OTpjtCU0TGZtC52v3EPZLc4k4FQH7qvWdvuf62n8T3bgbSPEHLFeOqzdXvB56iNpYrAzV8u5tHbWvq4q/+0BFFrQSZ0iW8HXX3SeSQL0nvv9/pji4hRtoWZwg8prIAakJykHIPDggP+d+z7uw9cWQ4Nyy+ZhK1EShp9D3oBpZBpcPK4N+ywV2ddocGXewx2gpNz5DLOymxyd6Jg1xhn6/ePdmp0UHLlPWslMJ2+D5QS51M6MsWgNs0TEzlPUzmeYR6vt1bnGVix6tYxSSziobNrThnSLpeiy1EFruU9dGEScCMkZu72ihet8y5WctEXcbylIwjBhWLD6bEKV4fpIDF3hYDfGSDqvEQTroPWhNudoVaajZlw0nEz/TLmj7hLcW89l2lfZWynQgxTnBvdBOzqGCgN9vyEopBG8RInm4+I28sxATas9B5sojhectRbSCzSLWCIYOHboPxPLSjdeMOoVoVWoXbRc8WP4UKuUg+YVrBW31X4R1v9tvyGjzsWxWTK5iQdCVyOWmXrBtPKUDHI9mTZnHfXeTsRtsZKjwySV0B40BMN9GOaoA2l4ltGXO1eNB9nOobbBrP73sFCZzFXLrgnAo/KDxCRcUGE+/dhwlAoGs0FgtvORo5mHDY8v7x1Dv5vXax8uqW+bYFuFh3vu6OSp/rIJYa+KzYnRSRXbe+Zu9MzMxSi9NIFuQB1cCPAdBTjlaJhlQAZHB+HCGh7f8fG6bcpock9/wXeQFDoibFWR1lNiGIDnNMYtHBdTM6CnRHYtlKpW+0C+BhA/u+Q==
X-Medusa # 2
jA+8aeCVl0PJlBP4CsW+A0k5GJdG4AAN7JZxNnkc3L4Auhy097W94A0oAJIHmIQSzh4JlOFbEmCqNTjyPiNUlDX+Go/Aev2LLy3Wbb4LuRMXtUiaZ5riW7/gE4JPovQqf71xz8hEVCHavVVSZBCzb+ModMO6eToxM3wTPQA6+D8fS4KZQphjENUVIVb4nHDq+MLLUtAJ+t5nCyZqQX54bJd57z9mOF07JJbd0x+Hx9JBlSYNHl2tGtVDixKKOtS5zgnYQvwcRmmLkTu+IbhUANZk2mH+uljhw3l7Wri8HZ8+VOHBdcnK6oSSK093U9JEppDDdMrdcSesnhOhMaUSjXcsM3aYY8L9p6z//aep+0sa
X-Argus # 3
iw+8aQ==
X-Helios # 4
mzldD91aKzfTcF8SCMCCGn4tdFZJxImB4NNpRlikIYB7Kvtb
X-Ladon # 5
r3kMdQ==
X-Khronos # 6
1773932427
X-Gorgon # 7
8404a00c0405a19810f52af5ffa35cc68fa1f92bebe2762947e0
|
对上了,这里请求参数中也正好是 \r\n 作为分割的,最后的返回值就是七神
跳转到 libmetasec_ml.so 中的偏移地址0x2a6e38

发现处在 sub_2A6E38,这个应该就是外部加密参数生成的 so 中的加密函数了,接着就可以 hook 一下这个函数,看一下参数是什么,接着好去到 unidbg 中进行模拟加密参数的生成,写一下 frida 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
const base = Module.findBaseAddress("libmetasec_ml.so");
var func_addr = base.add(0x2A6E38);
console.log("baseAddr from hook", base);
Interceptor.attach(func_addr, {
onEnter: function (args) {
console.log("=============入参开始==================")
var arg0 = args[0].readUtf8String();
var arg1 = args[1].readUtf8String();
console.log("参数1" + arg0);
console.log("参数2" + arg1);
},
onLeave: function (retval) {
console.log("返回值地址:: " + retval);
console.log("返回值:: " + retval.readUtf8String());
console.log("=============返回值结束==================")
}
});
|
hook 结果如下:
参数 1 就是请求的 url+一堆参数拼接起来的结果,这一点跟 web 有点像,参数 2 就是一堆的请求参数,用 \r\n 进行分割
unidbg 模拟执行
先弄个架子在这儿,这个用 ai 改造了一下
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
|
package com.douyin;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.arm.backend.Unicorn2Factory;
import com.github.unidbg.file.FileResult;
import com.github.unidbg.file.IOResolver;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.AbstractJni;
import com.github.unidbg.linux.android.dvm.BaseVM;
import com.github.unidbg.linux.android.dvm.DalvikModule;
import com.github.unidbg.linux.android.dvm.DvmClass;
import com.github.unidbg.linux.android.dvm.VaList;
import com.github.unidbg.linux.android.dvm.VM;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.hook.hookzz.HookZz;
import com.github.unidbg.hook.hookzz.IHookZz;
import com.github.unidbg.hook.hookzz.HookEntryInfo;
import com.github.unidbg.arm.context.RegisterContext;
import com.github.unidbg.virtualmodule.android.AndroidModule;
import java.io.File;
public class DouYin extends AbstractJni implements IOResolver {
// ========== 每次新项目只改这里 ==========
// 模拟器位数:so在armeabi-v7a目录下填false,arm64-v8a目录下填true
private static final boolean IS_64BIT = true;
// app包名(随意,一般填真实包名)
private static final String PROCESS_NAME = "com.ss.android.ugc.aweme";
// apk路径,不需要apk时填null(填null时LOAD_BY_NAME必须为false)
private static final String APK_PATH = "apks/douyin/douyin.apk";
// so加载方式:
// false = 传文件路径(用SO_PATH),不依赖apk,最常用
// true = 传库名(用SO_NAME),unidbg自动去apk内查找,必须提供APK_PATH
private static final boolean LOAD_BY_NAME = true;
private static final String SO_PATH = ""; // LOAD_BY_NAME=false时生效
private static final String SO_NAME = "metasec_ml"; // LOAD_BY_NAME=true时生效,不带lib前缀和.so后缀
// 是否打印JNI调用细节,调试时改true
private static final boolean VERBOSE = true;
// ========================================
public static AndroidEmulator emulator;
public static Memory memory;
public static VM vm;
public static Module module;
// 1. 构造方法 —— 初始化模拟器
public DouYin() {
// 1. 创建模拟器(32/64位由IS_64BIT控制)
emulator = IS_64BIT
? AndroidEmulatorBuilder.for64Bit().setProcessName(PROCESS_NAME).addBackendFactory(new Unicorn2Factory(true)).build()
: AndroidEmulatorBuilder.for32Bit().setProcessName(PROCESS_NAME).addBackendFactory(new Unicorn2Factory(true)).build();
// 2. 获取内存对象
memory = emulator.getMemory();
// 3. 设置安卓SDK版本(只支持19、23)
memory.setLibraryResolver(new AndroidResolver(23));
// 4. 创建虚拟机
vm = APK_PATH != null
? emulator.createDalvikVM(new File(APK_PATH))
: emulator.createDalvikVM();
vm.setJni(this);
vm.setVerbose(VERBOSE);
// 5. 加载so文件(两种方式由LOAD_BY_NAME控制)
DalvikModule dm = LOAD_BY_NAME
? vm.loadLibrary(SO_NAME, false)
: vm.loadLibrary(new File(SO_PATH), false);
// 6. 动态注册才需要执行JNI_OnLoad
dm.callJNI_OnLoad(emulator);
// 7. 获取module对象(后续拿基址、偏移等)
module = dm.getModule();
}
// 5. main方法 —— 右键直接运行
public static void main(String[] args) {
DouYin douYin = new DouYin();
}
@Override
public FileResult resolve(Emulator emulator, String pathname, int oflags) {
System.out.println("pathname:" + pathname);
return null;
}
}
|
运行,发现报错

这个一般就是当前的这个 so 文件依赖于 android.so 文件,这个 unidbg 为我们实现了相关的虚拟模块
1
|
new AndroidModule(emulator,vm).register(memory);
|
接着又发现 Jni 层在寻找 MS 这个类,但是我在 unidbg 中并没有引用这个类啊,你肯定是找不到的啊

去 jadx 看了一下这个类,发现继承 i2 这个类,i2 又继承 y2 这个类

在 JNI_Onload 调用之前声明这个类就可以了
1
|
MS = vm.resolveClass("com.bytedance.mobsec.metasec.ml.MS",vm.resolveClass("ms.bd.c.i2",vm.resolveClass("ms.bd.c.y2")));
|
继续,发生报错
1
2
3
4
5
|
java.lang.UnsupportedOperationException: com/bytedance/mobsec/metasec/ml/MS->b(IIJLjava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethodV(AbstractJni.java:504)
at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethodV(AbstractJni.java:438)
at com.github.unidbg.linux.android.dvm.DvmMethod.callStaticObjectMethodV(DvmMethod.java:59)
at com.github.unidbg.linux.android.dvm.DalvikVM64$112.handle(DalvikVM64.java:1836)
|
往上找,就找到了下面的这个地方

先看一下参数是什么
1
2
3
4
5
6
7
8
9
10
|
@Override
public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {
switch(signature){
case "com/bytedance/mobsec/metasec/ml/MS->b(IIJLjava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;":{
int arg = vaList.getIntArg(0);
System.out.println("参数==>"+arg);
}
}
return super.callStaticObjectMethodV(vm, dvmClass, signature, vaList);
}
|
得到的结果是:

然后就可以直接补了,去 jadx 中看一下这个分支,可以发现返回值就是 2,补上

ok,继续,然后又报错了
1
2
3
4
|
java.lang.UnsupportedOperationException: java/lang/Long->longValue()J
at com.github.unidbg.linux.android.dvm.AbstractJni.callLongMethodV(AbstractJni.java:236)
at com.github.unidbg.linux.android.dvm.AbstractJni.callLongMethodV(AbstractJni.java:231)
at com.github.unidbg.linux.android.dvm.DvmMethod.callLongMethodV(DvmMethod.java:84)
|
补上
1
2
3
4
5
6
7
8
9
|
@Override
public long callLongMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
switch (signature){
case "java/lang/Long->longValue()J":{
return (Long)dvmObject.getValue();
}
}
return super.callLongMethodV(vm, dvmObject, signature, vaList);
}
|
然后,然后这儿就结束了,接着就需要进行主动调用了

它的这个参数太多了,干脆就直接写成一个文件的形式然后读取吧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public void metaSec() throws IOException {
byte[] urlBytes = Files.readAllBytes(Paths.get("apks/douyin/url.txt"));
byte[] headerBytes = Files.readAllBytes(Paths.get("apks/douyin/headers.txt"));
MemoryBlock urlBlock = memory.malloc(urlBytes.length + 1, true);
UnidbgPointer urlPtr = urlBlock.getPointer();
urlPtr.write(0, urlBytes, 0, urlBytes.length);
MemoryBlock headerBlock = memory.malloc(headerBytes.length + 1, true);
UnidbgPointer headerPtr = headerBlock.getPointer();
headerPtr.write(0, headerBytes, 0, headerBytes.length);
Number result = module.callFunction(emulator, 0x2A6E38, urlPtr, headerPtr);
UnidbgPointer resultPtr = memory.pointer(result.longValue());
System.out.println(resultPtr.getString(0));
}
|
接着又报错

这个还是跟上面一样,去 jadx 中进行查看
然后报错
1
2
3
|
java.lang.UnsupportedOperationException: java/lang/Integer->getBytes(Ljava/lang/String;)[B
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:262)
|
直接补就行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Override
public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
switch (signature) {
case "java/lang/Integer->getBytes(Ljava/lang/String;)[B": {
String str = dvmObject.getValue().toString();
String charset = vaList.getObjectArg(0).getValue().toString();
System.out.println("getBytes str=" + str + " charset=" + charset);
try {
return new ByteArray(vm, str.getBytes(charset));
} catch (Exception e) {
return new ByteArray(vm, str.getBytes());
}
}
}
return super.callObjectMethodV(vm, dvmObject, signature, vaList);
}
|
接着又出现了
1
2
|
参数==>33554433
参数==>33554434
|
去 jadx 找就行
接着,又报错
1
2
3
4
5
6
|
java.lang.UnsupportedOperationException: java/lang/Thread->getStackTrace()[Ljava/lang/StackTraceElement;
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
at com.douyin.DouYin.callObjectMethodV(DouYin.java:161)
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:262)
at com.github.unidbg.linux.android.dvm.DvmMethod.callObjectMethodV(DvmMethod.java:89)
at com.github.unidbg.linux.android.dvm.DalvikVM64$32.handle(DalvikVM64.java:559)
|
直接补
1
2
3
4
5
6
7
8
|
case "java/lang/Thread->getStackTrace()[Ljava/lang/StackTraceElement;":{
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
DvmObject[] objs = new DvmObject[elements.length];
for (int i = 0; i < elements.length; i++) {
objs[i] = vm.resolveClass("java/lang/StackTraceElement").newObject(elements[i]);
}
return new ArrayObject(objs);
}
|
继续报错
1
2
3
4
5
|
java.lang.UnsupportedOperationException: java/lang/StackTraceElement->getClassName()Ljava/lang/String;
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
at com.douyin.DouYin.callObjectMethodV(DouYin.java:170)
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:262)
at com.github.unidbg.linux.android.dvm.DvmMethod.callObjectMethodV(DvmMethod.java:89)
|
直接补
1
2
3
4
|
case "java/lang/StackTraceElement->getClassName()Ljava/lang/String;":{
StackTraceElement stackTraceElement = (StackTraceElement)dvmObject.getValue();
return new StringObject(vm,stackTraceElement.getClassName());
}
|
继续报错
1
2
3
4
5
|
java.lang.UnsupportedOperationException: java/lang/StackTraceElement->getMethodName()Ljava/lang/String;
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
at com.douyin.DouYin.callObjectMethodV(DouYin.java:167)
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:262)
at com.github.unidbg.linux.android.dvm.DvmMethod.callObjectMethodV(DvmMethod.java:89)
|
直接补
1
2
3
4
|
case "java/lang/StackTraceElement->getMethodName()Ljava/lang/String;":{
StackTraceElement stackTraceElement = (StackTraceElement)dvmObject.getValue();
return new StringObject(vm,stackTraceElement.getMethodName());
}
|
仍在报错
1
2
3
4
5
|
java.lang.UnsupportedOperationException: java/lang/Thread->getBytes(Ljava/lang/String;)[B
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
at com.douyin.DouYin.callObjectMethodV(DouYin.java:171)
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:262)
at com.github.unidbg.linux.android.dvm.DvmMethod.callObjectMethodV(DvmMethod.java:89)
|
在补之前还需要补一下这个分支的数据
返回个版本号
继续补
1
2
3
4
|
case "java/lang/Thread->getBytes(Ljava/lang/String;)[B":{
String arg = vaList.getObjectArg(0).getValue().toString();
return new ByteArray(vm,arg.getBytes(StandardCharsets.UTF_8));
}
|
接着,就能够出值了

能不能用,不知道,算法分析后面再写吧,参数太多了,一篇文章不一定能写完