JodelRaccoons / jodel_api

Unoffical Python Interface to the Jodel API
https://github.com/nborrmann/jodel_api
MIT License
18 stars 7 forks source link

Document new function endpoints #12

Closed tkf0 closed 3 years ago

tkf0 commented 3 years ago

I have a hard time circumventing the SSL pinning on my devices, which is why I am unable to do it myself.

However, I would like to see how the surveys feature works, how followed channels can be retrieved etc.

So, if someone has a working setup, I'd love to read your short summary about the new functions 😃

Furthermore, it would also serve as a basis to implement these new features in this api.

Unbrick commented 3 years ago

The logic of the SSL Pinning resides in the com.jodelapp.jodelandroidv3.api package. See if you can hook the method with Frida and therefore bypass it.

Otherwise I will test and post my working setup within the next days.

Additionally I found a proper way of deobfuscating Jodel using Redex by Facebook. If you want to experiment by yourself, you might want to look into it!

tkf0 commented 3 years ago

Thank you for your response. Sadly my technical resources are quite limited (outdated/slow) and most of the RE stuff is way over my head. Hence, I'm looking forward to your results when you've got some time.

Unbrick commented 3 years ago

Try running this script using frida:

Java.perform(function () {
    var CertificatePinning = Java.use('com.jodelapp.jodelandroidv3.api.ApiModule$setupCertificatePinning$1');
    CertificatePinning.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (x, y) {
        console.log("HostnameVerifier#verify called, returning true...");
        return true;
    };
});

The command to run it with frida would be:

frida -U -f com.tellm.android.app -l BypassCertificatePinning.js --no-pause

This should bypass certificate pinning regarding the hostname verification.

tkf0 commented 3 years ago

I tried it, but either this happens:

1|root@cube_iwork8ultimate:/ # /data/local/tmp/frida-server
{
    "type": "error",
    "description": "Error: access violation accessing 0x3e312359",
    "stack": "Error: access violation accessing 0x3e312359\n    at NativePointer.readUtf16String (frida/runtime/core.js:127:1)\n    at t.stringFromJni (frida/node_modules/frida-java-bridge/lib/env.js:600:1)\n    at Object.fromJni (frida/node_modules/frida-java-bridge/lib/types.js:199:1)\n    at ne (frida/node_modules/frida-java-bridge/lib/class-factory.js:610:1)\n    at frida/node_modules/frida-java-bridge/lib/class-factory.js:592:1",
    "fileName": "frida/runtime/core.js",
    "lineNumber": 127,
    "columnNumber": 1
}

with

Spawned `com.tellm.android.app`. Resuming main thread!
[I1 TF::com.tellm.android.app]-> Process terminated
[I1 TF::com.tellm.android.app]->

Thank you for using Frida!

and the entire OS rebooting, or

Spawned `com.tellm.android.app`. Resuming main thread!
[I1 TF::com.tellm.android.app]-> Process crashed: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.ClassLoader android.app.LoadedApk.getClassLoader()' on a null object reference

***
FATAL EXCEPTION: main
Process: com.tellm.android.app, PID: 16323
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.tellm.android.app/com.jodelapp.jodelandroidv3.view.Launcher}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.ClassLoader android.app.LoadedApk.getClassLoader()' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2269)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2420)
        at android.app.ActivityThread.access$900(ActivityThread.java:154)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5294)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.ClassLoader android.app.LoadedApk.getClassLoader()' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2258)
        ... 10 more
***
[I1 TF::com.tellm.android.app]->

Thank you for using Frida!

I really think it's my aged tablet that's still running Android 5 with no newer custom ROMs available.

Unbrick commented 3 years ago

I would too guess on the tablet. I tested this script this morning on Android 11 and it worked properly ^^

Otherwise you could check whether your SELinux is set to enforcing or permissive ('adb shell getenforce') and in case it is set to enforcing you could set it to permissive ('adb shell setenforce 0').

Alternatively you could try using an android emulator like genymotion. After installing google apps genymotion did work pretty well for me.

tkf0 commented 3 years ago

So I tried genymotion (Android 10/API 29) with the 7.1.1 apk and your script worked as I saw "verify called" several times in the console, but nothing actually happened inside the app, no posts, nothing, no visible api requests in mitmproxy.

Unbrick commented 3 years ago

Do you have the mitmproxy certificate installed in the system certificate store?

tkf0 commented 3 years ago

Yes, I followed the procedure outlined here: https://docs.mitmproxy.org/stable/howto-install-system-trusted-ca-android/

Unbrick commented 3 years ago

I'm not sure where the issue then lies there. Do regular web pages load properly and are they visible in mitmproxy?

tkf0 commented 3 years ago

Yes to all. I'm puzzled as well. Still grateful for your help!

tkf0 commented 3 years ago

If you happen to test your current setup again on Genymotion soon and it works, please let me know. Then I would know if it's me ^^ In the meantime, I have tried multiple Android versions and the result was the same every time.

Unbrick commented 3 years ago

Its not your device, i can reproduce this issue. I'll look into this

Unbrick commented 3 years ago

So i just dug into this a little deeper and found out they use the okhttp3.CertificatePinner to validate the chain.

Hooking it is a little difficult due to the UTF-8 method names used for obfuscation. As these change every version, this script will most probably not keep up with the next version released. The jodel version i tested it with is 7.1.1.

Java.perform(function () {
    var CertificatePinning = Java.use('com.jodelapp.jodelandroidv3.api.ApiModule$setupCertificatePinning$1');
    CertificatePinning.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (x, y) {
        console.log("HostnameVerifier#verify called, returning true...");
        return true;
    };

    var OkHttp3CertificatePinner = Java.use('okhttp3.CertificatePinner');
    OkHttp3CertificatePinner['ǃ'].overload('java.lang.String', 'kotlin.jvm.functions.Function0').implementation = function(x,y) {
        console.log("OkHttp3 Certificate verify bypassed!")
        return;
    }
});

For me this one worked like a charm, including loading posts.

Small Edit:

The code looks like the video feature uses a different TLS-Pinning mechanism. Not tested though.

tkf0 commented 3 years ago

The new script indeed works, thanks! Well, for that matter at least, because the moment I registered I was banned on the spot haha. Not sure what it triggered, but there are certainly a lot of giveaways they can make use of to detect VMs and cert pinning evasion. So, for endpoint documentation, deobfuscation is probably the (only) way to go.

Unbrick commented 3 years ago

As of my tests, registering without proxy and enabling the proxy afterwards should be possible. You just should make sure to use a system-less rooting framework like Magisk.

tkf0 commented 3 years ago

I'm still tied to Genymotion. Have you tried installing Magisk there?

Unbrick commented 3 years ago

Only using genymotion on arm basis (in the AWS cloud). Genymotion on x86 does work with Magisk but not with frida.