本帖最后由 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文件的主要组成部分包括: 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权威指南(第二版)》 六、视频及课件地址
下方隐藏内容为本帖所有文件或源码下载链接:
游客你好,如果您要查看本帖隐藏链接需要登录才能查看,
请先登录
|