网站和网页的设计原则,wordpress模板商店,手加工外包加工网,网站首页制作案例第一章搞定了,Tk的上网环境,但是还不能抓包,因为Tk系的协议不太一样用的是QUIC协议那我们今天的目标是绕过这个协议,让他降级,实现我们成功抓包的目的(还有会番外篇非降级抓包,可以小小期待一下)环境手机
小米8
版本
33.4.3
准备抓包失败开了抓包以后APP直接是网络无连接了,并且…第一章搞定了,Tk的上网环境,但是还不能抓包,因为Tk系的协议不太一样用的是QUIC协议那我们今天的目标是绕过这个协议,让他降级,实现我们成功抓包的目的(还有会番外篇非降级抓包,可以小小期待一下)环境手机小米8版本33.4.3准备抓包失败开了抓包以后APP直接是网络无连接了,并且抓到的请求也是不正常的,下面我们就开始定位日志分析可以从日志分析入手,看看有没有什么异常的报错使用 adb logcat 命令查看先用 adb logcat -c 请一下日志执行 adb logcat 命令然后打开tiktok app出现发生错误这个页面后停止 adb locat 命令把文件保存到本地进行分析定位(整个日志中,只有此处有发送网络请求而且失败,所以一眼定位这里)日志里找到有一个请求URL的位置并且有一个|Exception in CronetUrlRequest 像是网络错误的请求所以分析一下这个位置jadx反编译拿上面的这个Exception in CronetUrlRequest 去jdax里进行搜索上面搜索到三个位置,后两个是同一个函数,所以hook一下这两个地方,打印下堆栈直接右键复制为Frida片段就可以了1234567891011121314151617Java.perform(function () {let g Java.use(org.chromium.g);g[LIZ].implementation function (i, i2, str) {console.log(g.LIZ is called: i${i}, i2${i2}, str${str});let result this[LIZ](i, i2, str);console.log(g.LIZ result${result});console.log(Java.use(android.util.Log).getStackTraceString(Java.use(java.lang.Throwable).$new()));return result;};let CronetUrlRequest Java.use(com.ttnet.org.chromium.net.impl.CronetUrlRequest);CronetUrlRequest[onError].implementation function (i, i2, i3, str, j) {console.log(CronetUrlRequest.onError is called: i${i}, i2${i2}, i3${i3}, str${str}, j${j});this[onError](i, i2, i3, str, j);console.log(Java.use(android.util.Log).getStackTraceString(Java.use(java.lang.Throwable).$new()));};})打印结果上面图片可以看到所有的打印都是走的CronetUrlRequest.onError这个函数,他是一个Native层的方法 那下面来分析一下So层定位So直接把app文件 重命名一下 .apk 改为.zip直接找到tiktok-33-4-3.zip\lib\arm64-v8a 这里面有很多so文件,怎么定位到我们需要的so文件那我这里使用grep进行搜索grep的作用就是搜索到我们要定位的字符串在那个So文件里grep的安装可以看这个 https://blog.csdn.net/qq_29752857/article/details/140169107把.apk后缀改为.zip压解到一个文件夹cd 到解压文件夹的 \lib\arm64-v8a目录 打开cmd执行命令 grep -r CronetUrlRequest *显示在 libsscronet.so 这个So文件中分析So从\lib\arm64-v8a下面找到libsscronet.so这个文件丢到ida64中按Shift F12 字符串搜索 CronetUrlRequest点击com/ttnet/org/chromium/net/impl/CronetUrlRequest进入sub_1900288↓o 然后按tab键Hook下这个位置 190028这里为了方便注释Hook的代码,拆分开写的主函数123456789101112131415161718function 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) {pass},onLeave: function (retval) {passa}});}}function main() {hook_dlopen(libsscronet.so)}setImmediate(main)注释Hook android_dlopen_ext 监控 .so 加载判断是不是我们要hook的libsscronet.so文件onEnter123456789onEnter: function (args) {var pathptr args[0]; // 读取第一个参数它是一个指向动态库路径的指针if (pathptr) { // 确保指针有效避免 null 访问错误this.path pathptr.readCString(); // 将指针解析成字符串得到动态库的路径if (this.path.indexOf(module_name) 0) { // 判断路径是否包含目标库名this.canhook true; // 发现目标库标记 this.canhook true表示可以 hook}}}注释onEnter 在目标函数android_dlopen_ext执行前触发如果路径是否包含目标库名,把canhook设置为TrueonLeave1234567891011121314onLeave: function (retval) {if (this.canhook) { // 只有在 onEnter 里确认目标库被加载了才会执行 hook 逻辑let base_libsscronet Module.findBaseAddress(libsscronet.so); // 获取 libsscronet.so 的基地址let sub_190028 base_libsscronet.add(0x190028); // 计算 sub_190028 函数的地址基地址 偏移 0x190028console.log(hook, sub_190028); // 打印目标函数的地址便于调试Interceptor.attach(sub_190028, { // Hook 目标函数onEnter(args) {console.log(sub_190028 called, return address:, DebugSymbol.fromAddress(this.returnAddress));// this.returnAddress 是调用 sub_190028 的上层函数的返回地址// DebugSymbol.fromAddress 解析该地址尝试获取调用 sub_190028 的函数名}});}}注释this.returnAddress 返回的是调用者的地址DebugSymbol.fromAddress 是为了把地址转为函数名打印结果按G跳转到 0x18fae8偏移量在V16上点进 sub_18209C这个函数.cc 文件是 C 源代码文件它的作用与 .cpp 文件相同通常用于存放 C 代码跟进sub_182194看到这块信息Hook一下 sub_20E814可以看到第二个是一个String ,所以hook代码要修改一下把第二个参数String也打印onLeave: function (retval) {if (this.canhook) {let base_libsscronet Module.findBaseAddress(libsscronet.so);let sub_20E814 base_libsscronet.add(0x20E814);console.log(hook, sub_20E814);Interceptor.attach(sub_20E814, {onEnter(args) {console.log(sub_20E814 called, return address:,args[1].readCString()), DebugSymbol.fromAddress(this.returnAddress);}});}}输出结果这个地方明显不是,app已经出现连接失败了,后面过了一会才有的打印,说明这个打印已经晚了,如果是我们想要的位置,他应该在检测中进行打印上面的输出其实并没有什么有效信息分析引用那这样我们线索已经断了,先按X看一下这个函数都是有谁引用了 看看有没有线索看了半天感觉也没啥有用的东西,那下面我们整理一下已经有信息,来猜测一下,后续怎么进行那目前我们根据已经有信息,看到代码里有用 ../../net/tt_net/ipc/ipc_channel_reader.cc 这样的方式去写的那可以猜测,我们真正需要Hook的那个函数也有可能是这样加载的,可以字符串搜索一下../../看到有几个目录net base components等,我们是为了解决抓包问题,那很有可能是在net目录下(network),那来搜索一下 ../../net还是比较多的,这个时候可以有选择的看一下,跟网络请求相关的quic ssl 等最后定位到是 ../../net/socket/ssl_client_socket_impl.cc这个文件然后点进来看一下hook下 20E7EC看到有一个叫HandleVerifyResult比较像,我们跳进去看一下0x3174dc如果打印不出 HandleVerifyResult 可以换个手机试下然后向上滑找到函数看一下是谁在引用, 因为怀疑这一段是 错误处理 所以先看一下谁调用他这里有两个点那个都可以,最后都是一个位置,进来之后继续找到函数看一下引用接着点进去,进去以后看到很多个函数都点开看一下,最后定位到sub_4913E8()上面我们可以搜一下SSL_CTX_set_custom_verify这是什么意思第三个参数是一个回调函数,这里他的返回值1表示成功,0表示失败,那我们手动把他Hook为0,让他不支持quic协议,实现降级就能成功绕过校验了~!123456789101112131415161718192021222324252627282930function 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){retval.replace(0x0);}})}})}}});}}成功搞定就可以抓包并且上TikTok了