Android安全:onCreate()函数的Native化
发布日期:2021-06-29 11:29:25 浏览次数:2 分类:技术文章

本文共 6813 字,大约阅读时间需要 22 分钟。

Java

在Android开发一个Activity,常规Java写法如下:

package com.zyc.oncreate2native;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.widget.TextView;public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView txt = findViewById(R.id.txt_main); txt.setText("onCreate-->Native success!"); }}

运行:

在这里插入图片描述
这样的写法放进反编译工具,分析起来几乎没有难度。
在这里插入图片描述
 

Native

上面的代码Native化之后:

#include 
#include
#include
extern "C" JNIEXPORT void JNICALLJava_com_zyc_oncreate2native_MainActivity_onCreate(JNIEnv *env, jobject thiz, jobject saved_instance_state) {
//super.onCreate(savedInstanceState); jclass MainActivity = env->GetObjectClass(thiz); jclass AppCompatActivity = env->GetSuperclass(MainActivity); jmethodID onCreate = env->GetMethodID(AppCompatActivity, "onCreate", "(Landroid/os/Bundle;)V"); env->CallNonvirtualVoidMethod(thiz, AppCompatActivity, onCreate, saved_instance_state); //调用父类方法 //setContentView(R.layout.activity_main); jmethodID setContentView = env->GetMethodID(MainActivity, "setContentView", "(I)V"); jclass Layout = env->FindClass("com/zyc/oncreate2native/R$layout"); //注意R类的写法 jfieldID activity_main = env->GetStaticFieldID(Layout, "activity_main", "I"); jint id_activity_main = env->GetStaticIntField(Layout, activity_main); env->CallVoidMethod(thiz, setContentView, id_activity_main); //TextView txt = findViewById(R.id.txt_main); jmethodID findViewById = env->GetMethodID(MainActivity, "findViewById","(I)Landroid/view/View;"); jclass id = env->FindClass("com/zyc/oncreate2native/R$id"); jfieldID txt_main = env->GetStaticFieldID(id, "txt_main", "I"); jint id_txt_main = env->GetStaticIntField(id, txt_main); jobject txt = env->CallObjectMethod(thiz, findViewById, id_txt_main); //txt.setText("onCreate-->Native success by c++ !!!"); jclass TextView = env->FindClass("android/widget/TextView"); jmethodID setText = env->GetMethodID(TextView, "setText", "(Ljava/lang/CharSequence;)V"); jstring text = env->NewStringUTF("onCreate-->Native success by c++ !!!"); env->CallVoidMethod(txt, setText, text); env->DeleteLocalRef(text);}

运行:

在这里插入图片描述
这时再反编译,Java层就无法看到有用信息了。
在这里插入图片描述
即使找到so文件分析伪C++代码,也头疼多了。

int __cdecl Java_com_zyc_oncreate2native_MainActivity_onCreate(_JNIEnv *a1, int a2, int a3){
int v3; // eax int v4; // ST6C_4 int v5; // eax int v6; // ST68_4 int v7; // eax int v8; // ST60_4 int v9; // eax int v10; // ST5C_4 int v11; // eax char v12; // al int v13; // ST50_4 int v14; // eax int v15; // ST4C_4 int v16; // eax char v17; // al int v18; // ST40_4 int v19; // eax int v20; // ST38_4 int v21; // ST34_4 v3 = _JNIEnv::GetObjectClass(a1, a2); v4 = v3; v5 = _JNIEnv::GetSuperclass(a1, v3); v6 = v5; v7 = _JNIEnv::GetMethodID(a1, v5, 4564, 4573); _JNIEnv::CallNonvirtualVoidMethod(a1, a2, v6, v7, a3); v8 = _JNIEnv::GetMethodID(a1, v4, "setContentView", "(I)V"); v9 = _JNIEnv::FindClass(a1, "com/zyc/oncreate2native/R$layout"); v10 = v9; v11 = _JNIEnv::GetStaticFieldID(a1, v9, 4649, 4663); v12 = _JNIEnv::GetStaticIntField(a1, v10, v11); _JNIEnv::CallVoidMethod(a1, a2, v8, v12); v13 = _JNIEnv::GetMethodID(a1, v4, "findViewById", "(I)Landroid/view/View;"); v14 = _JNIEnv::FindClass(a1, "com/zyc/oncreate2native/R$id"); v15 = v14; v16 = _JNIEnv::GetStaticFieldID(a1, v14, 4730, 4663); v17 = _JNIEnv::GetStaticIntField(a1, v15, v16); v18 = _JNIEnv::CallObjectMethod(a1, a2, v13, v17); v19 = _JNIEnv::FindClass(a1, "android/widget/TextView"); v20 = _JNIEnv::GetMethodID(a1, v19, 4763, 4771); v21 = _JNIEnv::NewStringUTF(a1, "onCreate-->Native success by c++ !!!"); _JNIEnv::CallVoidMethod(a1, v18, v20, v21); return _JNIEnv::DeleteLocalRef(a1, v21);}

当然, Java_com_zyc_oncreate2native_MainActivity_onCreate() 的方法名还是容易暴露,换成改成动态注册:

#include 
#include
#include
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "Tag", __VA_ARGS__)void ffff(JNIEnv *env, jobject thiz, jobject saved_instance_state) {
//super.onCreate(savedInstanceState); jclass MainActivity = env->GetObjectClass(thiz); jclass AppCompatActivity = env->GetSuperclass(MainActivity); jmethodID onCreate = env->GetMethodID(AppCompatActivity, "onCreate", "(Landroid/os/Bundle;)V"); env->CallNonvirtualVoidMethod(thiz, AppCompatActivity, onCreate, saved_instance_state); //调用父类方法 //setContentView(R.layout.activity_main); jmethodID setContentView = env->GetMethodID(MainActivity, "setContentView", "(I)V"); jclass Layout = env->FindClass("com/zyc/oncreate2native/R$layout"); jfieldID activity_main = env->GetStaticFieldID(Layout, "activity_main", "I"); jint id_activity_main = env->GetStaticIntField(Layout, activity_main); env->CallVoidMethod(thiz, setContentView, id_activity_main); //TextView txt = findViewById(R.id.txt_main); jmethodID findViewById = env->GetMethodID(MainActivity, "findViewById", "(I)Landroid/view/View;"); jclass id = env->FindClass("com/zyc/oncreate2native/R$id"); jfieldID txt_main = env->GetStaticFieldID(id, "txt_main", "I"); jint id_txt_main = env->GetStaticIntField(id, txt_main); jobject txt = env->CallObjectMethod(thiz, findViewById, id_txt_main); //txt.setText("onCreate-->Native success by c++ !!!"); jclass TextView = env->FindClass("android/widget/TextView"); jmethodID setText = env->GetMethodID(TextView, "setText", "(Ljava/lang/CharSequence;)V"); jstring text = env->NewStringUTF("onCreate-->Native success by c++ ffff!!!"); env->CallVoidMethod(txt, setText, text); env->DeleteLocalRef(text);}static JNINativeMethod methods[] = {
{
"onCreate", "(Landroid/os/Bundle;)V", (void*)ffff}};static int registerNatives(JNIEnv *env) {
//找到声明native方法的类 const char *className = "com/zyc/oncreate2native/MainActivity"; jclass clazz = env->FindClass(className); if (clazz == NULL) {
return JNI_FALSE; } //注册函数 参数:java类 所要注册的函数数组 注册函数的个数 int methodsNum = sizeof(methods) / sizeof(methods[0]); if (env->RegisterNatives(clazz, methods, methodsNum) < 0) {
return JNI_FALSE; } return JNI_TRUE;}JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL; //获取JNIEnv if (vm->GetEnv(reinterpret_cast
(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1; } assert(env != NULL); if (!registerNatives(env)) {
return -1; } //返回jni 的版本 return JNI_VERSION_1_6;}

这样一来定位 onCreate() 就更加困难了。

在这里插入图片描述
 

总 结

由上面不难看出, onCreate() 函数在Native化后逆向分析起来就困难多了。同理,其他Java函数也可以如法炮制,当然这一方法在提高安全性的同时也降低了开发效率。

转载地址:https://blog.csdn.net/zyc3545/article/details/117019993 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:JavaScript逆向:GlidedSky JSFuck题
下一篇:JavaScript逆向:金某xx网站登陆指纹算法分析

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月09日 08时21分49秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章