你如何使用 frida 挂钩一个原生的剥离库?
Posted
技术标签:
【中文标题】你如何使用 frida 挂钩一个原生的剥离库?【英文标题】:How do you hook a native stripped library using frida? 【发布时间】:2020-02-17 20:30:05 【问题描述】:在 java 内部,它从“something.so”调用本机函数:
public static native byte[] functionName(int i, byte[] bArr);
如您所见,此函数应该返回字节数组。所以我尝试了这个:
Interceptor.attach (Module.findExportByName ( "something.so", "functionName"),
onEnter: function (args)
console.log("entered");
var ptr_data = env.getClassName(args[1]);
var length = args[2];
var data = Memory.readByteArray(ptr_data, length);
console.log(data);
);
但是 frida 不能返回任何结果。甚至没有打印“输入”。请注意,如果您使用 ida 打开,您将看不到名称“functionName”,因为它被剥离了 elf (.so) 我不知道“functionName”的这个位置在哪里,我想找到它,因为它包含很多垃圾代码。
还有其他方法可以使用 frida 找到它吗? 请写一个例子并与我分享。
【问题讨论】:
你的帖子让我很困惑。一方面,您在谈论类(通常表示“Java 类”) - 另一方面,您正在使用代码来挂钩本机(例如 C/C++,因此是非 Java)方法。 @Robert 感谢您解决这个问题。我编辑了帖子,我的意思是在java类中它调用了本机函数functionName 您应该提供更多详细信息 - 确切的类、方法和函数名称,否则您很可能得不到答案,因为不清楚问题出在哪里。 没有其他线索它被剥夺了精灵,你用ida看不到里面的任何东西 什么是“什么都不是”?通常你至少得到函数列表,可能没有名字。您尝试使用导出函数的任何人,因此我假设有一个导出方法列表。 【参考方案1】:可以原生注册,不会导出,也就是说Module.enumerateExports
看不到它
这个 sn-p 将挂钩 JNI RegisterNatives 并显示函数名称偏移量,您可以通过 Module.findBaseAddress('something.so').add(offset)
拦截该偏移量
registerNativeMethods 可用于对抗本机 .so 库的反逆向技术,例如尽可能隐藏符号,混淆导出的符号并最终在 JNI 桥上添加一些保护。 Find manually registered (obfuscated) native function address
var RevealNativeMethods = function()
var pSize = Process.pointerSize;
var env = Java.vm.getEnv();
var RegisterNatives = 215, FindClassIndex = 6; // search "215" @ https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html
var jclassAddress2NameMap = ;
function getNativeAddress(idx)
return env.handle.readPointer().add(idx * pSize).readPointer();
// intercepting FindClass to populate Map<address, jclass>
Interceptor.attach(getNativeAddress(FindClassIndex),
onEnter: function(args)
jclassAddress2NameMap[args[0]] = args[1].readCString();
);
// RegisterNative(jClass*, .., JNINativeMethod *methods[nMethods], uint nMethods) // https://android.googlesource.com/platform/libnativehelper/+/master/include_jni/jni.h#977
Interceptor.attach(getNativeAddress(RegisterNatives),
onEnter: function(args)
for (var i = 0, nMethods = parseInt(args[3]); i < nMethods; i++)
/*
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; // = sizeof(JNINativeMethod)
var methodsPtr = ptr(args[2]);
var signature = methodsPtr.add(i * structSize + pSize).readPointer();
var fnPtr = methodsPtr.add(i * structSize + (pSize * 2)).readPointer(); // void* fnPtr
var jClass = jclassAddress2NameMap[args[0]].split('/');
console.log('\x1b[3' + '6;01' + 'm', JSON.stringify(
module: DebugSymbol.fromAddress(fnPtr)['moduleName'], // https://www.frida.re/docs/javascript-api/#debugsymbol
package: jClass.slice(0, -1).join('.'),
class: jClass[jClass.length - 1],
method: methodsPtr.readPointer().readCString(), // char* name
signature: signature.readCString(), // char* signature TODO Java bytecode signature parser Z: 'boolean', B: 'byte', C: 'char', S: 'short', I: 'int', J: 'long', F: 'float', D: 'double', L: 'fully-qualified-class;', '[': 'array' https://github.com/skylot/jadx/blob/master/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java
address: fnPtr
), '\x1b[39;49;00m');
);
Java.perform(RevealNativeMethods);
【讨论】:
以上是关于你如何使用 frida 挂钩一个原生的剥离库?的主要内容,如果未能解决你的问题,请参考以下文章
Frida - Windows 原生应用程序 - 读取 Wininet.h 公开的结构
Frida 服务器应用程序在与 Android 设备挂钩时崩溃
使用 Mingw32 安装 gmp 时如何修复无休止的“检查是不是可以剥离库”