Closed illnino closed 7 years ago
@illnino Thanks for finding this interesting issue. This error is happening due to the fact that Frida has recently changed its default JS runtime engine from V8 to Duktape, as V8 is not supported on the recent jailbreaks (because it requires kernel patch to allow RWX pages).
So you can try out two of the following options (and see which one works for you):
session.enable_jit()
before https://github.com/dpnishant/appmon/blob/master/intruder/appintruder.py#L215Do let me know which one worked for you, so that I can decide on the fix for this issue and commit the changes.
If I understand correctly, it should look as below. Unfortunately, I got the same error.
if platform == 'android' and spawn == 1:
print colored("Now Spawning %s" % app_name, "green")
pid = device.spawn([app_name])
session.enable_jit()
session = device.attach(pid)
It seems it no longer complains. However, it looks like it failed to hook the touchid implementation. By clicking the cancel button on 1Password touchid validation page, I got nothing.
Similarly, the same behave in my another testing app.
(venv)➜ intruder git:(nino) ✗ python appintruder.py -a "1Password" -p ios -s scripts/iOS/touchID_compiled.js
___ .______ .______ .___ ___. ______ .__ __.
/ \ | _ \ | _ \ | \/ | / __ \ | \ | |
/ ^ \ | |_) | | |_) | | \ / | | | | | | \| |
/ /_\ \ | ___/ | ___/ | |\/| | | | | | | . ` |
/ _____ \ | | | | | | | | | `--' | | |\ |
/__/ \__\ | _| | _| |__| |__| \______/ |__| \__|
github.com/dpnishant
[INFO] Attached to 1Password
[INFO] Building injection...
[INFO] Instrumentation started...
I am not sure if I compiled it in a correct way. To install frida-compile
with npm install frida-compile
, I got errors.
npm WARN enoent ENOENT: no such file or directory, open '/Users/illnino/package.json'
Then I try npm init
and npm install frida-compile
, it complains npm WARN json@1.0.0 No repository field.
➜ cat package.json
{
"name": "frida-tools",
"version": "1.0.0",
"description": "frida-compile",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "na"
},
"author": "",
"license": "ISC"
}
I ignored the warning, and run
➜ frida-tools cd node_modules/frida-compile/bin
➜ bin ./compile.js ~/touchid.js ~/touchid_compile.js
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/*
Copyright (c) 2016 Nishant Das Patnaik.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
'use strict';
var resolver = new ApiResolver('objc');
var module = {};
const pendingBlocks = new Set();
resolver.enumerateMatches('-[LAContext evaluatePolicy:localizedReason:reply:]', {
onMatch: function (match) {
module.name = match.name;
module.address = match.address;
},
onComplete: function () {}
});
Interceptor.attach(module.address, {
onEnter: function (args) {
var reason = new ObjC.Object(args[3]);
console.log(reason);
var block = new ObjC.Block(args[4]);
pendingBlocks.add(block); // keep it alive
var appCallback = block.implementation;
block.implementation = function (success, error) {
console.log('Fingerprint Matched: ' + success);
var success = true;
appCallback(success, error);
pendingBlocks.delete(block);
};
}
});
},{}]},{},[1])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJ0b3VjaGlkLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7Ozs7Ozs7Ozs7Ozs7Ozs7QUFnQkE7O0FBRUEsSUFBSSxXQUFXLElBQUksV0FBSixDQUFnQixNQUFoQixDQUFmO0FBQ0EsSUFBSSxTQUFTLEVBQWI7QUFDQSxNQUFNLGdCQUFnQixJQUFJLEdBQUosRUFBdEI7O0FBRUEsU0FBUyxnQkFBVCxDQUEwQixvREFBMUIsRUFBZ0Y7QUFDOUUsV0FBUyxVQUFTLEtBQVQsRUFBZ0I7QUFDdkIsV0FBTyxJQUFQLEdBQWMsTUFBTSxJQUFwQjtBQUNBLFdBQU8sT0FBUCxHQUFpQixNQUFNLE9BQXZCO0FBQ0QsR0FKNkU7QUFLOUUsY0FBWSxZQUFXLENBQUU7QUFMcUQsQ0FBaEY7O0FBUUEsWUFBWSxNQUFaLENBQW1CLE9BQU8sT0FBMUIsRUFBbUM7QUFDakMsV0FBUyxVQUFTLElBQVQsRUFBZTs7QUFFdEIsUUFBSSxTQUFTLElBQUksS0FBSyxNQUFULENBQWdCLEtBQUssQ0FBTCxDQUFoQixDQUFiO0FBQ0EsWUFBUSxHQUFSLENBQVksTUFBWjs7QUFFQSxRQUFJLFFBQVEsSUFBSSxLQUFLLEtBQVQsQ0FBZSxLQUFLLENBQUwsQ0FBZixDQUFaO0FBQ0Esa0JBQWMsR0FBZCxDQUFrQixLQUFsQixFQU5zQixDQU1JOztBQUUxQixRQUFJLGNBQWMsTUFBTSxjQUF4Qjs7QUFFQSxVQUFNLGNBQU4sR0FBdUIsVUFBVSxPQUFWLEVBQW1CLEtBQW5CLEVBQTBCO0FBQy9DLGNBQVEsR0FBUixDQUFZLDBCQUEwQixPQUF0QztBQUNBLFVBQUksVUFBVSxJQUFkO0FBQ0Esa0JBQVksT0FBWixFQUFxQixLQUFyQjtBQUNBLG9CQUFjLE1BQWQsQ0FBcUIsS0FBckI7QUFDRCxLQUxEO0FBTUQ7QUFqQmdDLENBQW5DIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIifQ==
@illnino Try a different app as the "touchid" script only hooks the LocalAuthentication method for TouchID integration, but if the app uses the Keychain Services (Security.framework) method to integrate TouchID then it might not hook. If later is the case, then its a known issue and so far there is no work around for it, at least not known to me.
More info here: https://www.synopsys.com/blogs/software-security/integrating-touch-id-into-ios-applications/
@dpnishant Thanks for the information. I am able to bypass the TouchID authentication with below script on the same App. And it should hook API - - evaluatePolicy:localizedReason:reply:
if(ObjC.available) {
var hook = ObjC.classes.LAContext["- evaluatePolicy:localizedReason:reply:"];
Interceptor.attach(hook.implementation, {
onEnter: function(args) {
send("Hooking Touch Id..")
var block = new ObjC.Block(args[4]);
const appCallback = block.implementation;
block.implementation = function (error, value) {
const result = appCallback(1, null);
return result;
};
},
});
} else {
console.log("Objective-C Runtime is not available!");
}
@illnino That script has a dangerous bug: it does not keep the block
JS variable alive, so if it gets GCed before the method is finished with the block it will result in a use-after-free. The fix is simple, though: you can create an array at the top of the script, e.g. var pendingBlocks = [];
, and pendingBlocks.push(block);
after creation, and inside the block: pendingBlocks.splice(pendingBlocks.indexOf(block), 1);
in the callback.
@oleavr Thank you so much for explanation. @illnino Can you please check out new touchID script and see it its working for you?
ENV
Mac OS 10.11.6 iPhone 6s Jailbroken iOS 9.0 Frida 10.0.3
Reproduction Steps
FYI
AppMon Sniffer works properly