帮你把java代码翻译到c/c++ jni调用
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了帮你把java代码翻译到c/c++ jni调用,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4427字,纯文字阅读大概需要7分钟。
内容图文
简介
andorid上有个工具叫dex2oat,在apk安装的阶段会把dex转换成elf的二进制格式。基于此思路扩展,如果我们在java字节码生成后产品发布前就把java字节码转换成平台的c/c++ jni调用代码,结合ollvm,那么对外发布的直接就是一个高度混淆的二进制的jni动态库,其逆向难度会大大的增强。(主要场景在于android java && 对外开放jar包代码保护)
实例
以 http://androidxref.com/9.0.0_r3/xref/art/test/003-omnibus-opcodes/src/Goto.java 为例
static int smallGoto(boolean which) {
System.out.println("Goto.smallGoto");
int i = 0;
if (which) {
i += filler(i);
} else {
i -= filler(i);
}
return i;
}
新建idea工程导入Goto.java,编译工程生成jar。编写规则文件config_test.yaml
apikey: helloworld
rules:
- com.test.TestCompiler.Goto:
compile:
- smallGoto: 'cons,bogus,call'
libname: hello
platform:
- MacOS-x64
使用命令行与编译服务器交互
./javatojni_helper_mac --infile=./jar_test.jar --config=./config_test.yaml
编译服务器会接收到jar后,解析生成的jar的字节码得到cfg
再将cfg转换成ssa ir形式,过程中推导出变量的类型&生命周期&异常处理表,最后codegen把ir转换到c/c++ jni代码
//Java_com_test_TestCompiler_Goto.cpp
#include "java2cpp.h"
#include "ids.h"
extern "C" JNIEXPORT jint JNICALL Java_com_test_TestCompiler_Goto_smallGoto__Z(JNIEnv *env, jobject thiz, jboolean in_parameter_0) {
/*
0 boolean
*/
//LOG_DEBUG("call method: %s", R"###(com.test.TestCompiler.Goto: int smallGoto(boolean))###");
jclass _java_lang_System_jclass = NULL;
jclass _com_test_TestCompiler_Goto_jclass = NULL;
jclass _java_io_PrintStream_jclass = NULL;
jvalue temp;
jthrowable exception;
jboolean local_z0;
jobject $r0 = NULL;
jint $i0;
jint $i1;
jint local_i2;
jint local_i3;
jboolean local_z1;
jint local_i4;
label0:{
temp.z = in_parameter_0;
local_z0 = temp.z;
temp = java2cpp_get_static_field(env, &_java_lang_System_jclass, &__0003cjava_lang_System_0003a_00020java_io_PrintStream_00020out_0003e_jfleidID, "java/lang/System", "out", "Ljava/io/PrintStream;", JValueType_l);
JAVA2CPP_GOTO_IF_EXCEPTION(L_TOP_EX_HANDLE);
JAVA2CPP_DELETE_OBJECT($r0);
$r0 = temp.l;
jvalue var_arg_1[1] = {{.l=0},};
temp.l = env->NewStringUTF("\x47\x6f\x74\x6f\x2e\x73\x6d\x61\x6c\x6c\x47\x6f\x74\x6f");
JAVA2CPP_GOTO_IF_EXCEPTION(L_TOP_EX_HANDLE);
AutoObject var_arg_2(env, temp.l);
var_arg_1[0].l = temp.l;
temp = java2cpp_call_instance_method(env, $r0, &_java_io_PrintStream_jclass, &__0003cjava_io_PrintStream_0003a_00020void_00020println_00028java_lang_String_00029_0003e_jmethodID, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", var_arg_1, JValueType_v);
var_arg_2.reset();
JAVA2CPP_GOTO_IF_EXCEPTION(L_TOP_EX_HANDLE);
temp.i = 0;
local_i2 = temp.i;
temp.z = local_z0;
local_z1 = temp.z;
temp.i = (jint)local_z1;
local_i4 = temp.i;
if(local_i4 == 0) {
goto label1;
}
jvalue var_arg_3[1] = {{.l=0},};
var_arg_3[0].i = local_i2;
temp = java2cpp_call_static_method(env, &_com_test_TestCompiler_Goto_jclass, &__0003ccom_test_TestCompiler_Goto_0003a_00020int_00020filler_00028int_00029_0003e_jmethodID, "com/test/TestCompiler/Goto", "filler", "(I)I", var_arg_3, JValueType_i);
JAVA2CPP_GOTO_IF_EXCEPTION(L_TOP_EX_HANDLE);
$i1 = temp.i;
temp.i = local_i2 + $i1;
local_i3 = temp.i;
goto label2;
}
label1:{
jvalue var_arg_4[1] = {{.l=0},};
var_arg_4[0].i = local_i2;
temp = java2cpp_call_static_method(env, &_com_test_TestCompiler_Goto_jclass, &__0003ccom_test_TestCompiler_Goto_0003a_00020int_00020filler_00028int_00029_0003e_jmethodID, "com/test/TestCompiler/Goto", "filler", "(I)I", var_arg_4, JValueType_i);
JAVA2CPP_GOTO_IF_EXCEPTION(L_TOP_EX_HANDLE);
$i0 = temp.i;
temp.i = local_i2 - $i0;
local_i3 = temp.i;
}
label2:{
temp.i = local_i3;
return temp.i;
}
L_TOP_EX_HANDLE:
return 0;
}
自动生成的c/c++ jni代码在数值赋值方面比较啰嗦,还好clang -o2会帮我们负重前行。此时原先数行的java字节码已经变成数百行的汇编代码
未混淆的ida f5伪代码
未混淆的流程图
如果结合ollvm,原来数百行汇编代码又将膨胀变成数千行的汇编代码,此时ida f5伪代码已经不能正常工作
混淆后的流程图
已知问题
1)由于local-reference-table存在上限,如果jni函数内有大量的jobject对象,运行时有可能造成局部表溢出触发异常
2)jvm标准规定某些函数不能为native(例如构造函数),而android中的实现又允许,为多平台翻译一致性差异部分统一成不翻译
3)synchronized暂不支持字符串常量,例如某函数有类似以下写法,目前该函数不会被翻译
private int testCompiler() {
synchronized ("mylock"){
}
return 0;
}
- Android O, DEX 38新增的invoke-custom指令暂不支持
运行性能
待补充
先说结论,首先性能肯定是变慢的,现代jvm对字节码执行做了大量的优化,通过jni调用外部函数会有额外的开销,具体性能影响视要翻译的java代码而定,jvm和jni交互的越多则越慢。
竞品对比
待补充
内容总结
以上是互联网集市为您收集整理的帮你把java代码翻译到c/c++ jni调用全部内容,希望文章能够帮你解决帮你把java代码翻译到c/c++ jni调用所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。