1.1 tiktok

frida 抓包实战

环境准备

打开 Postern 设置代理, 打开电脑抓包软件 Proxyman, 证书要自己先装好,这边不做过多的介绍!

image-20230215102836782

可以看到此时有一台设备已经连接成功了!

image-20230215102851095

对于 tiktok 这种需要翻墙才可以访问的还可以在你的抓包软件上加入外部代理,外部代理的设置指向你的代理服务,例如我的服务是 Clash, 就指向 7890 端口!

image-20230215103522464
image-20230215103553029

抓包步骤

此时打开 tiktok,尝试抓包,发现居然没有网络,抓包软件上全是握手失败,所以可能是存在 SSL 证书校验之类的。

image-20230215104112634
image-20230215104117724

此时我们可以使用 Frida Hook 一下证书校验,这边有一个通用的抖音系的 hook 脚本, 因为抖音这边需要 hook so文件才可以 ,Hook 脚本如下:

// 先执行端口映射
// adb forward tcp:27042 tcp:27042

// frida -U -f xxx -l .\ssl_bp.js --no-pause
// frida -U -f com.zhiliaoapp.musically -l .\ssl_bp.js --no-pause
// 抖音正版
// frida -H 127.0.0.1 -f com.ss.android.ugc.aweme -l .\ssl_bp.js --no-pause
// frida -U -f com.ss.android.ugc.aweme -l .\ssl_bp.js --no-pause

// 抖音极速版
// com.ss.android.ugc.aweme.lite
//  frida -U -f com.ss.android.ugc.aweme.lite -l .\ssl_bp.js --no-pause

// 番茄小说
// com.dragon.read
// frida -U -f com.dragon.read -l .\ssl_bp.js --no-pause
function bypass() {
    Process.enumerateModules({
        onMatch: function (module) {
            //console.log('Module name: ' + module.name + " - Base Address: " + module.base.toString());
            if (module.name == "libsscronet.so") {
                // console.log("libsscronet.so matched");
                // var base = Module.findBaseAddress("libsscronet.so");
                // var method1 = base.add(0x163E90).add(0x1);
                // Interceptor.attach(method1,{
                // 	onEnter:function(args){
                // 	},
                // 	onLeave:function(retval){
                // 		console.log("抓包校验保护已绕过:",retval)
                // 		if(retval == 0x1){
                // 			retval.replace(0x0)
                // 		}

                // 	}
                // });
                var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
                if (android_dlopen_ext != null) {
                    Interceptor.attach(android_dlopen_ext, {
                        onEnter: function (args) {
                            var soName = args[0].readCString();
                            if (soName.indexOf("libsscronet.so") != -1) {
                                this.loaded = true;
                            }
                        },
                        onLeave: function (retval) {
                            if (this.loaded) {
                                hook_set_custom_verify();
                            }
                        }
                    });
                }
            }
        },
        onComplete: function () { }
    });

    /*var base = Module.findBaseAddress("libsscronet.so");
    var method1 = base.add(0x163E90).add(0x1);
    Interceptor.attach(method1,{
        onEnter:function(args){
        },
        onLeave:function(retval){
            console.log("抓包校验保护已绕过:",retval)
            if(retval == 0x1){
                retval.replace(0x0)
            }

        }
    });*/
}

function main() {
	// 8.0以下所有的so加载都通过dlopen
    var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
    //var android_dlopen_ext = Module.findExportByName(null, "dlopen"); 
    if (android_dlopen_ext != null) {
        Interceptor.attach(android_dlopen_ext, {
            onEnter: function (args) {
                var soName = args[0].readCString();
                if (soName.indexOf("libsscronet.so") != -1) {
                    this.loaded = true;
                }
            },
            onLeave: function (retval) {
                if (this.loaded) {
                    // hook_xlog();
                    hook_set_custom_verify();
                }
            }
        });
    }
}



function hook_set_custom_verify() {
    var set_custom_verify = Module.findExportByName("libttboringssl.so", "SSL_CTX_set_custom_verify");
	console.log("set_custom_verify", set_custom_verify);
    Interceptor.attach(set_custom_verify, {
        onEnter: function (args) {
			console.log(args[2]);
            var callback = args[2];
			console.log("callback:", callback);
            hook_callback(callback);
        }, onLeave(retval) {
        }
    });
}

function hook_callback(callback) {
    Interceptor.attach(callback, {
        onLeave(retval) {
            console.log("verify callback return:", retval);
            retval.replace(0); // 0 就是成功
        }
    });
}

function hook_xlog(){
    Java.perform(function () {
    var ba = Java.use('com.ss.android.common.applog.AppLog');

    ba.getLogEncryptSwitch.implementation = function () {
        return false;
    }
})
}

//setImmediate(function(){
//	setTimeout(main, 5000);
//});
setImmediate(main, 5000);
// setImmediate(bypass);
  1. 连接设备

使用 USB 连接设备

image-20230215104356408
  1. 启动 frida 服务

10:46:28 › adb shell
OnePlus6:/ $ su
OnePlus6:/ # cd data/local/tmp/
OnePlus6:/data/local/tmp # ls
frd-16.0.8 frida-server-14.2.18-android-arm64 re.frida.server
OnePlus6:/data/local/tmp # ./fr
frd-16.0.8                          frida-server-14.2.18-android-arm64
OnePlus6:/data/local/tmp # ./frida-server-14.2.18-android-arm64
image-20230215104712391
  1. 开始 Hook

先找一下当前包名,可以使用以下命令获取,要开打开 tiktok

adb shell dumpsys window | grep mCurrentFocus

这个命令会返回当前打开的应用包名以及 activity, 可以看到当前的包名是:com.zhiliaoapp.musically

image-20230215105041424

启动 firda hook, 输入下面的命令

frida -U -f com.zhiliaoapp.musically -l ssl_bp.js

执行完这条命令之后会发现,tiktok 会自动重启

image-20230215105302507

并且也已经有网络了,证明我们 Hook 成功了

image-20230215105802190
image-20230215105858333

可以看到抓包软件里面也有了网络请求包了,这个时候我们就可以自己慢慢分析请求了!

image-20230215105846984
image-20230215110021776

踩坑记录

  1. 当使用低版本的 frida 时,发现 hook 完毕进程就一直卡住了

image-20230215114225263

frida 返回结果如上,发现一运行完就直接变成这样了,然后 tiktok 一直卡在启动首页,这个是因为低版本有一个参数需要添加(但是我也不知道这个参数的作用,后面有空了在研究),那就是 --no-pause

所以当用低版本的参数,如 14.2.18 时,真正的启动命令应该为:

frida -U -f com.zhiliaoapp.musically -l ssl_bp.js --no-pause
image-20230215114314379
  1. 程序第一次还能够抓到包,第二次就抓不到了

这个问题在多次尝试后发现好像和抓包软件有关,在 Mac 上的 proxyman 抓不到包了,并且抓到的包都没有域名,但是尝试使用 windowscharles 就可以抓到,所以还是建议多尝试不同的软件!

image-20230215114715453

最后更新于

这有帮助吗?