refactoring reveal obfuscated native methods

This commit is contained in:
iddoeldor 2018-08-26 12:19:43 +03:00 committed by GitHub
parent e0f52d9bae
commit 44300f35af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,14 +1,13 @@
var isLibARThooked = false; // $ frida -Uf com.app --no-pause -l scripts.js
var fIntercepted = false;
function hookLibART() { function revealNativeMethods() {
if (isLibARThooked === true) { if (fIntercepted === true) {
return; return;
} }
var symbols = Module.enumerateSymbolsSync("libart.so");
var addrRegisterNativeMethods;
var jclassAddress2NameMap = {}; var jclassAddress2NameMap = {};
for (i = 0; i < symbols.length; i++) { var androidRunTimeSharedLibrary = "libart.so"; // may change between devices
var symbol = symbols[i]; Module.enumerateSymbolsSync(androidRunTimeSharedLibrary).forEach(function(symbol){
switch (symbol.name) { switch (symbol.name) {
case "_ZN3art3JNI21RegisterNativeMethodsEP7_JNIEnvP7_jclassPK15JNINativeMethodib": case "_ZN3art3JNI21RegisterNativeMethodsEP7_JNIEnvP7_jclassPK15JNINativeMethodib":
/* /*
@ -16,22 +15,33 @@ function hookLibART() {
https://demangler.com/ https://demangler.com/
art::JNI::RegisterNativeMethods(_JNIEnv*, _jclass*, JNINativeMethod const*, int, bool) art::JNI::RegisterNativeMethods(_JNIEnv*, _jclass*, JNINativeMethod const*, int, bool)
*/ */
addrRegisterNativeMethods = symbol.address; var RegisterNativeMethodsPtr = symbol.address;
console.log("RegisterNativeMethods is at " + addrRegisterNativeMethods); console.log("RegisterNativeMethods is at " + RegisterNativeMethodsPtr);
Interceptor.attach(addrRegisterNativeMethods, { Interceptor.attach(RegisterNativeMethodsPtr, {
onEnter: function(args) { onEnter: function(args) {
var methodsPtr = ptr(args[2]); var methodsPtr = ptr(args[2]);
var methodCount = parseInt(args[3]); var methodCount = parseInt(args[3]);
for (var i = 0; i < methodCount; i++) { for (var i = 0; i < methodCount; i++) {
var namePtr = Memory.readPointer(methodsPtr.add(i * 12)); var pSize = Process.pointerSize;
var sigPtr = Memory.readPointer(methodsPtr.add(i * 12 + 4)); /*
var fnPtrPtr = Memory.readPointer(methodsPtr.add(i * 12 + 8)); https://android.googlesource.com/platform/libnativehelper/+/master/include_jni/jni.h#129
typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
*/
var structSize = pSize * 3; // JNINativeMethod contains 3 pointers
var namePtr = Memory.readPointer(methodsPtr.add(i * structSize));
var sigPtr = Memory.readPointer(methodsPtr.add(i * structSize + pSize));
var fnPtrPtr = Memory.readPointer(methodsPtr.add(i * structSize + (pSize * 2)));
// output schema: className#methodName(arguments)returnVal@address // output schema: className#methodName(arguments)returnVal@address
console.log( console.log(
// package & class, replacing forward slash with dot for convenience
jclassAddress2NameMap[args[0]].replace(/\//g, '.') + jclassAddress2NameMap[args[0]].replace(/\//g, '.') +
'#' + Memory.readCString(namePtr) + '#' + Memory.readCString(namePtr) + // method
Memory.readCString(sigPtr) + Memory.readCString(sigPtr) + // signature (arguments & return type)
'@' + fnPtrPtr '@' + fnPtrPtr // C side address
); );
} }
}, },
@ -49,16 +59,11 @@ function hookLibART() {
}); });
break; break;
} }
} });
fIntercepted = true;
isLibARThooked = true;
} }
Java.perform(function () { Java.perform(revealNativeMethods);
try {
hookLibART(); // TODO update
} catch (e) { // https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05j-Testing-Resiliency-Against-Reverse-Engineering.md
// safety first
console.error('[?]', e);
}
});