大神论坛

找回密码
快速注册
查看: 442 | 回复: 0

[原创] 安卓逆向破解教程十、不是我说,有了IDA还要什么女朋友?

主题

帖子

0

积分

初入江湖

UID
561
积分
0
精华
威望
0 点
违规
大神币
68 枚
注册时间
2023-09-16 14:56
发表于 2023-09-16 16:45
本帖最后由 cdp20031308 于 2023-09-16 16:45 编辑

一、课程目标


1.初识ELF文件格式、常见节区
2.了解NDK开发,写一个简单的so
3.学习IDA Pro工具的使用来分析so文件
4.通过学习ARM基础知识,能进行简单的修改
5.通过Chatgpt&IDA快速分析二进制文件**

二、工具


1.教程Demo(更新)
2.MT管理器/NP管理器
3.IDA Pro
4.雷电模拟器
5.Android Studio

三、课程内容


1. 初识ELF文件格式

ELF(Executable and Linkable Format)是一种可执行和可链接的文件格式,是linux底下二进制文件,可以理解为windows下的PE文件,在Android中可以比作dll,方便函数的移植,在常用于保护Android软件,增加逆向难度。

ELF文件的主要组成部分包括:

  • ELF Header:文件头,描述文件的基本信息

  • Program Header Table:程序头表,描述进程映像的布局

  • Section Header Table:节区头表,描述文件的各个节区

2.NDK开发

NDK(Native Development Kit)是一套用于开发Android应用程序的工具集,它允许您在C/C++中编写性能关键的部分代码,并将这些代码与Java代码进行连接。

步骤:
1.下载NDK和CMake

2.新建一个项目,往下拉,找到"c++"这个选项
3.查看CMakeLists.txt和编写native-lib.cpp
下面是cmakelist.txt和native-lib.cpp文件的作用以及简要说明:

public class MainActivity extends AppCompatActivity {

// Used to load the 'ndkdemo' library on application startup.
static {
System.loadLibrary("ndkdemo"); // 加载名为"ndkdemo"的库
}

private ActivityMainBinding binding; // 声明一个ActivityMainBinding变量

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

binding = ActivityMainBinding.inflate(getLayoutInflater()); // 使用ViewBinding将布局文件解析为一个ActivityMainBinding对象
setContentView(binding.getRoot()); // 将Activity的布局设置为根布局

// Example of a call to a native method
TextView tv = binding.sampleText; // 获取布局文件中的TextView控件
tv.setText(stringFromJNI()); // 调用本地方法stringFromJNI()并将其返回的字符串设置为TextView的文本内容
}

/**
* A native method that is implemented by the 'ndkdemo' native library,
* which is packaged with this application.
*/
public native String stringFromJNI(); // 声明一个native方法stringFromJNI()
}
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# 设置构建本地库所需的CMake的最小版本要求
cmake_minimum_required(VERSION 3.22.1)

# 声明和命名项目
project("ndkdemo")

# 创建并命名一个库,设置其类型为STATIC或SHARED,并指定源代码的相对路径
# 可以定义多个库,CMake会为您构建它们
# Gradle会自动将共享库打包到APK中
add_library(
# 设置库的名称
ndkdemo

# 设置库类型为共享库
SHARED

# 提供源文件的相对路径
native-lib.cpp)

# 搜索指定的预构建库并将路径存储为变量。
# 由于CMake默认在搜索路径中包含系统库,因此您只需指定要添加的公共NDK库的名称。
# CMake会在完成构建之前验证该库是否存在。
find_library(
# 设置路径变量的名称
log-lib

# 指定要让CMake定位的NDK库的名称
log)

# 指定CMake应链接到目标库的库。
# 您可以链接多个库,例如在此构建脚本中定义的库、预构建的第三方库或系统库。
target_link_libraries(
# 指定目标库
ndkdemo

# 将目标库链接到NDK中包含的log库
${log-lib})
#include <jni.h> // JNI头文件,提供了JNI函数和数据类型的定义
#include <string> // C++标准库的string类

// 声明一个jni函数,该函数将会被Java代码调用
// JNIEXPORT表示这个函数是可导出的,并且可以被其他代码使用
// jstring表示这个函数返回的是一个Java字符串对象
// JNICALL是JNI函数的调用约定
// Java_com_example_ndkdemo_MainActivity_stringFromJNI是JNI函数的命名规则,与Java中对应的方法名对应
// Java打头,1包名,2类名,3方法名字;"_"号隔开
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ndkdemo_MainActivity_stringFromJNI(
JNIEnv* env, // JNIEnv是指向JNI环境的指针,可以用来访问JNI提供的功能
jobject /* this */) { // jobject是指向Java对象的指针,在本例中并没有使用

std::string hello = "Hello from C++"; // 创建一个C++字符串对象
return env->NewStringUTF(hello.c_str()); // 将C++字符串对象转换为Java字符串对象并返回
}

1.JNI的前世今生

NDK是开发套件,JNI才是调用的框架。所以与其说是NDK开发,不如说是JNI的开发。不过NDK是Android提供的开发套件。JNI可不是,JNI全称Java Native Interface,即Java本地接口,JNI是Java调用Native 语言的一种特性。通过JNI可以使得Java与C/C++机型交互。即可以在Java代码中调用C/C++等语言的代码或者在C/C++代码中调用Java代码。

2.JNI的两种注册方式

jni静态注册方式

  • 优点: 理解和使用方式简单, 属于傻瓜式操作, 使用相关工具按流程操作就行, 出错率低

  • 缺点: 当需要更改类名,包名或者方法时, 需要按照之前方法重新生成头文件, 灵活性不高

    jni动态注册方式

  • #include <jni.h>
    #include <string>

    extern "C" {

    JNIEXPORT jstring JNICALL Java_com_example_ndkdemo_MainActivity_nativeGetStringFromJNI(JNIEnv* env, jobject obj) {
    std::string hello = "Hello wuaipojie";
    return env->NewStringUTF(hello.c_str());
    }

    // 定义本地方法注册函数
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
    return -1;
    }

    // 定义要注册的本地方法
    JNINativeMethod methods[] = {
    {"nativeGetStringFromJNI", "()Ljava/lang/String;", reinterpret_cast<void*>(Java_com_example_ndkdemo_MainActivity_nativeGetStringFromJNI)}
    };

    // 获取类引用
    jclass clazz = env->FindClass("com/example/ndkdemo/MainActivity");
    if (clazz == nullptr) {
    return -1;
    }

    // 注册本地方法
    if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
    return -1;
    }

    return JNI_VERSION_1_6;
    }

    } // extern "C"

    数据类型

    下面是一些常见的C++数据类型和它们在Java中的对应关系,以及它们在JNI动态注册中的数据类型签名(signature):

  • 在JNI动态注册中,需要使用正确的数据类型签名来声明本地方法。例如,如果你要注册一个返回int类型的本地方法,其数据类型签名应为I

    3.IDA Pro使用技巧与Patch

    简介:
    IDA Pro(Interactive Disassembler Professional)是一款功能强大的交互式反汇编和调试工具,广泛应用于软件逆向工程、漏洞分析和二进制代码分析。它支持多种处理器架构和可执行文件格式,包括但不限于x86、ARM、MIPS、PowerPC等。通过使用IDA Pro,可以对程序进行静态分析、动态调试和代码修改等操作。

    快捷键:

  • Patch方式

    1.keypatch插件快速修补
    快捷键:Ctrl+Alt+k
    2.ARM TO Hex
    https://armconverter.com/

    4.ARM基础知识

    常见寻址方式

  • 压栈和出栈指令

  • 跳转指令

  • 算术运算指令

    汇编中也可以进行算术运算, 比如加减乘除,常用的运算指令用法如表 所示:

  • 逻辑运算

    汇编语言的时候也可以使用逻辑运算指令,常用的运算指令用法如表 所示:

  • 偷懒小插件

    WPeChatGPT

api报错问题,可以参考仓库里的解决方法:

pip uninstall urllib3
pip install urllib3==1.25.11

如果 urllib3 版本没错或重装 1.25 版本还是存在 API 访问问题的话,那么请下载最新版本,对插件指定代{过}{滤}理:

  • 将下面三行代码取消注释,然后把代{过}{滤}理地址及端口信息填入 proxies 变量即可:

  • print("WPeChatGPT has appointed the proxy.")
    proxies = {'http': "http://127.0.0.1:7890", 'https': "http://127.0.0.1:7890"}
    openai.proxy = proxies

    四、课后小作业


    1.修改教程demo第五关里的native校验

    五、答疑


    待更新

    Obsidian主题:
    Blue-topaz-example https://github.com/PKM-er/Blue-topaz-example

    推荐书籍:
    王爽老师的《汇编语言(第三版)》
    《IDA Pro权威指南(第二版)》

    六、视频及课件地址


    下方隐藏内容为本帖所有文件或源码下载链接:

游客你好,如果您要查看本帖隐藏链接需要登录才能查看, 请先登录

返回顶部