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

Early instrumentation: Intercepting method onCreate() from MainActivity on Android ART #29

Closed
enovella opened this issue Apr 24, 2017 · 56 comments

Comments

@enovella
Copy link
Contributor

enovella commented Apr 24, 2017

Hi all,

I have been playing around with some Android crackmes from the OWASP community and found that I was not able to hook the first class loaded that extended from the class Activity. Therefore, I wondered why this was happening.

Target code (decompiled)

First of all lets see the target code to intercept:

public class MainActivity extends Activity
{
    private void a(final String title) {
        final AlertDialog create = new AlertDialog$Builder((Context)this).create();
        create.setTitle((CharSequence)title);
        create.setMessage((CharSequence)"This in unacceptable. The app is now going to exit.");
        create.setButton(-3, (CharSequence)"OK", (DialogInterface$OnClickListener)new b(this));
        create.show();
    }
    
    protected void onCreate(final Bundle bundle) {
        if (c.a() || c.b() || c.c()) {
            this.a("Root detected!");
        }
        if (sg.vantagepoint.a.b.a(this.getApplicationContext())) {
            this.a("App is debuggable!");
        }
        super.onCreate(bundle);
        this.setContentView(2130903040);
    }

The goal is to inject code when entering into onCreate() to defeat the security checks. To achieve early instrumentation, the process was chosen to be spawned instead of attached, and the hook was written as such:

Java.perform(function () {
	send("Starting hooks OWASP uncrackable1...");

	var mainactivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity");
	mainactivity.onCreate.overload("android.os.Bundle").implementation = function(var_0) {
	    send("sg.vantagepoint.uncrackable1.MainActivity.onCreate(Landroid/os/Bundle;)V    MainActivity HIT!!!");
	    var ret = this.onCreate.overload("android.os.Bundle").call(this,var_0);
	};

	send("Hooks installed.");
});	

Question

With all that, my question was if Frida is capable of intercepting this early method when the main activity class is instantiated.

Further information

APK: Uncrackable level1
Target class: public class MainActivity extends Activity
Target method: protected void onCreate(final Bundle bundle)
Frida version: 9.1.27
Target Arch: Android 7.1.x ART
Device: Nexus 5x
Host Arch: x64 Ubuntu 16.04.2

@TheDauntless
Copy link

Did you get an error?

This also sounds like it's related to #25, #26 and #28 ?

@enovella
Copy link
Contributor Author

Hi,

Frida didn't show any error but the hook wasn't hit. After this, I hooked the method onStart() which is descendant of onCreate(). Sometimes it worked and others didn't work.

Activity methods: onCreate() vs onStart()

aa
Let me take a peek at these #issues.

Cheers

@enovella
Copy link
Contributor Author

enovella commented Apr 24, 2017

The method onStart() is hit when the application is launched but this does not solve the issue due to the fact the method onCreate() already performed some checks.

With the following hook, I hit the method onStart():

	var mainactivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity");
	mainactivity.onStart.overload().implementation = function() {
		send("MainActivity.onStart() HIT!!!");
		var ret = this.onStart.overload().call(this);
	};

This is the result after minimizing and maximizing the Android app:

[13:37 edu@ubuntu hooks] > python run_usb_spawn.py 
pid: 10821
[*] Intercepting ...
[!] Received: [Starting hooks OWASP uncrackable1...]
[!] Received: [Hooks installed.]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [java.lang.System.exit(I)V  // We avoid exiting the application  :)]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onStart() HIT!!!]

@SrFlipFlop
Copy link

Hi,

I have the same issue with the same application. I try to hook the sg.vantagepoint.a.c functions and don't have any feedback from Frida.

if (Java.available) {    
    Java.perform(function () {        
        var rootChecks = Java.use('sg.vantagepoint.a.c');
        rootChecks.a.overload().implementation = function() {
            send('Return sg.vantagepoint.a.c.a -> false')
            return false;
        };
        rootChecks.b.implementation = function() {
            send('Return sg.vantagepoint.a.c.b -> false')
            return false;
        };
        rootChecks.c.implementation = function() {
            send('Return sg.vantagepoint.a.c.c -> false')
            return false;
        };
    });
}

Enviroment used

Frida: 9.1.27, 9.1.26, 9.1.14
Emulator: Android 6.0 x86_64
Host: Kali 4.6.4 x64

@enovella
Copy link
Contributor Author

Hi @SrFlipFlop ,

I also tried the same hooks and they weren't hit by Frida. Then I attempted to hook onCreate() but I could not instrument the method either.

Know that @TheDauntless experimented issues when using emulator + Frida. Did the process crash for you?

Cheers

@SrFlipFlop
Copy link

Hi @enovella

In older versions of Frida sometimes the hooked applications crashed. But using Frida 9.1.27 I didn't found any issue.

Regards.

@enovella
Copy link
Contributor Author

enovella commented May 8, 2017

Hi all,

Regarding the unreachable hooks due to the early instrumentation, I'd like to mention that I have been playing with the uncrackable level3, although I am still investigating where carefully to place the Java hooks on, I was able to hit my hooks:

[!] Received: [MainActivity.onCreate() HIT!!!]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.verifyLibs()V]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.baz()J]
[!] Received: [2378563664]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.init([B)V]
[!] Received: [70697A7A6170697A7A6170697A7A6170697A7A6170697A7A]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot1()Z  Root check 1 HIT!  su.exists()]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot2()Z  Root check 2 HIT!  test-keys]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot3()Z  Root check 3 HIT!  Root packages]
[!] Received: [sg.vantagepoint.util.IntegrityCheck.isDebuggable(Landroid/content/Context;)Z  Debug check HIT! ]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onCreate() HIT!!!]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.verifyLibs()V]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.baz()J]
[!] Received: [2378563664]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.init([B)V]
[!] Received: [70697A7A6170697A7A6170697A7A6170697A7A6170697A7A]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot1()Z  Root check 1 HIT!  su.exists()]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot2()Z  Root check 2 HIT!  test-keys]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot3()Z  Root check 3 HIT!  Root packages]
[!] Received: [sg.vantagepoint.util.IntegrityCheck.isDebuggable(Landroid/content/Context;)Z  Debug check HIT! ]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onCreate() HIT!!!]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.verifyLibs()V]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.baz()J]
[!] Received: [2378563664]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.init([B)V]
[!] Received: [70697A7A6170697A7A6170697A7A6170697A7A6170697A7A]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot1()Z  Root check 1 HIT!  su.exists()]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot2()Z  Root check 2 HIT!  test-keys]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot3()Z  Root check 3 HIT!  Root packages]
[!] Received: [sg.vantagepoint.util.IntegrityCheck.isDebuggable(Landroid/content/Context;)Z  Debug check HIT! ]
[!] Received: [MainActivity.onStart() HIT!!!]
[!] Received: [MainActivity.onCreate() HIT!!!]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.verifyLibs()V]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.baz()J]
[!] Received: [2378563664]
[!] Received: [sg.vantagepoint.uncrackable3.MainActivity.init([B)V]
[!] Received: [70697A7A6170697A7A6170697A7A6170697A7A6170697A7A]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot1()Z  Root check 1 HIT!  su.exists()]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot2()Z  Root check 2 HIT!  test-keys]
[!] Received: [sg.vantagepoint.util.RootDetection.checkRoot3()Z  Root check 3 HIT!  Root packages]
[!] Received: [sg.vantagepoint.util.IntegrityCheck.isDebuggable(Landroid/content/Context;)Z  Debug check HIT! ]
[!] Received: [MainActivity.onStart() HIT!!!]

Will be commenting more when all is more clear :P

@enovella
Copy link
Contributor Author

enovella commented May 8, 2017

In the first run, Frida does not see onCreate() method. Though, if we minimize the application (leave it on background) and reopen it again, all your hooks will be hit.

The problem with this issue is the time when the Java hooks are set. Looking for a solution

@TheDauntless
Copy link

Possible contenders for hook:

Approach:
Using LD_PRELOAD and hook the contenders to see if / when they are called and how often. Next, we need a way of validating the injection point to see if it is a good place. Current thought is to check if Java.available == true, but I don't know if that makes sense?

@TheDauntless
Copy link

TheDauntless commented May 12, 2017

A first possible solution is _ZN7android14AndroidRuntime8startRegEP7_JNIEnv.

Currently, Frida hooks setArgV0, called from app_main.cpp. This is too early. A few lines further, the start method is called. This method is described as

967 * Start the Android runtime. This involves starting the virtual machine
968 * and calling the "static void main(String[] args)" method in the class
969 * named by "className".
970 *
971 * Passes the main function two arguments, the class name and the specified
972 * options string.

Halfway through, after some other initialisations, onVmCreated(env); is called. I wasn't able to hook that one, but if I hook on the call right after (startReg), it appears everything is ready for Frida-java.

The remaining question now is: Is this too late ?

I used the following script for validating:

// Used for LD PRELOAD TEST


'use strict';

rpc.exports = {
  init: function () {
    test();
  }
};

function VMTest(caller)
{
    try
    {
        const jsizeSize = 4;
        const pointerSize = Process.pointerSize;
        const vms = Memory.alloc(pointerSize);
        const vmCount = Memory.alloc(jsizeSize);

        const address = Module.findExportByName("libnativehelper.so", "JNI_GetCreatedJavaVMs");
        const myFunc = new NativeFunction(address, 'int', ['pointer', 'int', 'pointer']);
        const retVal = myFunc(vms, 1, vmCount);

        if(Memory.readInt(vmCount) > 0)
        {
            console.log("SUCCESS in " + caller)
        }

    }
    catch(err)
    {
        console.log("Too soon in " + caller)
    }

}

function test()
{
    VMTest("rcp.exports");

    var exported = Module.enumerateExportsSync("libandroid_runtime.so");
    exported.forEach(function(item){
        try
        {
            var name = item["name"]
            var ob = {

                onEnter(args)
                {
                    VMTest(name + " (enter)");
                },
                onLeave(args) {
                    VMTest(name + " (leave)");
                }
            }

            if(name.indexOf("_ZN7android14AndroidRuntime8startRegEP7_JNIEnv") == 0)
            {
                console.log("hooking on " + name);
                Interceptor.attach(item["address"], ob);
            }
        }
        catch(error)
        {
           // console.log(error);
        }
    })
    console.log("all done!");
}

@TheDauntless
Copy link

I just now noticed the following crash log in logcat when Java.perform is used:

05-13 12:03:01.419 6565 6565 F art : art/runtime/oat_quick_method_header.cc:55] Failed to find Dex offset for PC offset 0x8ca2695c(PC 0x0, entry_point=0x735d96a4 current entry_point=0x735d96a4) in android.app.LoadedApk android.app.ActivityThread.getPackageInfoNoCheck(android.content.pm.ApplicationInfo, android.content.res.CompatibilityInfo)
05-13 12:03:01.426 6565 6565 D AndroidRuntime: Shutting down VM
05-13 12:03:01.427 6565 6565 E AndroidRuntime: FATAL EXCEPTION: main
05-13 12:03:01.427 6565 6565 E AndroidRuntime: Process: a.b.permissionspawner, PID: 6565
05-13 12:03:01.427 6565 6565 E AndroidRuntime: java.lang.IllegalArgumentException: packageInfo
05-13 12:03:01.427 6565 6565 E AndroidRuntime: at android.app.ContextImpl.createAppContext(ContextImpl.java:1982)
05-13 12:03:01.427 6565 6565 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5294)
05-13 12:03:01.427 6565 6565 E AndroidRuntime: at android.app.ActivityThread.-wrap2(ActivityThread.java)
05-13 12:03:01.427 6565 6565 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1545)
05-13 12:03:01.427 6565 6565 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)
05-13 12:03:01.427 6565 6565 E AndroidRuntime: at android.os.Looper.loop(Looper.java:154)
05-13 12:03:01.427 6565 6565 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6119)
05-13 12:03:01.427 6565 6565 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
05-13 12:03:01.427 6565 6565 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
05-13 12:03:01.427 6565 6565 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
05-13 12:03:01.430 1609 1620 W ActivityManager: Force finishing activity a.b.permissionspawner/.MainActivity

@galapogos
Copy link

galapogos commented Aug 7, 2017

Hi,
I'm using the latest Frida 10.3.12 both Ubuntu, and Frida-server 10.3.12 on Nexus 5 device. I'm still getting the same issues as @enovella and @SrFlipFlop
onCreate() hooks are not hit, neither are the descendants onStart() unless I send the Activity to the background, and back to the foreground via recent apps (see below).

[!] Received: [MainActivity.onStart() HIT!!!]
MainActivity.onStart() HIT!!!

None of the sg.vantagepoint.a.c function hooks are hit either, unless I send the Activity to the background, and back to the foreground by re-launching it (see below).

[!] Received: [MainActivity.onCreate() HIT!!!]
MainActivity.onCreate() HIT!!!
[!] Received: [sg.vantagepoint.a.c.b()Z  Root check 1 HIT!  su.exists()]
sg.vantagepoint.a.c.b()Z  Root check 2 HIT!  su.exists()
[!] Received: [sg.vantagepoint.a.c.b()Z  Root check 2 HIT!  test-keys]
sg.vantagepoint.a.c.b()Z  Root check 2 HIT!  test-keys
sg.vantagepoint.a.c.c()Z  Root check 3 HIT!  Root packages
[!] Received: [sg.vantagepoint.a.c.c()Z  Root check 3 HIT!  Root packages]
sg.vantagepoint.a.b.a(Landroid/content/Context;)Z  Debug check HIT!
[!] Received: [sg.vantagepoint.a.b.a(Landroid/content/Context;)Z  Debug check HIT! ]
Activity HIT!!!
[!] Received: [Activity HIT!!!]
[!] Received: [MainActivity.onStart() HIT!!!]
MainActivity.onStart() HIT!!!

If I send the Activity back to the foreground via recent apps, the hooks aren't hit (see below).

[!] Received: [MainActivity.onStart() HIT!!!]
MainActivity.onStart() HIT!!!

Has this issue been fixed on the latest versions?

@enovella
Copy link
Contributor Author

Hi @galapogos ,

I heard that it should have been fixed by one the @oleavr releases. The behaviour you comment was exacty the same I experimented.

Don't promise anything but I will try to test it to verify your claim.

Best,

@galapogos
Copy link

Hi @enovella
Thanks. I'm a relative Frida noob, so which @oleavr release fixes this, and how do I install it? Do I need both the Frida and Frida-server components from him?

@enovella
Copy link
Contributor Author

Just install the latest Frida. You do need both Frida and Frida-server running the same version.

@galapogos
Copy link

galapogos commented Aug 17, 2017 via email

@enovella
Copy link
Contributor Author

Hi @galapogos,

could you provide us more details about the issue?

Best,
Edu

@galapogos
Copy link

galapogos commented Aug 18, 2017 via email

@galapogos
Copy link

galapogos commented Aug 18, 2017 via email

@jhscheer
Copy link

jhscheer commented Sep 13, 2017

Hi,
I'm facing the exact same issue with the latest Frida release (10.5.15) on a Nexus 5x 6.0.1 device.
As described by @enovella, @SrFlipFlop and @galapogos, Frida spawns the App and does not hook early enough to catch any methods (no errors).
Only after the workaround (minimizing and maximizing the App), all methods are hooked as desired. However, this workaround only works with this particular App because it sort of waits for you to act. Would the root check in this App just exit, without displaying a message first, I wouldn't be able to solve this crackme with Frida :(
I also tried to switch from Java.perform( to Java.performNow(, but that didn't change anything.
Something like the wait for debugger option from Android would be nice. Is there something similar I could try?

adb logcat:

09-13 12:59:27.198   921  3855 I ActivityManager: Start proc 9378:sg.vantagepoint.uncrackable1/u0a95 for activity sg.vantagepoint.uncrackable1/.MainActivity
09-13 12:59:27.200  9231  9231 I frida-server-10: type=1400 audit(0.0:176): avc: denied { write } for name="re.frida.server" dev="dm-0" ino=654090 scontext=u:r:init:s0 tcontext=u:object_r:frida_file:s0 tclass=dir permissive=1
09-13 12:59:27.200  9231  9231 I frida-server-10: type=1400 audit(0.0:177): avc: denied { add_name } for name="pipe-d7ce9e7ff3bd0d9841617003f67c659d" scontext=u:r:init:s0 tcontext=u:object_r:frida_file:s0 tclass=dir permissive=1
09-13 12:59:27.200  9231  9231 I frida-server-10: type=1400 audit(0.0:178): avc: denied { create } for name="pipe-d7ce9e7ff3bd0d9841617003f67c659d" scontext=u:r:init:s0 tcontext=u:object_r:frida_file:s0 tclass=sock_file permissive=1
09-13 12:59:27.200  9231  9231 I frida-server-10: type=1400 audit(0.0:179): avc: denied { setattr } for name="pipe-d7ce9e7ff3bd0d9841617003f67c659d" dev="dm-0" ino=654110 scontext=u:r:init:s0 tcontext=u:object_r:frida_file:s0 tclass=sock_file permissive=1
09-13 12:59:27.200  9231  9231 I frida-server-10: type=1400 audit(0.0:180): avc: denied { relabelfrom } for name="pipe-d7ce9e7ff3bd0d9841617003f67c659d" dev="dm-0" ino=654110 scontext=u:r:init:s0 tcontext=u:object_r:frida_file:s0 tclass=sock_file permissive=1
09-13 12:59:27.200  9231  9231 I frida-server-10: type=1400 audit(0.0:181): avc: denied { relabelto } for name="pipe-d7ce9e7ff3bd0d9841617003f67c659d" dev="dm-0" ino=654110 scontext=u:r:init:s0 tcontext=u:object_r:frida_file:s0 tclass=sock_file permissive=1
09-13 12:59:27.337  9378  9378 W System  : ClassLoader referenced unknown path: /data/app/sg.vantagepoint.uncrackable1-1/lib/arm64
09-13 12:59:27.646   921  2954 I ActivityManager: Displayed sg.vantagepoint.uncrackable1/.MainActivity: +473ms```

@oleavr
Copy link
Member

oleavr commented Sep 13, 2017

This is a device-specific issue. Until someone with a Nexus device volunteers to debug this (I don't have any such device myself), this will remain an unresolved issue. As a workaround you may use an emulator or another Android device.

@jhscheer
Copy link

jhscheer commented Sep 13, 2017

Hi @oleavr,
as already stated by @SrFlipFlop, this issue also affects emulators:

Frida: 9.1.27, 9.1.26, 9.1.14
Emulator: Android 6.0 x86_64
Host: Kali 4.6.4 x64

I can also reproduce this issue with Frida 9.1.16 and 10.1.2 on an x86 Android 6.0 Android Studio Emulator (Host running Fedora and python3.6).
I couldn't test the latest Frida 10.5.x releases with my emulators, since the App always crashed when I tried to spawn the App with Frida, but that's an entirely different issue.

@jhscheer
Copy link

Hi,
I did some more testing with various Frida versions and multiple devices/emulators and Android versions.
I couldn't find a combination of the above where I was able to use early instrumentation :(
I'm either doing something fundamentally wrong, or this issue needs to be reopened!

Host: Linux x86_64, python3.6
APK: https://github.com/OWASP/owasp-mstg/tree/master/Crackmes/Android/Level_01/

Tested:
Device:

  • Nexus 5X - 6.0.1 - ARM64 - 10.5.15

AndroidStudio Emulator:

  • Nexus 5 - 5.1.0 - API 22 ARM - 10.5.15
  • Nexus 5 - 6.0.0 - API 23 ARM - 10.5.15

Genymotion Emulator:

  • Nexus 5X - 6.0.0 - API 23 x86 - 10.2.3
  • Nexus 5X - 6.0.0 - API 23 x86 - 10.2.2
  • Nexus 5X - 6.0.0 - API 23 x86 - 10.2.1
  • Nexus 5X - 6.0.0 - API 23 x86 - 10.1.6
  • Nexus 5X - 6.0.0 - API 23 x86 - 10.1.5
  • Nexus 7 2013 - 6.0.0 - API 23 x86 - 10.1.2
  • Nexus 5X - 6.0.0 - API 23 x86 - 10.1.2
  • Galaxy S6 - 6.0.0 - API 23 x86 - 10.1.2
  • Pixel C - 6.0.0 - API 23 x86 - 10.1.2
  • Custom Phone - 6.0.0 - API 23 x86 - 10.1.2
  • Custom Phone - 6.0.0 - API 23 x86 - 9.1.16

(I tested a lot more Frida versions, but I encountered an other issue were Frida spawn crashes the App, see frida/frida#343)

uncrackable1.js

'use strict';
setImmediate(function() {
  send("hooking started");

  Java.perform(function () {

	var mainactivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity");
	mainactivity.onCreate.overload("android.os.Bundle").implementation = function(var_0) {
	  send("'MainActivity.onCreate()' hooked");
	  this.onCreate.overload("android.os.Bundle").call(this,var_0);
	};
	mainactivity.onStart.overload().implementation = function() {
	  send("'MainActivity.onStart()' hooked");
	  this.onStart.overload().call(this);
	};

	var rootcheck = Java.use("sg.vantagepoint.a.c");
	rootcheck.a.overload().implementation = function() {
	  var ret = this.a.overload().call(this)
	  send("'sg.vantagepoint.a.c.a()' hooked -> return \"false\" instead of \"" + ret + "\"");
	  return false;
	};
	rootcheck.b.overload().implementation = function() {
	  var ret = this.b.overload().call(this)
	  send("'sg.vantagepoint.a.c.b()' hooked -> return \"false\" instead of \"" + ret + "\"");
	  return false;
	};
	rootcheck.c.overload().implementation = function() {
	  var ret = this.c.overload().call(this)
	  send("'sg.vantagepoint.a.c.c()' hooked -> return \"false\" instead of \"" + ret + "\"");
	  return false;
	};

	var activity = Java.use("android.app.Activity");
	activity.onCreate.overload("android.os.Bundle").implementation = function(var_0) {
	  send("'android.app.Activity.onCreate()' hooked");
	  this.onCreate.overload("android.os.Bundle").call(this,var_0);
	};
	activity.onResume.implementation = function () {
		send("'android.app.Activity.onResume()' hooked");
		this.onResume();
	};

	var debugcheck = Java.use("sg.vantagepoint.a.b");
	debugcheck.a.overload("android.content.Context").implementation = function(var_0) {
	  var ret = this.a.overload("android.content.Context").call(this,var_0)
	  send("'sg.vantagepoint.a.b.a(this.getApplicationContext())' hooked -> return \"false\" instead of \"" + ret + "\"");
	  return false;
	};

	send("hooks inserted");
  });
});

Steps to reproduce:

  • adb install UnCrackable-Level1.apk
  • frida -U -f sg.vantagepoint.uncrackable1 --no-pause -l uncrackable1.js

or in python:

device = frida.get_usb_device(timeout=1)

print ("[log] device.spawn() ...")
# creates the process with the main thread suspended
pid = device.spawn(["sg.vantagepoint.uncrackable1"])

print ("[log] device.attach() ...")
session = device.attach(pid)

with io.open(scriptname, "r", encoding='utf8') as f:                                                         
	script = session.create_script(f.read())

script = session.create_script(script_content)
script.on('message', on_message)
print ("[log] script.load() ...")
script.load()

print ("[log] device.resume() ...")
# resumes the main thread
device.resume(pid)

Output:

[log] device.spawn() ...                                                                                         
[log] device.attach() ...                                                                                        
[log] script.load() ...                                                                                          
[log] device.resume() ...                                                                                        
[recv] hooking started                                                                                           
[recv] hooks inserted

the App shows the "Root detected" Alert
I manually press the 'Home' button
and then I press the Uncrackable1 Icon from the App drawer
(it doesn't work with the 'Overview' button)

[recv] 'MainActivity.onCreate()' hooked                                                                          
[recv] 'sg.vantagepoint.a.c.a()' hooked -> return "false" instead of "true"                                      
[recv] 'sg.vantagepoint.a.c.b()' hooked -> return "false" instead of "true"                                      
[recv] 'sg.vantagepoint.a.c.c()' hooked -> return "false" instead of "true"                                      
[recv] 'sg.vantagepoint.a.b.a(this.getApplicationContext())' hooked -> return "false" instead of "false"         
[recv] 'android.app.Activity.onCreate()' hooked                                                                  
[recv] 'MainActivity.onStart()' hooked                                                                           
[recv] 'android.app.Activity.onResume()' hooked

the App does not show the "Root detected" Alert and I can proceed ...

Since at first glance logcat logs do not show anything suspicious, I don't know how to proceed here.
I really need this feature of Frida and I'm willing to do more testing, etc. to get to the root of this issue.
Pleas let me know if you can think of something else I could try.

@oleavr
Copy link
Member

oleavr commented Mar 9, 2018

Might work better with 10.6.59, which fixed a long-standing stability issue in the Java hooking logic.

@enovella
Copy link
Contributor Author

enovella commented Mar 9, 2018

@oleavr I am not sure about that. Look at this #29 (comment)

@oleavr
Copy link
Member

oleavr commented Mar 9, 2018

@enovella Did you verify this with 10.6.59? The bug that was fixed in .59 caused undefined behavior, so it could explain this issue – or this could be a different one, but someone has to test this on 10.6.59 to be sure.

@jhscheer
Copy link

jhscheer commented Mar 9, 2018

Hi,
I just tested 10.6.59 for early instrumentation and it works if I use the frida-server!
It does however, not work with frida-gadget :(
Since I don't have access to a device right now I used an x86 Emulator with Android 7.0.1.

This works:

  • frida --usb --load=uncrackable1.js -f sg.vantagepoint.uncrackable1
    then %resume
  • frida --usb --load=uncrackable1.js -f sg.vantagepoint.uncrackable1 --no-pause

If I switch to frida-gadget, everything works fine, except early instrumentation.
Only with the workaround (home_button to suspend the App, then click on the App in the App drawer) I was able to hit the early instrumentation hooks.

@oleavr , thanks again for all the awesome work on frida and especially regarding Android.
Let me know if I can be of assistance for testing frida-gadget regarding early instrumentation on Android.

@enovella
Copy link
Contributor Author

enovella commented Mar 9, 2018

@oleavr I tested a couple of weeks ago. Nevertheless, I will re-test it tomorrow with the latest Frida.
@jhscheer IIRC, the early instrumentation wasn't working when I was spawning the app by using Python bindings but it kinda worked when using the Frida REPL. So weird though.

@awakened1712
Copy link

awakened1712 commented Mar 10, 2018

I could confirm that 10.6.59 early instrumentation does not work with python2 bindings. Tested on OneplusOne (armv7) running Android 6.

@jhscheer
Copy link

jhscheer commented Mar 11, 2018

Hi,
I also had no success with 10.6.59 and python3 bindings (Android 7.1.1 x86).
Hooking MainActivity.onCreate() etc. does not work with spawn(), attach(), resume().
The onCreate() method is only hooked when using the App suspend/resume workaround, which is the same behaviour I observed with frida-gadget.

@enovella
Copy link
Contributor Author

Hi all,

I also had no success with 10.6.59 and python2 bindings (Android 7.1.2 ARM64). Is there something we can do to solve finally this issue? (@oleavr ). This is an important issue to resolve imho.

Best

@jhscheer
Copy link

jhscheer commented Mar 12, 2018

Hi,
I switched from Android 7.1.1 to 8.0.0 (x86) and now early instrumentation with python3 bindings works!
However early instrumentation with frida-gadget on Android 8.0.0 does not work, not even with the workaround :(
I'll try again on a real device (arm64) tomorrow.

Edit:
I tested it again with a real device:

Nexus5X
buildnumber=OPM5.171019.015
androidVersion=8.1.0

Same behaviour than with the emulator:
early instrumentation works but not with frida-gadget injected into the APK.

@oleavr
Copy link
Member

oleavr commented Mar 13, 2018

@enovella If you're saying it works with the REPL but not the python bindings, that means you're using the API wrong – because the REPL is using the same python bindings. Could you share a minimal example reproducing the behavior you're seeing?

@oleavr oleavr reopened this Mar 13, 2018
@enovella
Copy link
Contributor Author

Hi @oleavr,

I thought that had already shared with you. Anyhow, here you go:

Looking forward to solving this issue.

@enovella
Copy link
Contributor Author

Also to comment, with the REPL "kinda" worked but didn't continue working after hitting the hooks. Therefore, I could say that it didn't work properly for me on Android 7.1.2 Nexus 5X.

@oleavr
Copy link
Member

oleavr commented Mar 13, 2018

@enovella Ah sorry, I should have looked closer.

I see the problem: resume() should never be called before script.load() -- this means you allow the application's main thread to start before you have applied any instrumentation at all. So any APIs called early are likely to be missed by your hooks.

Some style nitpicks:

  • Use false instead of Boolean(0), and true instead of Boolean(1).
  • Don't look up the Java method more than once – assign it to a variable instead. So instead of:
Klass.foo.overload('int').implementation = function (a1) {
  return Klass.foo.overload('int').call(this, a1);
};

do:

var foo = Klass.foo.overload('int');
foo.implementation = function (a1) {
  return foo.call(this, a1);
};

Regarding the hanging issue, a good way to get to the bottom of that is to disable hooks until it's able to start, to narrow it down to just one.

@enovella
Copy link
Contributor Author

Hi @oleavr,

Many thanks for the comments and reopening the issue. It seems that the problem is at my side. Will come back to you with answers after testing your advises.

Regarding the gadget, do you want to keep this page for handling this issue as well? Otherwise, after verifying that the error was in my code, I will close the issue.

Cheers

@jhscheer
Copy link

@oleavr , @enovella
It would be great, if you could leave this issue open until early instrumentation for frida-gadget is also fixed.
FYI: I just tested again and it also doesn't work for me on Frida 10.7.0 and Android 8.0.0

@enovella
Copy link
Contributor Author

enovella commented Mar 14, 2018

Busy this week but I will share my testing results as soon as possible. Let's leave this issue opened until the issue has been entirely resolved both in frida-gadget and Python bindings.

@phros
Copy link

phros commented Mar 23, 2018

Hi Guys, I have the same problem (Frida 10.7.6, frida-server 10.7.6, Nexus 5, Android 6). Following setup:

  • start command: frida -U -l hello.js -f com.testapp.helloworld
  • hello.js:
setImmediate(function() { 
    console.log("[*] Starting script");
    Java.perform(function() {
        console.log("[*]   Inside Java.perform")
        [...]
    });
    console.log("[*] Hook set");
}) 

Output:

[LGE AOSP on HammerHead::com.testapp.helloworld]->
[*] Starting script
[*] Hook set

So, the Java.perform Method is not executed.

The interesting part is, when I type %resume and let the app start normally and then edit the hello.js script, frida reloads the script and the Java.perform function is executed and I see the output:

[LGE AOSP on HammerHead::com.testapp.helloworld]-> 
[*] Starting script
[*]   Inside Java.perform
[*] Hook set

When I try to hook onCreate or other "early" stuff, this does not work, because the hook is not set...

@pich4ya
Copy link

pich4ya commented Aug 23, 2018

go up!

@enovella
Copy link
Contributor Author

enovella commented Apr 17, 2019

This works perfectly:

[23:10 edu@truelove ~] >  r2 frida://spawn/usb//owasp.mstg.uncrackable1
 -- Don't do this.
[0x00000000]> \. ./owasp1.js 
[0x00000000]> \dc
resumed spawned process.
[0x00000000]> Starting hooks OWASP uncrackable1...
Hooks installed.
MainActivity.onCreate() HIT!!!
sg.vantagepoint.a.c.a()Z  Root check 1 HIT!  su.exists()
sg.vantagepoint.a.c.b()Z  Root check 2 HIT!  test-keys
sg.vantagepoint.a.c.c()Z  Root check 3 HIT!  Root packages
sg.vantagepoint.a.b.a(Landroid/content/Context;)Z  Debug check HIT! 
MainActivity.onStart() HIT!!!
[0x00000000]> 
[0x00000000]> sg.vantagepoint.a.a.a([B[B)[B   doFinal(enc)  // AES/ECB/PKCS7Padding
Decrypted flag: I want to believe
[0x00000000]> \?V
{"version":"12.4.7.3.gc04f610"}

@TheDauntless
Copy link

Hi @enovella , can you include your owasp1.js script? Or give some more insights into what is now working, what isn't?

It might be a little bit too early to close this issue?

@enovella
Copy link
Contributor Author

Uncomment the commented code and return false instead of 0:
https://enovella.github.io/android/reverse/2017/05/18/android-owasp-crackmes-level-1.html

@agrawalsmart7
Copy link

agrawalsmart7 commented May 15, 2019

Hi @enovella

Below is my code and on that code I want to hook onClick implementation. But I didn't find the way on how to do it?

Do you have an idea about How can i?

public class MainActivity extends Activity {
    private void a(String str) {
        AlertDialog create = new Builder(this).create();
        create.setTitle(str);
        create.setMessage("This is unacceptable. The app is now going to exit.");
        create.setButton(-3, "OK", new OnClickListener() {
            public void onClick(DialogInterface dialogInterface, int i) {
                System.exit(0);
            }
        });
        create.setCancelable(false);
        create.show();
}

@giorgos-pieri
Copy link

@oleavr shouldn't this issue be open? Issue exists even on frida 12.2.25

@enovella
Copy link
Contributor Author

enovella commented Jun 25, 2019

Please @giorgos-pieri upgrade to 12.6.x where the issue is fixed

Check this out:
#29 (comment)

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