2023-01-19 391
我试图理解一个android应用,该应用程序包含一个名为foo的本机方法com.app.Bar
class Bar有一个静态子句加载共享对象System.loadLibrary(“libfoo.so”)我假设是用 – fvisibility = hidden 因为唯一的导出是JNI_OnLoad,no JNIEXPORT void JNICALL Java_com_app_Bar_foo no JNIEXPORT void JNICALL Java_com_app_Bar_foo public native int foo不遵循 naming judvention .
到目前为止我尝试了什么?
jnianalyzer 输出13K线,看起来像JNI_OnLoad@@Base+0x712e
frida脚本尝试查找foo地址(不起作用)
function intercept(address) {
try {
Interceptor.attach(address, {
onEnter: function(args) {
console.log("onEnter", address);
},
onLeave: function(ignored) {}
});
} catch (e) {
console.error(e);
}
}
function Main() {
var dlopen = new NativeFunction(Module.findExportByName(null, 'dlopen'), 'pointer', ['pointer', 'int']);
var dlsym = new NativeFunction(Module.findExportByName(null, 'dlsym'), 'pointer', ['pointer', 'pointer']);
Process.enumerateModulesSync().forEach(function(m) {
if (m.name === "libfoo.so") {
console.log("Module", JSON.stringify(m));
var handle = dlopen(Memory.allocUtf8String(m.path), 1);
var symb = Memory.allocUtf8String("foo");
var exports = Module.enumerateExportsSync(m.name);
console.log(JSON.stringify({
handle: handle,
symb: symb,
dlsym: dlsym(handle, symb),
exports: exports.map(function(ex){ return ex.address + ": " + ex.name })
}, null, 2));
// intercept all exports
exports.forEach(function(ex){
intercept(ex.address);
});
// explicit intercept foo by known offset
intercept(m.base.add(0x22334)); // this outputs "Error: unable to intercept function at 0x86c96328; please file a bug"
}
});
console.log("sleep..");
Thread.sleep(1.5);
console.log("invoke", Java.use('com.clazz.foo').signToken("A".repeat(32)));
}
Java.perform(Main);
我已经使用Frida
解决了它
挂钩art::JNI::RegisterNativeMethods(_JNIEnv*, _jclass*, JNINativeMethod const*, int, bool)和art::JNI::FindClass libart.so模块后.
代码
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);
我认为是用-fvisibility =隐藏的,因为唯一的导出是jni_onload,no jniexport void jnicall jnicall jnicall jnicall jnicall jnicall_com_app_bar_foo,这意味着public int int foo不遵循命名约定.
这是并不总是true ,因为您也可以在JNI_OnLoad内使用RegisterNatives来声明您的JNI方法不遵循典型的命名约定.
/*
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
clazz = env->FindClass(className);
if (clazz == NULL) {
ALOGE("Native registration unable to find class '%s'", className);
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
ALOGE("RegisterNatives failed for '%s'", className);
return JNI_FALSE;
}
return JNI_TRUE;
}
调用foo时的过程是什么?
也许您可以看一下这篇文章 https://arophix. com/2017/12/17/andoid-jni-summary/
如何提取Foo的地址? (我熟悉弗里达)
我不确定Frida,对于Cydia底物,您可以使用dlsym找到.so的指定符号的地址,例如.
void* find_symbol(const char* libraryname, const char* symbolname)
{
void *imagehandle = dlopen(libraryname, RTLD_GLOBAL | RTLD_NOW);
if (imagehandle != NULL) {
void * sym = dlsym(imagehandle, symbolname);
if (sym != NULL) {
LOGE("symbol (%s) is found at address %p (%p) in lib %s", symbolname, sym, &sym, libraryname);
return sym;
} else {
LOGE("find_symbol() can't find symblo (%s).", symbolname);
return NULL;
}
} else {
LOGE("dlopen error: %s, when opening lib %s",dlerror(), libraryname);
return NULL;
}
}
这是用于使用Cydia底物 https://arophix的完整教程. com/2017/11/30/android-substrate-hooking/,
——————————
编辑#1
对于弗里达,也许是相似的.这是一个参考链接,可能有助于您的情况. https://www.notsosecure.com/instrumenting-native-android-函数 – 使用frida/
编辑#2
有关一个完整的GitHub教程项目,请参阅使用Apkktool和Frida进行反向工程在Android apk上..
以上所述是小编给大家介绍的查找手动注册(混淆)的本地函数地址,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!
原文链接:https://77isp.com/post/25904.html
=========================================
https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。
数据库技术 2022-03-28
网站技术 2022-11-26
网站技术 2023-01-07
网站技术 2022-11-17
Windows相关 2022-02-23
网站技术 2023-01-14
Windows相关 2022-02-16
Windows相关 2022-02-16
Linux相关 2022-02-27
数据库技术 2022-02-20
抠敌 2023年10月23日
嚼餐 2023年10月23日
男忌 2023年10月22日
瓮仆 2023年10月22日
簿偌 2023年10月22日
扫码二维码
获取最新动态