[FlareOn2]Android
[FlareOn2]Android
native层逆向,将apk后缀改为zip解压,在lib中找到对应so文件,或者jadx选中so文件右键导出
这个函数参数IDA识别错了,选中对应参数按Y修改,前两个是固定的,又vaildata()输入参数类型是string,所以第三个参数类型为jstring,修改好后是这样的
1 | jstring __fastcall Java_com_flareon_flare_ValidateActivity_validate(JNIEnv *env, jobject obj, jstring input) |
脚本:
- 读取地址表
t1
从文件偏移 0x5004 - 0x1000 = 0x4004
处读取 23 个地址,组成地址表 t1
。
调整偏移的原因:ELF 文件在内存中的加载基址通常为 0x1000
,文件偏移需减去基址得到实际物理偏移。
- 读取质数表
word_2214
数据内容:word_2214
是一个长度为 3476 的数组,存储质数(如 [2, 3, 5, 7, 11, ...]
)。
用途:后续计算中,每个位置 j
的质数 word_2214[j]
将作为基底。
计算生成字节流
res
- 遍历
t1
中的每个地址i
,转换为文件偏移offset = i - 0x1000
。 - 读取该偏移处的数据块,解包为数组
a
。 - 对每个元素
a[j]
,若不为零,则计算word_2214[j] ** a[j]
,并将所有结果累乘到v
。 - 将
v
拆分为高 8 位和低 8 位,存入res
列表。
- 遍历
示例
假设
word_2214 = [2, 3, 5]
,且某次循环中a = [1, 2, 0]
:- 计算
v = 2^1 * 3^2 * 5^0 = 2 * 9 * 1 = 18
。 - 拆分字节:
18 = 0x12
→ 高 8 位0x00
,低 8 位0x12
→res += [0x00, 0x12]
。 - 最终字符:
chr(0x00)
(不可见)和chr(0x12)
(ASCII 控制字符)。
- 计算
1 | import struct |
[前置知识]java静态注册参数类型
在 JNI(Java Native Interface)中,Java_com_example_MyClass_myMethod
这类通过静态注册生成的 Native 函数的前两个参数是固定的,它们的含义和类型由 JNI 规范定义。以下是详细解释:
前两个参数的固定含义
参数顺序 | 参数类型 | 参数名称 | 说明 |
---|---|---|---|
第1个参数 | JNIEnv* |
env |
JNI 环境指针,提供访问 JNI 函数表的接口(如操作字符串、数组、调用方法等)。 |
第2个参数 | jobject 或 jclass |
obj /clazz |
调用上下文对象,具体类型取决于 Java 方法是 实例方法 还是 静态方法。 |
第二个参数的具体类型
1. 实例方法(非静态方法)
- Java 方法定义:
1 | public native void myInstanceMethod(); // 实例方法 |
- Native 函数签名:
1 | JNIEXPORT void JNICALL Java_com_example_MyClass_myInstanceMethod(JNIEnv* env, jobject obj); |
- 第二个参数
jobject obj
:表示调用该 Native 方法的 Java 对象实例(即this
)。
2. 静态方法
- Java 方法定义:
1 | public static native void myStaticMethod(); // 静态方法 |
- Native 函数签名:
1 | JNIEXPORT void JNICALL Java_com_example_MyClass_myStaticMethod(JNIEnv* env, jclass clazz); |
- 第二个参数
jclass clazz
:表示调用该 Native 方法的 Java 类对象(即MyClass.class
)。
参数的作用和用法
1. JNIEnv\* env
- 核心功能:
通过env
指针可以调用 JNI 提供的 所有功能函数,例如:- 字符串操作:
env->NewStringUTF()
,env->GetStringUTFChars()
。 - 数组操作:
env->GetIntArrayElements()
。 - 方法调用:
env->CallVoidMethod()
,env->CallStaticObjectMethod()
。 - 异常处理:
env->ExceptionCheck()
。
- 字符串操作:
- 线程安全:
JNIEnv*
是线程相关的,不可跨线程使用(每个线程需通过JavaVM
获取自己的JNIEnv
)。
2. jobject obj
或 jclass clazz
操作对象实例(
jobject obj
):
通过obj
可以访问实例的字段或方法:cpp
复制
1
2
3
4// 获取实例字段的 fieldID
jfieldID fieldId = env->GetFieldID(env->GetObjectClass(obj), "fieldName", "I");
// 修改字段值
env->SetIntField(obj, fieldId, 100);操作静态成员(
jclass clazz
):
通过clazz
可以访问类的静态字段或方法:cpp
复制
1
2
3
4// 获取静态字段的 fieldID
jfieldID staticFieldId = env->GetStaticFieldID(clazz, "staticFieldName", "I");
// 修改静态字段值
env->SetStaticIntField(clazz, staticFieldId, 200);
示例代码
1. 实例方法示例
1 | // Java 实例方法:public native String getMessage(); |
2. 静态方法示例
1 | // Java 静态方法:public static native int add(int a, int b); |
常见问题
1. 为什么第二个参数类型不同?
- 设计逻辑:
实例方法需要操作具体对象(this
),而静态方法属于类本身,无需对象实例。
2. 能否在静态方法中访问实例字段?
- 不能:静态方法没有
jobject obj
参数(无对象实例),只能通过FindClass
和GetStaticFieldID
操作静态成员。
3. 如何获取 jclass
?
- 方法 1:通过
env->GetObjectClass(obj)
(实例方法中可用)。 - 方法 2:通过
env->FindClass("com/example/MyClass")
(需全限定类名,用/
代替.
)。
总结
- 前两个参数固定:
JNIEnv* env
+jobject
(实例方法)或jclass
(静态方法)。 - 核心用途:
env
:调用 JNI 函数,操作 Java 对象和资源。obj
/clazz
:访问调用上下文(实例或类)。
- 注意事项:线程安全、参数类型匹配、资源释放(如
ReleaseStringUTFChars
)。
参考链接
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Elliot-Lin!