Eltion/Tiktok-SSL-Pinning-Bypass

Question: How Tiktok detect that SSL pinning bypassed?

Sasa2023 opened this issue ยท 35 comments

Hi,

First thank you very much for your wonderful job here, it works like charm.

Second, The problem is that somehow Tiktok actually detect that SSL pinning is bypassed, so most of actions such as follow is not working.

Do you have an idea how this happens?

Thanks you again, I appreciated your work,

Sasa

My account permanently banned after I use the patched apk of v25.9.4. o(T_T)o

But I learn a lot from this project. Thanks.

I'll look into this soon, it could be that they are detecting that frida-gadget is being used :)

Have you had the opportunity to review? They also blocked the registration process at the moment.

@arifaslaan not yet :(

Hi! I am following this topic as well.

I am working on a Frida Script to bypass on iOS. If anybody interested, this is all I have so far:

console.log("iOS 15 Bypass SSL Pinning")

console.log('\n')

var sslSetCustomVerify
var sslCtxSetCustomVerify
var sslGetPskIdentity

try {
	Module.ensureInitialized("libboringssl.dylib")
    console.log("libboringssl.dylib module loaded.")
} catch(err) {
	console.log("libboringssl.dylib module not loaded. Trying to manually load it.")
	Module.load("libboringssl.dylib");  
}

console.log('\n')

const customVerifyCallback = new NativeCallback(function (ssl, out_alert) {
    console.log(ssl)
    console.log(out_alert)
	console.log(`[!!!!] Custom SSL context verify callback called. Returning SSL_VERIFY_NONE`)
	return 0
}, "int", ["pointer", "pointer"])

const customCTXVerifyCallback = new NativeCallback(function (ssl, out_alert) {
    console.log(ssl)
    console.log(out_alert)
	console.log(`[!!!!] Custom SSL CTX context verify callback called. Returning SSL_VERIFY_NONE`)
	return 0
}, "int", ["pointer", "pointer"])

try {
    console.log("Setting custom verify callback...")

	sslSetCustomVerify = new NativeFunction(
		Module.findExportByName("libboringssl.dylib", "SSL_set_custom_verify"),
		'void', ['pointer', 'int', 'pointer']
	);
	Interceptor.replace(sslSetCustomVerify, new NativeCallback(function(ssl, mode, callback) {
		sslSetCustomVerify(ssl, mode, customVerifyCallback)
	}, 'void', ['pointer', 'int', 'pointer']))

    console.log("Custom verify callback set.")
} catch (e) {
    console.log("Cannot set custom verify callback. Trying SSL_CTX_set_custom_verify")

    try {
        sslCtxSetCustomVerify = new NativeFunction(
            Module.findExportByName("libboringssl.dylib", "SSL_CTX_set_custom_verify"),
            'void', ['pointer', 'int', 'pointer']
        );
        Interceptor.replace(sslCtxSetCustomVerify, new NativeCallback(function(ssl, mode, callback) {
            console.log(`SSL_CTX_set_custom_verify(), setting custom callback.`)
            sslCtxSetCustomVerify(ssl, mode, customCTXVerifyCallback)
        }, 'void', ['pointer', 'int', 'pointer']))
    } catch (e) {
        console.log("Cannot set CTX custom verify callback!")
    }
}

console.log('\n')

try {
    console.log("Setting PSK identity...")

	sslGetPskIdentity = new NativeFunction(
		Module.findExportByName("libboringssl.dylib", "SSL_get_psk_identity"),
		'pointer', ['pointer']
	);

    Interceptor.replace(sslGetPskIdentity, new NativeCallback(function(ssl) {
        console.log(`SSL_get_psk_identity(), returning "fakePSKidentity"`)
        console.log(ssl)
        return "fakePSKidentity"
    }, 'pointer', ['pointer']))

    console.log("PSK identity set.")
} catch (e) {
	console.log("Cannot set PSK identity")
}

Does it work with apps other than Tiktok?

Hi @Eltion and everyone,

Is it possible to hook libsscronet after is has been loaded?

Also I thinks that jsBridge is changing the app behavior at runtime by adding new methods or remove others.

Thanks,
Sasa

@Sasa2023, You can run frida to attach to the process and spawn the app.

frida -U -l .\tiktok-ssl-pinning-bypass.js com.zhiliaoapp.musically 

So you can open app normally then attach frida to it

@Eltion I am actually doing this but the app is crashing or the hook doesn't work and SSL pinning can't be bypassed.

@Sasa2023 Yes actually it won't work. The reason is that method SSL_CTX_set_custom_verify is only called at the beginning when the app opens :(.

@arifaslaan, @hackercxj , @Sasa2023 can you let me know if you're using frida or patched apk when you're getting these problems?

I've added a new function spoofSignature to fake the signature of the patched apk to appear as signed by tiktok with the same signature as the original apk, I think this maybe is how they figured out that the apk was patched.

2fe2089#diff-692fc9858059052547bb966a14284c25c34198dddd6f2665f0e804ef5895e3ac

@arifaslaan, @hackercxj , @Sasa2023 can you let me know if you're using frida or patched apk when you're getting these problems?

Hi Eltion,

I just use patched app. Because it's enough for me. It helps me listen to the app. I don't need to inject with frida again. Actually, I've been dealing with TikTok for about three years. At first, such complex blocking methods did not exist. But right now there is a lot of confusion. I follow all of the things you mentioned above. I'll let you know when I find a solution or something similar. On the Android side, even having the developer options of the phone turned on is a problem in some cases. In fact, all they do is create confusion and complicate the solution. They've always done that. Sorry I went a little off topic.

Best Regards.

I've added a new function spoofSignature to fake the signature of the patched apk to appear as signed by tiktok with the same signature as the original apk, I think this maybe is how they figured out that the apk was patched.

An ingenious idea. I'll let you know the result after I try it.

@arifaslaan thank you :)

@Eltion Wow great work faking the sig is actually works but some actions are still detected, Do you have an idea where it might be check and detect emulator I mean in java layer or native layer!?

Thanks a lot @Eltion for your effort and beautiful work :-)

Sasa

@Sasa2023 You're using an emulator? which one? For me I've tested om my phone, actions like follow work :)

Hi @Eltion Thanks a lot for your reply! first I was using Nox player as it was tested by you but I wasn't able to bypass emulator detection because it prevents some API endpoints then I used a real android device with your great script and everything was fine until my device get blocked first they block the IP then they block the device itself and you know it is not that easy to fake change the device info as Tiktok actually record a great deal of data about the device almost everything including if it is emulator, has frida, has cydia, rooted, jailbreaked and so on.

Also I don't know exactly where the register_device function located which read the phone IMEI and others so I can hook it with frida.

Also I am pretty sure that they detect frida gadget but your great work around by spoofing real app package was able to bypass requests such as follow and login.

@Eltion Thank you so much bro.
Sasa

@Sasa2023 does the normal tiktok app work for you? I'll try later to create a patch with custom frida-gadget, that may help

@Eltion Thank you very much for your reply! Yes the normal tiktok app is working fine with me. It think that the custom frida-gadget is a great idea. if you need any help please let me know.

Hey. Can you guys intercept the tiktok traffic r? I tried with patched apk but could not achieve what I want. Traffic is still encoded.

tiktok detects frida and other things such as root. they get sent (encrypted) over their mssdk security system

I can provide bounty for decrypted traffic

Hello @Eltion! Why does the registration process stop working in the latest version 27.8.1 after adding a signature via apksigner? Do you have some original keystore file?

tiktok detects frida and other things such as root. they get sent (encrypted) over their mssdk security system

Do they detect strong frida too?

Sorry this is a little off topic, but maybe someone here can help me out. Has anyone somehow found a way to use TikTok on an emulator? I have tried many things, but TikTok always recognizes very quickly that I am using an emulator. For example, I have tried different emulators like Bluestack, Nox or AVD and rooted it and changed the fingerprint of the device with Magisk Hide Config, but TikTok still recognizes that I am using an emulator.

p1tsi commented

Hi! I am following this topic as well.

I am working on a Frida Script to bypass on iOS. If anybody interested, this is all I have so far:

console.log("iOS 15 Bypass SSL Pinning")

console.log('\n')

var sslSetCustomVerify
var sslCtxSetCustomVerify
var sslGetPskIdentity

try {
	Module.ensureInitialized("libboringssl.dylib")
    console.log("libboringssl.dylib module loaded.")
} catch(err) {
	console.log("libboringssl.dylib module not loaded. Trying to manually load it.")
	Module.load("libboringssl.dylib");  
}

console.log('\n')

const customVerifyCallback = new NativeCallback(function (ssl, out_alert) {
    console.log(ssl)
    console.log(out_alert)
	console.log(`[!!!!] Custom SSL context verify callback called. Returning SSL_VERIFY_NONE`)
	return 0
}, "int", ["pointer", "pointer"])

const customCTXVerifyCallback = new NativeCallback(function (ssl, out_alert) {
    console.log(ssl)
    console.log(out_alert)
	console.log(`[!!!!] Custom SSL CTX context verify callback called. Returning SSL_VERIFY_NONE`)
	return 0
}, "int", ["pointer", "pointer"])

try {
    console.log("Setting custom verify callback...")

	sslSetCustomVerify = new NativeFunction(
		Module.findExportByName("libboringssl.dylib", "SSL_set_custom_verify"),
		'void', ['pointer', 'int', 'pointer']
	);
	Interceptor.replace(sslSetCustomVerify, new NativeCallback(function(ssl, mode, callback) {
		sslSetCustomVerify(ssl, mode, customVerifyCallback)
	}, 'void', ['pointer', 'int', 'pointer']))

    console.log("Custom verify callback set.")
} catch (e) {
    console.log("Cannot set custom verify callback. Trying SSL_CTX_set_custom_verify")

    try {
        sslCtxSetCustomVerify = new NativeFunction(
            Module.findExportByName("libboringssl.dylib", "SSL_CTX_set_custom_verify"),
            'void', ['pointer', 'int', 'pointer']
        );
        Interceptor.replace(sslCtxSetCustomVerify, new NativeCallback(function(ssl, mode, callback) {
            console.log(`SSL_CTX_set_custom_verify(), setting custom callback.`)
            sslCtxSetCustomVerify(ssl, mode, customCTXVerifyCallback)
        }, 'void', ['pointer', 'int', 'pointer']))
    } catch (e) {
        console.log("Cannot set CTX custom verify callback!")
    }
}

console.log('\n')

try {
    console.log("Setting PSK identity...")

	sslGetPskIdentity = new NativeFunction(
		Module.findExportByName("libboringssl.dylib", "SSL_get_psk_identity"),
		'pointer', ['pointer']
	);

    Interceptor.replace(sslGetPskIdentity, new NativeCallback(function(ssl) {
        console.log(`SSL_get_psk_identity(), returning "fakePSKidentity"`)
        console.log(ssl)
        return "fakePSKidentity"
    }, 'pointer', ['pointer']))

    console.log("PSK identity set.")
} catch (e) {
	console.log("Cannot set PSK identity")
}

Are you sure that this script works for iOS bypass? I tried with TikTok v29.2.0 and it seems it doesn't work.

This works in TIKTOK iOS app installed in playcover in M1 macs

first open tiktok. and finds its PID and then use this command.

frida -p PID -l script.js

// Existing hook for TTHttpTask
Interceptor.attach(ObjC.classes.TTHttpTask["- skipSSLCertificateError"].implementation, {
    onEnter: function (args) {},
    onLeave: function (retval) {
        console.log('Overriding -> TTHttpTask skipSSLCertificateError : ');
        retval.replace(0x1)
    }
});


@p1tsi @kaykyr

This works in TIKTOK iOS app installed in playcover in M1 macs

first open tiktok. and finds its PID and then use this command.

frida -p PID -l script.js

// Existing hook for TTHttpTask
Interceptor.attach(ObjC.classes.TTHttpTask["- skipSSLCertificateError"].implementation, {
    onEnter: function (args) {},
    onLeave: function (retval) {
        console.log('Overriding -> TTHttpTask skipSSLCertificateError : ');
        retval.replace(0x1)
    }
});

@p1tsi @kaykyr

When running tiktok app it crushes auto after few seconds means the PID became unavailable

This works in TIKTOK iOS app installed in playcover in M1 macs
first open tiktok. and finds its PID and then use this command.
frida -p PID -l script.js

// Existing hook for TTHttpTask
Interceptor.attach(ObjC.classes.TTHttpTask["- skipSSLCertificateError"].implementation, {
    onEnter: function (args) {},
    onLeave: function (retval) {
        console.log('Overriding -> TTHttpTask skipSSLCertificateError : ');
        retval.replace(0x1)
    }
});

@p1tsi @kaykyr

When running tiktok app it crushes auto after few seconds means the PID became unavailable

Try on this verison TikTokLRD 24.8.0 ipa you can find it online.

This works in TIKTOK iOS app installed in playcover in M1 macs
first open tiktok. and finds its PID and then use this command.
frida -p PID -l script.js

// Existing hook for TTHttpTask
Interceptor.attach(ObjC.classes.TTHttpTask["- skipSSLCertificateError"].implementation, {
    onEnter: function (args) {},
    onLeave: function (retval) {
        console.log('Overriding -> TTHttpTask skipSSLCertificateError : ');
        retval.replace(0x1)
    }
});

@p1tsi @kaykyr

When running tiktok app it crushes auto after few seconds means the PID became unavailable

Try on this verison TikTokLRD 24.8.0 ipa you can find it online.

Thanks, but I couldn't find a trusted link really I hope you can provide one if you have it available
Cheers

Eltion, bro can you find solution for Bypass SSL piining App like Likee

This works in TIKTOK iOS app installed in playcover in M1 macs

first open tiktok. and finds its PID and then use this command.

frida -p PID -l script.js

frida -p $(frida-ps | sed -n -E 's/^[[:space:]]*([0-9]+)[[:space:]]*TikTok.*/\1/p') -l script.js

This works in TIKTOK iOS app installed in playcover in M1 macs
first open tiktok. and finds its PID and then use this command.
frida -p PID -l script.js

// Existing hook for TTHttpTask
Interceptor.attach(ObjC.classes.TTHttpTask["- skipSSLCertificateError"].implementation, {
    onEnter: function (args) {},
    onLeave: function (retval) {
        console.log('Overriding -> TTHttpTask skipSSLCertificateError : ');
        retval.replace(0x1)
    }
});

@p1tsi @kaykyr

When running tiktok app it crushes auto after few seconds means the PID became unavailable

Try on this verison TikTokLRD 24.8.0 ipa you can find it online.

@abdullahsaeed98 it also works with the latest version TikTokLRD 31.5.0, I've just tested it.

@Eltion Im using this patched APK in my rooted device but the app is keep crashing every time when i'm opening

there is any reason for it? what else we can try here ?