frida / frida-java-bridge

Java runtime interop from Frida
327 stars 124 forks source link

Java.perform() executed after .resume() #126

Open magnusstubman opened 5 years ago

magnusstubman commented 5 years ago

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?

iGio90 commented 4 years ago

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