Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: How Tiktok detect that SSL pinning bypassed? #9

Open
Sasa2023 opened this issue Nov 26, 2022 · 35 comments
Open

Question: How Tiktok detect that SSL pinning bypassed? #9

Sasa2023 opened this issue Nov 26, 2022 · 35 comments
Assignees

Comments

@Sasa2023
Copy link

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

@hackercxj
Copy link

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.

@Eltion
Copy link
Owner

Eltion commented Dec 13, 2022

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

@arifaslaan
Copy link

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

@Eltion
Copy link
Owner

Eltion commented Dec 15, 2022

@arifaslaan not yet :(

@kaykyr
Copy link

kaykyr commented Dec 19, 2022

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

@demon071
Copy link

Does it work with apps other than Tiktok?

@Sasa2023
Copy link
Author

Sasa2023 commented Jan 5, 2023

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

@Eltion
Copy link
Owner

Eltion commented Jan 5, 2023

@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

@Sasa2023
Copy link
Author

Sasa2023 commented Jan 6, 2023

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

@Eltion
Copy link
Owner

Eltion commented Jan 11, 2023

@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
Copy link
Owner

Eltion commented Jan 11, 2023

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

@Eltion
Copy link
Owner

Eltion commented Jan 11, 2023

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
Copy link

@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
Copy link

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.

@Eltion
Copy link
Owner

Eltion commented Jan 14, 2023

@arifaslaan thank you :)

@Sasa2023
Copy link
Author

@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

@Eltion
Copy link
Owner

Eltion commented Jan 17, 2023

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

@Sasa2023
Copy link
Author

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

@Eltion
Copy link
Owner

Eltion commented Jan 19, 2023

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

@Sasa2023
Copy link
Author

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

@themmfa
Copy link

themmfa commented Feb 5, 2023

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.

@technicaljicama
Copy link

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

@senolatac
Copy link

I can provide bounty for decrypted traffic

@AskhatMaksut
Copy link

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?

@yoshimo
Copy link

yoshimo commented Mar 17, 2023

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

Do they detect strong frida too?

@simmison
Copy link

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
Copy link

p1tsi commented May 9, 2023

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.

@abdullahsaeed98
Copy link

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

@Sicks3c
Copy link

Sicks3c commented Aug 18, 2023

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

@abdullahsaeed98
Copy link

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.

@Sicks3c
Copy link

Sicks3c commented Aug 19, 2023

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

@arstoo6001
Copy link

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

@brunoaduarte
Copy link

brunoaduarte commented Oct 10, 2023

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

@brunoaduarte
Copy link

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.

@junai-py
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests