亲爱的读者你们好啊,今天主要分享一下 frida 相关的学习文档,见文章最后一节。
Module
var module = Process.findModuleByAddress(Module.findBaseAddress("libc.so"))
module.enumerateSymbols()
enumerateSymbols
返回该 so 的符号表。
还有一个比较类似的函数:enumerateExports
。
enumerateSymbols
对应的是 SHT_SYMTAB
,enumerateExports
对应的是 SHT_DYNSYM
。
两者的区别见文档:
https://refspecs.linuxfoundation.org/LSB_2.1.0/LSB-Core-generic/LSB-Core-generic/elftypes.html
简单理解为,SHT_DYNSYM
是 SHT_SYMTAB
的一个子集,文档里面说明,这两者一般不共存。
Frida的相关源码:
https://github.com/frida/frida-gum/tree/main/gum/backend-elf
ModuleMap
val mm = new ModuleMap([filter]);
创建一个对象,表示当前所有已加载的 so 的快照,可使用 update
函数刷新,filter 用于过滤想要观察的 so。
可以使用 find
函数来寻找其对应的 so:
find(address)
当你有一个地址,但是不知道它属于哪个so的时候,可以使用这个方法。
例子
如果想了解更多关于Frida的API示例和用法,可以访问Frida的JavaScript API文档(https://frida.re/docs/javascript-api/),那里有更详细的指南和使用案例。
此外,GitHub上的frida-snippets项目(https://github.com/iddoeldor/frida-snippets)也包括了许多实用的Frida代码片段。
对于想要深入了解Frida的高级用法的人来说,Learn Frida网站(https://learnfrida.info/advanced_usage/)提供了更加深入的教程和示例。
比如,registerNativeMethods
可用作对抗逆向分析,所以我们可以hook
这个函数:
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.htmlvar 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#977Interceptor.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#129typedef 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* fnPtrvar jClass = jclassAddress2NameMap[args[0]].split('/');var methodName = methodsPtr.add(i * structSize).readPointer().readCString();console.log('\x1b[3' + '6;01' + 'm', JSON.stringify({module: DebugSymbol.fromAddress(fnPtr)['moduleName'], // https://www.frida.re/docs/javascript-api/#debugsymbolpackage: jClass.slice(0, -1).join('.'),class: jClass[jClass.length - 1],method: methodName, // methodsPtr.readPointer().readCString(), // char* namesignature: 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.javaaddress: fnPtr}), '\x1b[39;49;00m');}}});
}Java.perform(RevealNativeMethods);