frida-java-bridge icon indicating copy to clipboard operation
frida-java-bridge copied to clipboard

Java.perform() executed after .resume()

Open magnusstubman opened this issue 5 years ago • 1 comments

I'm trying to hook android.os.Process.start() but fail as the process executes before I can hook it with Frida.

Python script: (hook.py)

#!/usr/bin/env python

import frida
import os
import sys
import argparse
import time
  
def parse_hook(filename):
  print('[*] Parsing hook')
  hook = open(filename, 'r')
  script = session.create_script(hook.read())

  def on_message(message, data):
      print(message)
  script.on('message', on_message)

  script.load()
  time.sleep(3)
  print('[*] ' + filename + ' loaded')


if __name__ == '__main__':
  try:
    parser = argparse.ArgumentParser()
    parser.add_argument('package', help='Spawn a new process and attach')
    parser.add_argument('script', help='Print stack trace for each hook')
    args = parser.parse_args()


    print('[*] Spawning ' + args.package)
    device = frida.get_usb_device()
    device.enable_spawn_gating()
    pid = device.spawn(args.package)
    time.sleep(1)

    print('[*] ' + args.package + ' spawned with pid ' + str(pid))
    session = frida.get_usb_device().attach(pid)

    parse_hook(args.script)
    print('[*] Resuming ' + str(pid))
    frida.get_usb_device().resume(pid)

    print('')
    sys.stdin.read()

  except KeyboardInterrupt:
    print('keybardinterrupt ')
    sys.exit(0)

Javascript file: (x.js)

console.log("script exec");
if (Java.available) {
    console.log("java available");

    Java.perform(function() {

      console.log("java perform");

      Java.use('android.os.Process')['start'].overload(
      'java.lang.String',
      'java.lang.String',
      'int',
      'int',
      '[I',
      'int',
      'int',
      'int',
      'java.lang.String',
      'java.lang.String',
      'java.lang.String',
      'java.lang.String',
      'java.lang.String',
      '[Ljava.lang.String;'
      ).implementation = function(a,b,c,d,e,f,g,h,i,j,k,l,m,n) {

          send("called");
          return this.start(a,b,c,d,e,f,g,h,i,j,k,l,m,n);
      };
      send("hooks installed");
   });
}


$ ./hook.py com.company.app x.js
[*] Spawning com.company.app
[*] com.company.app spawned with pid 22785
[*] Parsing hook
script exec
java available
[*] x.js loaded
[*] Resuming 22785

java perform
{u'type': u'send', u'payload': u'hooks installed'}

As you can see from the output, the function passed to java.Perform() is executed after the spawned application is resumed via the resume() call, hence any hooking of android.os.Process methods is futile.

Testing system:

$ uname -a
Linux ghirew 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1+deb9u3 (2019-06-16) x86_64 GNU/Linux
$ pip search frida
frida-tools (2.0.2)              - Frida CLI tools
  INSTALLED: 2.0.2 (latest)
frida-gadget (0.1.6)             - Easy to use frida gadget
frida-util (0.5)                 - Silly python wrapper around Frida.
frida-runner (0.2.0)             - A Stupid CLI script to run Frida on iOS or Android
frida-push (1.0.8)               - Wrapper tool to identify the remote device and push device specific frida-server binary.
frida (12.6.11)                  - Dynamic instrumentation toolkit for developers, reverse-engineers, and security researchers
  INSTALLED: 12.6.10
  LATEST:    12.6.11
frida-android-adb (1.2.0)        - A pure python implementation of the Android ADB and Fastboot protocols
frida-android-M2Crypto (0.27.0)  - M2Crypto: A Python crypto and SSL toolkit
apk-cheater (0.0.7)              - Easy to use frida gadget
$ frida --version
12.6.10

Testing device:

OnePlus3:/ # uname -a
Linux localhost 3.18.66-perf+ #1 SMP PREEMPT Thu Dec 6 00:54:59 CST 2018 aarch64

What am I doing wrong?

magnusstubman avatar Jul 19 '19 11:07 magnusstubman

replace Java.perform with Java.performNow and it should work

iGio90 avatar Apr 19 '20 10:04 iGio90