您的位置:首页 > 房产 > 家装 > 竣工验收备案查询_网页游戏推广平台_查询网址域名ip地址_品牌营销策划怎么写

竣工验收备案查询_网页游戏推广平台_查询网址域名ip地址_品牌营销策划怎么写

2025/7/18 19:18:17 来源:https://blog.csdn.net/linchaolong/article/details/146968846  浏览:    关键词:竣工验收备案查询_网页游戏推广平台_查询网址域名ip地址_品牌营销策划怎么写
竣工验收备案查询_网页游戏推广平台_查询网址域名ip地址_品牌营销策划怎么写

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

RegisterNatives

RegisterNatives 是 JNI(Java Native Interface)的一部分,用于在 Java 类和本地 C/C++ 代码之间注册本地方法。其原型如下:

jint RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint method_count);

参数说明:

  • env:JNIEnv 指针。

  • clazz:Java 类的 jclass 句柄。

  • methods:指向 JNINativeMethod 结构体数组的指针。

  • method_count:要注册的方法数量。

其中,methods 结构体的定义如下:

typedef struct {const char* name;       // 方法名称(指向字符串)const char* signature;  // 方法签名(指向字符串)void* fnPtr;            // 方法的本地实现(指向本地函数)
} JNINativeMethod;

可以看到,每个 JNINativeMethod 结构体由 三个指针 组成:

  1. name(方法名指针)

  2. signature(方法签名指针)

  3. fnPtr(本地方法指针)

一般会有两个 RegisterNatives 函数,CheckJNI 版本只有在调试选项打开时才会调用,我们一般用 JNI 的那个就行。

[+] Found RegisterNatives symbol: _ZN3art12_GLOBAL__N_18CheckJNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi at 0x780d7757a8
[+] Found RegisterNatives symbol: _ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi at 0x780d7eed10

通过 hook RegisterNatives 实现监控 app 中动态注册的 JNI 函数。代码如下:

RegisterNatives.js

// 查找 libart.so 中的 RegisterNatives 地址
function findRegisterNativesAddr() {let symbols = Module.enumerateSymbolsSync("libart.so");let addrRegisterNatives = null;// 遍历所有符号,查找非 CheckJNI 版本的 RegisterNativesfor (let i = 0; i < symbols.length; i++) {let symbol = symbols[i];// 确认符合 RegisterNatives 标准的符号(非 CheckJNI 版本)if (symbol.name.indexOf("CheckJNI") < 0 &&symbol.name.indexOf("RegisterNatives") >= 0) {addrRegisterNatives = symbol.address;console.log("[+] Found RegisterNatives symbol: " + symbol.name + " at " + symbol.address);break;  // 找到第一个匹配的符号即可}}// 如果没有找到 RegisterNatives 地址,返回 nullif (addrRegisterNatives === null) {console.log("[!] No non-CheckJNI RegisterNatives symbol found!");}return addrRegisterNatives;
}// Hook RegisterNatives 函数,打印方法相关信息
function hookRegisterNatives(addrRegisterNatives) {if (addrRegisterNatives !== null) {// 使用 Interceptor 附加到 RegisterNatives 地址Interceptor.attach(addrRegisterNatives, {onEnter: function (args) {// 获取 java 类和方法列表let javaClass = args[1];let className = Java.vm.tryGetEnv().getClassName(javaClass); // 获取类名// 打印 RegisterNatives 的方法参数let methodsPtr = ptr(args[2]);let methodCount = args[3].toInt32();console.log("[RegisterNatives] method_count:", methodCount);// 遍历注册的每个 JNI 方法for (let i = 0; i < methodCount; i++) {let methodPtr = methodsPtr.add(i * Process.pointerSize * 3); // 获取每个方法的指针// 读取每个方法的名称、签名和函数指针let namePtr = Memory.readPointer(methodPtr);let sigPtr = Memory.readPointer(methodPtr.add(Process.pointerSize));let fnPtr = Memory.readPointer(methodPtr.add(Process.pointerSize * 2));let name = Memory.readCString(namePtr); // 方法名称let sig = Memory.readCString(sigPtr);   // 方法签名let symbol = DebugSymbol.fromAddress(fnPtr); // 函数符号信息// 打印每个 JNI 方法的详细信息console.log("[RegisterNatives] Class:", className);console.log("  Method: " + name);console.log("  Signature: " + sig);console.log("  Function Pointer: " + fnPtr);console.log("  Function Symbol: " + symbol);}}});} else {console.log("[!] Cannot hook RegisterNatives because the address is null.");}
}// 执行查找并 hook RegisterNatives
setImmediate(function() {let addrRegisterNatives = findRegisterNativesAddr();hookRegisterNatives(addrRegisterNatives);
});

启动指定 app 并执行脚本

frida -H 127.0.0.1:1234 -l register_natives.js -f packageName

输出如下:

[+] Found RegisterNatives symbol: _ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi at 0x780d7eed10
Spawned `com.shizhuang.duapp`. Use %resume to let the main thread start executing!
[Remote::com.shizhuang.duapp]-> %resume
[Remote::com.shizhuang.duapp]-> [RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: dISignature: (I)IFunction Symbol: 0x77a435693c libGameVMP.so!0xb93c
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: dSSignature: (Ljava/lang/String;)Ljava/lang/String;Function Symbol: 0x77a4356aec libGameVMP.so!0xbaec
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: dLSignature: (J)JFunction Symbol: 0x77a4356ad0 libGameVMP.so!0xbad0
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: IVSignature: ([Ljava/lang/Object;)VFunction Symbol: 0x77a4358fa8 libGameVMP.so!0xdfa8
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: IZSignature: ([Ljava/lang/Object;)ZFunction Symbol: 0x77a4358fa8 libGameVMP.so!0xdfa8
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: IBSignature: ([Ljava/lang/Object;)BFunction Symbol: 0x77a4358fa8 libGameVMP.so!0xdfa8
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: ICSignature: ([Ljava/lang/Object;)CFunction Symbol: 0x77a4358fa8 libGameVMP.so!0xdfa8
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: ISSignature: ([Ljava/lang/Object;)SFunction Symbol: 0x77a4358fa8 libGameVMP.so!0xdfa8
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: IISignature: ([Ljava/lang/Object;)IFunction Symbol: 0x77a4358fa8 libGameVMP.so!0xdfa8
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: IFSignature: ([Ljava/lang/Object;)FFunction Symbol: 0x77a4358fe8 libGameVMP.so!0xdfe8
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: IJSignature: ([Ljava/lang/Object;)JFunction Symbol: 0x77a4358fa8 libGameVMP.so!0xdfa8
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: IDSignature: ([Ljava/lang/Object;)DFunction Symbol: 0x77a4359028 libGameVMP.so!0xe028
[RegisterNatives] method_count: 1
[RegisterNatives] Class: lte.NCallMethod: ILSignature: ([Ljava/lang/Object;)Ljava/lang/Object;Function Symbol: 0x77a4358fa8 libGameVMP.so!0xdfa8

JNIEnv

常用的 JNI 函数在 frida 的 env.js 中都已经定义好了

https://github.com/frida/frida-java-bridge/blob/main/lib/env.js

word/media/image1.png

通过下面代码获取 JNIEnv 引用,就可以调用相关的 JNI 函数

let env = Java.vm.tryGetEnv()

word/media/image2.png

文档:https://frida.re/docs/javascript-api/

读取 String 对象内容

通过 env.js 中定义的 stringFromJni 函数可以直接获取到字符串对象的值

word/media/image3.png

示例代码:

let str = env.stringFromJni(stringObj)
console.log(str);

dlopen

dlopen 函数 在 linker 模块,是 Android 系统上的动态库加载函数,用于在运行时加载共享库(.so 文件)。

你可以在 bionic/linker/dlfcn.cpp 中找到 dlopen 的实现:

void* dlopen(const char* filename, int flags) {return do_dlopen(filename, flags, nullptr);
}

http://aospxref.com/android-11.0.0_r21/xref/bionic/libc/include/dlfcn.h

word/media/image4.png

android_dlopen_ext 是 Android 特有的 dlopen 扩展版本,允许开发者在加载共享库时使用额外的选项,比如 指定库的加载路径 或 共享库的保护标志。

android_dlopen_ext 函数原型

void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo);

参数

  • filename:共享库路径(如 “libnative-lib.so”)。

  • flags:同 dlopen(如 RTLD_LAZY)。

  • extinfo:额外的加载选项,传 NULL 表示默认行为。

通过 frida hook android app 的 so 加载过程,代码如下:

dlopen.js

function hook_dlopen(package_name) {// Hook dlopen 函数const dlopenAddr = Module.findExportByName(null, "dlopen");const dlopen = new NativeFunction(dlopenAddr, 'pointer', ['pointer', 'int']);Interceptor.attach(dlopen, {onEnter(args) {// 获取传递给 dlopen 的参数(SO 文件路径)const soPath = Memory.readUtf8String(args[0]);// 如果是目标 app SO 文件,则打印路径if (package_name) {if (soPath.includes(package_name)) {// 打印信息console.log("dlopen() - Loaded SO file:", soPath);}}else{console.log("dlopen() - Loaded SO file:", soPath);}}, onLeave(retval) {}});// Hook android_dlopen_ext 函数const android_dlopen_extAddr = Module.findExportByName(null, "android_dlopen_ext");const android_dlopen_ext = new NativeFunction(android_dlopen_extAddr, 'pointer', ['pointer', 'int', 'pointer']);Interceptor.attach(android_dlopen_ext, {onEnter(args) {// 获取传递给 android_dlopen_ext 的参数(SO 文件路径)const soPath = Memory.readUtf8String(args[0]);// 如果是目标 app SO 文件,则打印路径if (package_name) {if (soPath.includes(package_name)) {// 打印信息console.log("android_dlopen_ext() - Loaded SO file:", soPath);}}else{console.log("android_dlopen_ext() - Loaded SO file:", soPath);}}, onLeave(retval) {}});
}setImmediate(function () {hook_dlopen("com.shizhuang.duapp")
});

执行脚本

frida -H 127.0.0.1:1234 -l  dlopen.js -f packageName

输出如下:

____/ _  |   Frida 14.2.18 - A world-class dynamic instrumentation toolkit| (_| |> _  |   Commands:/_/ |_|       help      -> Displays the help system. . . .       object?   -> Display information about 'object'. . . .       exit/quit -> Exit. . . .. . . .   More info at https://www.frida.re/docs/home/
Spawned `com.shizhuang.duapp`. Use %resume to let the main thread start executing!
[Remote::com.shizhuang.duapp]-> %resume
[Remote::com.shizhuang.duapp]-> android_dlopen_ext() - Loaded SO file: /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/oat/arm64/base.odex
android_dlopen_ext() - Loaded SO file: /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/lib/arm64/libGameVMP.so
android_dlopen_ext() - Loaded SO file: /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/lib/arm64/libmmkv.so
android_dlopen_ext() - Loaded SO file: /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/lib/arm64/libxcrash.so
android_dlopen_ext() - Loaded SO file: /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/lib/arm64/libdulog.so
android_dlopen_ext() - Loaded SO file: /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/lib/arm64/libduhook.so
android_dlopen_ext() - Loaded SO file: /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/lib/arm64/libheif.so
android_dlopen_ext() - Loaded SO file: /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/lib/arm64/libdewuffmpeg.so
android_dlopen_ext() - Loaded SO file: /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/lib/arm64/libduplayer.so
android_dlopen_ext() - Loaded SO file: /data/app/com.shizhuang.duapp-fTxemmnM8l6298xbBELksQ==/lib/arm64/libstatic-webp.so
android_dlopen_ext() - Loaded SO file: /data/user/0/com.shizhuang.duapp/files/soloader_x64/libxyvodsdk.so
android_dlopen_ext() - Loaded SO file: /data/user/0/com.shizhuang.duapp/files/soloader_x64/libijmdetect_drisk.so
android_dlopen_ext() - Loaded SO file: /data/user/0/com.shizhuang.duapp/files/soloader_x64/libdu_security.so

文件读写

Frida 文件读写相关 api

https://frida.re/docs/javascript-api/#file

word/media/image5.png

写一个字符串到文件:

function writeStringToFile() {try {var appContext = Java.use("android.app.ActivityThread").currentApplication().getApplicationContext();var privateDir = appContext.getExternalFilesDir(null).getAbsolutePath();var path = privateDir + "/cyrus_studio.dat";var file = new File(path, "w");file.write("CYRUS STUDIO");file.flush();file.close();console.log("[+] Successfully wrote to " + path);} catch (e) {console.log("[!] Error: " + e.message);}
}setImmediate(function () {Java.perform(writeStringToFile);
});

执行脚本:

frida -H 127.0.0.1:1234 -l write_string_to_file.js -F

输出如下:

[+] Successfully wrote to /storage/emulated/0/Android/data/com.shizhuang.duapp/files/cyrus_studio.dat

调用 C 函数

在 Frida 中,NativeFunction 用于调用 native 函数。它允许我们在 JavaScript 中调用 C 语言函数,就像普通 JavaScript 函数一样。

基本语法

var func = new NativeFunction(address, returnType, argTypes);
  • address:函数地址,可以用 Module.findExportByName 或 Module.findExportByName(null, “func_name”) 获取。

  • returnType:函数的返回类型,如 “void”、“int”、“pointer” 等。

  • argTypes:一个数组,指定函数的参数类型,如 [“pointer”, “int”]。

在 libc.so 文件操作相关函数原型如下:

// 打开文件
FILE *fopen(const char *filename, const char *mode);
/*
参数:
- filename: 需要打开的文件路径
- mode: 文件打开模式,如 "r"(只读),"w"(写入),"rb"(二进制只读)等
返回值:
- 成功返回 FILE* 指针,失败返回 NULL
*/// 移动文件指针
int fseek(FILE *stream, long offset, int whence);
/*
参数:
- stream: 已打开的文件指针
- offset: 偏移量,以字节为单位
- whence: 参考位置- SEEK_SET (0): 文件开头- SEEK_CUR (1): 当前指针位置- SEEK_END (2): 文件末尾
返回值:
- 成功返回 0,失败返回非零值
*/// 获取当前文件指针位置
long ftell(FILE *stream);
/*
参数:
- stream: 已打开的文件指针
返回值:
- 返回当前文件指针的偏移量(从文件开头算起)
- 失败返回 -1L
*/// 读取文件内容
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
/*
参数:
- ptr: 读取数据的存储缓冲区
- size: 每个数据块的大小(单位:字节)
- count: 读取数据块的个数
- stream: 已打开的文件指针
返回值:
- 返回成功读取的数据块数目
- 失败或到文件末尾返回小于 count 的值
*/// 关闭文件
int fclose(FILE *stream);
/*
参数:
- stream: 需要关闭的文件指针
返回值:
- 成功返回 0,失败返回 EOF(通常为 -1)
*/

在 Android 系统中,这些函数的原型通常可以在 Bionic(Android 的 C 库)中找到。

路径:/bionic/libc/include/stdio.h // Android (Bionic)

word/media/image6.png
http://aospxref.com/android-11.0.0_r21/xref/bionic/libc/include/stdio.h

通过 NativeFunction 封装 系统中 libc.so 文件相关的函数,并调用读取文件内容

function readFileToString() {// 定义 C 语言标准库函数的 Frida 封装var fopen = new NativeFunction(Module.findExportByName("libc.so", "fopen"), "pointer", ["pointer", "pointer"]);var fseek = new NativeFunction(Module.findExportByName("libc.so", "fseek"), "int", ["pointer", "int", "int"]);var ftell = new NativeFunction(Module.findExportByName("libc.so", "ftell"), "long", ["pointer"]);var fread = new NativeFunction(Module.findExportByName("libc.so", "fread"), "int", ["pointer", "long", "int", "pointer"]);var fclose = new NativeFunction(Module.findExportByName("libc.so", "fclose"), "int", ["pointer"]);try {// 获取 Android 应用的上下文var appContext = Java.use("android.app.ActivityThread").currentApplication().getApplicationContext();var privateDir = appContext.getExternalFilesDir(null).getAbsolutePath();var path = privateDir + "/cyrus_studio.dat"; // 目标文件路径// 分配内存存储文件路径和打开模式var mode = Memory.allocUtf8String("rb"); // 以二进制只读模式打开文件var filePath = Memory.allocUtf8String(path);// 调用 fopen 打开文件var fp = fopen(filePath, mode);if (fp.isNull()) {console.log(`[!] Failed to open file ${path} for reading`);} else {// 移动文件指针到文件末尾,计算文件大小fseek(fp, 0, 2); // SEEK_ENDvar size = ftell(fp);fseek(fp, 0, 0); // SEEK_SET(回到文件开头)// 分配缓冲区存储文件内容var buffer = Memory.alloc(size + 1);fread(buffer, size, 1, fp); // 读取文件内容到 bufferfclose(fp); // 关闭文件// 读取缓冲区内容并转换为字符串var content = Memory.readUtf8String(buffer);console.log("[+] File content: " + content);}} catch (e) {console.log("[!] Error: " + e.message);}
}setImmediate(function () {Java.perform(readFileToString);
});

执行脚本

frida -H 127.0.0.1:1234 -l read_file_to_string.js -F

输出如下:

[+] File content: CYRUS STUDIO

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com