frida / frida-node

Frida Node.js bindings
282 stars 66 forks source link

spawn gating issue #23

Closed alvarofe closed 5 years ago

alvarofe commented 7 years ago

I took this as start point https://gist.github.com/oleavr/ae7bcbbb9179852a4731.

Here is the code

gating.js

'use strict';

const co = require('co');
const frida = require('frida');
const load = require('frida-load');

let target, device;

co(function*() {
    device = yield frida.getUsbDevice();
    device.events.listen('spawned', onSpawned);
    device.enableSpawnGating();
    const pending = yield device.enumeratePendingSpawns();
    pending.forEach(function(spawn, i) {
      console.log('pending[' + i + ']=', spawn, ' Resuming!');
      device.resume(spawn.pid);
    });
    console.log('ready');
  })
  .catch(function(error) {
    console.log('mmm error here');
    console.error(error.message);
    process.exitCode = 1;
  });

function onSpawned(spawn) {
  console.log('onSpawned:', spawn);
  co(function*() {
      if (spawn.identifier === 'com.android.insecurebankv2') {
        const session = yield device.attach(spawn.pid);
        const source = yield load(require.resolve('./agent.js'));
        const script = yield session.createScript(source);
        script.events.listen('message', function(message, data) {
          onMessage(spawn, message, data);
        });
        yield script.load();
        const exports = yield script.getExports();
        yield exports.init();
        yield device.resume(spawn.pid);
      } else {
        yield device.resume(spawn.pid);
      }

    })
    .catch(function(error) {
      console.error(error.message);
    });
}

function onMessage(spawn, message, data) {
  console.log(message);
  console.log('onMessage:', spawn, message, data);
}

agent.js

rpc.exports = {
  init: function() {
    'use strict';
    Java.perform(function() {
      var javaFile = Java.use("java.io.File");
      javaFile.exists.implementation = function() {
        console.log('File exists called');
        return this.exists.apply(this, arguments);
      }
    });
  }
};

But I am getting this

air:helper alvaro$ node gating.js
ready
onSpawned: Spawn { identifier: 'com.android.insecurebankv2', pid: 17454 }
onMessage: Spawn { identifier: 'com.android.insecurebankv2', pid: 17454 } { type: 'error',
  description: 'Error: access violation accessing 0x6f0056',
  stack: 'Error: access violation accessing 0x6f0056\n    at frida/node_modules/frida-java/lib/env.js:206\n    at apply (native)\n    at frida/node_modules/frida-java/lib/env.js:201\n    at frida/node_modules/frida-java/lib/class-factory.js:113\n    at frida/node_modules/frida-java/lib/class-factory.js:1621\n    at call (native)\n    at getPackageInfoNoCheck (input:1)\n    at apply (native)\n    at r (frida/node_modules/frida-java/lib/class-factory.js:842)\n    [...]',
  fileName: 'frida/node_modules/frida-java/lib/env.js',
  lineNumber: 206,
  columnNumber: 1 } null

FWIW I've not been able to make spawn, attach and resume to work. I am doing the following being spawn-agent.js the same agent without rpc.exports.

'use strict';

const co = require('co');
const frida = require('frida');
const load = require('frida-load');

let session, script;

co(function *() {
  const device = yield frida.getUsbDevice();
  const pid = yield device.spawn(['com.android.insecurebankv2']);
  session = yield device.attach(pid);
  const source = yield load(
      require.resolve('./spawn-agent.js'));
  script = yield session.createScript(source);
  script.events.listen('message', message => {
    if (message.type === 'send' && message.payload.event === 'ready')
      device.resume(pid);
    else
      console.log(message);
  });
  yield script.load();
})
.catch(console.error);

Here an asciinema https://asciinema.org/a/539my8j4jrmkghbgrdbtb3pdt

Am i doing it wrong ?

alvarofe commented 7 years ago

swapping these two lines

yield exports.init();
yield device.resume(spawn.pid);

for

yield device.resume(spawn.pid);
yield exports.init();

load the script correctly. I assume the process is still not created and this.method.apply crash.

Is this really early instrumentation? I would like to apply the scripts before to resume

pandasauce commented 7 years ago

I am running into the same problem attempting to use one of the cleaned up gating examples:

rpc.exports = {
    init: function () {
        console.log('entered init');
        if (!Java.available) {
            console.log('no java sorry');
        } else {
            console.log('has java!');
            Java.perform(function () {
                console.log('entered java perform');
                const Activity = Java.use("android.app.Activity");
                Activity.onResume.implementation = function () {
                    send("onResume");
                    this.onResume();
                };
            });
        }
    },
}
> python legging.py
Enabled spawn gating
Pending: []
Waiting for data
on_spawned: Spawn(pid=22420, identifier="app_name_sanitized")
Instrumenting: Spawn(pid=22420, identifier="app_name_sanitized")
entered init
has java!
Processed: Spawn(pid=22420, identifier="app_name_sanitized")
Waiting for data
on_message: Spawn(pid=22420, identifier="app_name_sanitized") {'type': 'error', 'description': 'Error: access violation accessing 0x4d008d', 'stack': 'Error: access violation accessing 0x4d008d\n    at frida/node_modules/frida-java/lib/env.js:206\n    at apply (native)\n    at frida/node_modules/frida-java/lib/env.js:201\n    at frida/node_modules/frida-java/lib/class-factory.js:113\n    at frida/node_modules/frida-java/lib/class-factory.js:1621\n
    at call (native)\n    at getPackageInfoNoCheck (input:1)\n    at apply (native)\n    at r (frida/node_modules/frida-java/lib/class-factory.js:842)\n    [...]', 'fileName': 'frida/node_modules/frida-java/lib/env.js', 'lineNumber': 206, 'columnNumber': 1} None
oleavr commented 5 years ago

Issue was in frida-java, and should be fixed.