Tiktok-SSL-Pinning-Bypass icon indicating copy to clipboard operation
Tiktok-SSL-Pinning-Bypass copied to clipboard

Question: How Tiktok detect that SSL pinning bypassed?

Open Sasa2023 opened this issue 2 years ago • 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

Sasa2023 avatar Nov 26 '22 22:11 Sasa2023

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.

hackercxj avatar Dec 13 '22 10:12 hackercxj

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

Eltion avatar Dec 13 '22 10:12 Eltion

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

arifaslaan avatar Dec 15 '22 01:12 arifaslaan

@arifaslaan not yet :(

Eltion avatar Dec 15 '22 02:12 Eltion

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")
}

kaykyr avatar Dec 19 '22 16:12 kaykyr

Does it work with apps other than Tiktok?

demon071 avatar Dec 26 '22 14:12 demon071

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 avatar Jan 05 '23 08:01 Sasa2023

@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 avatar Jan 05 '23 12:01 Eltion

@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 avatar Jan 06 '23 02:01 Sasa2023

@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 :(.

Eltion avatar Jan 11 '23 12:01 Eltion

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

Eltion avatar Jan 11 '23 12:01 Eltion

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.

https://github.com/Eltion/Tiktok-SSL-Pinning-Bypass/commit/2fe2089c80e3edcd3568b88ba960f6d105da2534#diff-692fc9858059052547bb966a14284c25c34198dddd6f2665f0e804ef5895e3ac

Eltion avatar Jan 11 '23 21:01 Eltion

@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.

arifaslaan avatar Jan 12 '23 00:01 arifaslaan

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 avatar Jan 12 '23 00:01 arifaslaan

@arifaslaan thank you :)

Eltion avatar Jan 14 '23 01:01 Eltion

@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 avatar Jan 16 '23 21:01 Sasa2023

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

Eltion avatar Jan 17 '23 01:01 Eltion

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 avatar Jan 17 '23 18:01 Sasa2023

@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 avatar Jan 19 '23 06:01 Eltion

@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.

Sasa2023 avatar Jan 19 '23 08:01 Sasa2023

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.

themmfa avatar Feb 05 '23 10:02 themmfa

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

technicaljicama avatar Feb 12 '23 16:02 technicaljicama

I can provide bounty for decrypted traffic

senolatac avatar Mar 02 '23 09:03 senolatac

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?

AskhatMaksut avatar Mar 02 '23 12:03 AskhatMaksut

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

Do they detect strong frida too?

yoshimo avatar Mar 17 '23 15:03 yoshimo

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.

simmison avatar Mar 28 '23 11:03 simmison

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.

p1tsi avatar May 09 '23 10:05 p1tsi

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

abdullahsaeed98 avatar May 25 '23 08:05 abdullahsaeed98

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

Sicks3c avatar Aug 18 '23 17:08 Sicks3c

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 avatar Aug 19 '23 06:08 abdullahsaeed98