ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

逆向工程实验全流程:PE静态分析与APK脱壳实战

逆向工程实验全流程:PE静态分析与APK脱壳实战 简介这份资源是华中科技大学网络空间安全学院逆向工程分析技术实验的完整存档面向正在修读逆向工程、软件安全相关课程的高校学生以及希望动手练习逆向分析基础技能的初学者。包内共57个文件约6.11MB以35张png实验截图、6个xml配置、2份md说明文档为主另含exe、i64、apk、dex、so、arsc、py等逆向分析常见样本与脚本覆盖从静态分析到Android逆向的典型实验场景。资源包含源码与说明书可自行修改方便对照实验步骤复现分析过程。目前已有165人学习下载。读者可借助其中的实验样本、操作截图与说明文档理解逆向分析的基本流程、工具使用与关键思路适合作为课程实验参考或自主练习的素材。1. 逆向工程实验包拆解从静态分析到 APK 脱壳的完整复现路径很多人对逆向工程的第一印象是「拿 IDA 打开 exe 找 flag」但真正上手才发现卡住你的往往不是逆向思路而是环境跑不起来、文件打不开、脚本报错。这份华中科技大学网络空间安全学院的逆向工程分析技术实验存档包含两个实验的完整材料一个 Windows 平台的 PE 逆向实验含.i64数据库、.exe样本、Python 脚本和答案文件一个 Android 平台的 APK 逆向实验含反编译后的classes.dex、AndroidManifest.xml、资源文件和打包 zip。所有源码和说明书都可以自行修改适合课程设计参考、实验复现和自学练手。如果你正在找一份能直接跑通的逆向工程课程实验这份资源省去了从零搭环境的折腾。2. 实验一 PE 逆向从 i64 数据库到 Python 求解脚本2.1 文件构成与工具链选型拿到Experient-1.i64和Experient-1.exe这两个文件第一反应应该是确认工具链。.i64是 IDA Pro 64 位数据库文件意味着原作者用的是 IDA 64 位版本做的静态分析。.exe是待分析的 PE 样本1.py是配套的求解脚本ans.txt是预期输出结果。为什么选 IDA 而不是 Ghidra在这个实验场景下IDA 的.i64数据库直接保存了分析状态——函数命名、注释、交叉引用、结构体定义都在里面。你打开.i64就能看到原作者的分析痕迹相当于拿到了一份带批注的答案。Ghidra 虽然免费但没法直接加载.i64格式你得从.exe重新分析效率差很多。常见做法是先用 IDA 打开.i64看分析结果再用 Python 脚本验证求解逻辑。如果你没有 IDA Pro可以用 IDA Free 打开.exe重新分析但要注意 Free 版不支持 64 位反编译只能看汇编。2.2 用 IDA 加载 i64 数据库并定位关键函数打开 IDAFile → Open选择Experient-1.i64。加载完成后先看左侧函数列表窗口Functions window按地址排序找到main或start入口。如果函数名被 stripped 了就找entry point附近的调用链。定位关键逻辑的常用手法在 Strings windowShiftF12里搜索可疑字符串比如flag、correct、wrong、input等双击字符串跳到引用位置用X键查看交叉引用在反编译窗口F5里看伪代码重点关注条件跳转和循环结构// 典型的逆向题伪代码结构示意 int __cdecl main(int argc, const char **argv, const char **envp) { char input[32]; printf(Enter flag: ); scanf(%s, input); if ( check_flag(input) ) // 关键判断函数 puts(Correct!); else puts(Wrong!); return 0; }上面这段伪代码是逆向题里最常见的结构。核心逻辑在check_flag函数里你需要跟进这个函数看它怎么处理输入、怎么比较、比较的目标值是什么。在 IDA 里双击函数名就能跳进去。参数说明input是用户输入缓冲区check_flag的返回值决定成败。实际实验中check_flag可能做了异或、移位、查表等操作你需要逐步还原。2.3 Python 脚本还原求解逻辑1.py是配套的求解脚本。先看它的结构# 1.py 典型结构根据实验内容推断 # 逆向工程实验一求解脚本 def decode(encoded_bytes): 根据逆向分析结果还原 flag result [] for i, b in enumerate(encoded_bytes): # 这里的操作取决于 IDA 里看到的变换逻辑 # 比如异或、加减、查表等 result.append(b ^ 0x41) # 示例异或密钥 return bytes(result) if __name__ __main__: # 从 exe 中提取的密文数据 cipher [0x32, 0x27, 0x36, 0x20, 0x21] # 示例数据 flag decode(cipher) print(fFlag: {flag.decode()})逻辑说明脚本的核心是把 IDA 里分析出的变换逻辑用 Python 重写一遍。decode函数接收密文字节数组按逆向出的算法逐步还原。参数encoded_bytes是从 exe 的.data段或.rdata段提取的常量数组你需要在 IDA 里找到这些数据的地址和长度。实际操作步骤在 IDA 里找到比较用的常量数组右键 →Export data导出为.py或.txt把导出的数据粘贴到1.py的cipher变量里根据 IDA 伪代码修改decode函数里的变换逻辑运行python 1.py对比ans.txt验证结果注意如果1.py里的逻辑和 IDA 里看到的不一致以 IDA 为准。脚本可能是半成品需要你自己补全。3. 实验二 APK 逆向从反编译资源到 dex 分析3.1 APK 解包后的目录结构与关键文件实验二的目录结构很清晰AliCrackme/ ├── AndroidManifest.xml # 应用清单声明权限、组件、入口 Activity ├── classes.dex # Dalvik 字节码核心逻辑所在 ├── resources.arsc # 编译后的资源索引表 ├── res/ # 资源文件目录布局、字符串、图片等 ├── META-INF/ # 签名信息 ├── lib/ # native 库如有 └── AliCrackme.zip # 原始 APK 打包AndroidManifest.xml是入口先看它确定MainActivity是哪个类。classes.dex是重头戏所有 Java/Kotlin 代码编译后都在这里。resources.arsc和res/目录负责 UI 和字符串资源。常见做法是先用apktool反编译得到 smali 代码再用jadx或dex2jar jd-gui得到 Java 源码。两种方式各有优劣——smali 更接近底层Java 源码可读性更好但可能丢失细节。3.2 用 jadx 反编译 classes.dex 定位校验逻辑jadx 是目前最顺手的 dex 反编译工具支持命令行和 GUI。命令行方式# 用 jadx 反编译 APK jadx -d output_dir AliCrackme.apk # 或者只反编译 dex jadx -d output_dir classes.dex反编译完成后在output_dir/sources/下找到MainActivity.java。典型的 Crackme 校验逻辑长这样// MainActivity.java 典型校验逻辑示意 public class MainActivity extends Activity { public void onCheckClick(View v) { String input editText.getText().toString(); if (checkPassword(input)) { Toast.makeText(this, Correct!, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, Wrong!, Toast.LENGTH_SHORT).show(); } } private boolean checkPassword(String input) { // 核心校验逻辑 // 可能是字符串比较、哈希校验、native 调用等 return input.equals(buildExpectedString()); } }逻辑说明onCheckClick是按钮点击回调checkPassword是核心校验函数。你需要跟进checkPassword看它怎么构造期望值。如果它调用了 native 方法native boolean checkPassword(String)那就需要分析lib/下的.so文件。参数说明input是用户输入的密码字符串buildExpectedString()可能做了拼接、异或、Base64 解码等操作。jadx 的反编译结果通常能直接看懂遇到混淆的变量名如a、b、c就结合上下文推断。3.3 资源文件与 AndroidManifest 的辅助定位有时候校验逻辑不在 dex 里而是藏在资源文件中。比如字符串比较的目标值可能定义在res/values/strings.xml里。用apktool反编译后可以直接看# 用 apktool 反编译 APK apktool d AliCrackme.apk -o AliCrackme_decoded # 查看 strings.xml cat AliCrackme_decoded/res/values/strings.xmlAndroidManifest.xml里重点关注package属性应用包名application标签下的android:name自定义 Application 类activity标签下的android:name入口 Activitymeta-data标签可能藏有密钥或配置提示如果AndroidManifest.xml是二进制格式直接解压 APK 得到的就是二进制用apktool或AXMLPrinter2转成可读文本。4. 避坑与常见问题排查4.1 IDA 打开 i64 报版本不兼容现象双击.i64文件IDA 提示「database version mismatch」或直接闪退。原因.i64数据库和 IDA 版本强绑定。原作者用的 IDA 版本和你本地的不一致高版本数据库无法在低版本 IDA 中打开。解决换用同版本或更高版本的 IDA。如果实在没有就用 IDA 打开.exe重新分析虽然丢失了原作者的注释但核心逻辑还在。另一个办法是用 IDA 的File → Produce file → Dump database to IDC导出为 IDC 脚本但前提是你能打开。4.2 Python 脚本运行报编码错误现象python 1.py报UnicodeDecodeError或SyntaxError: Non-UTF-8 code。原因脚本里可能包含中文注释而文件编码不是 UTF-8。Windows 下默认用 GBK 编码保存跨平台运行时就会出问题。解决用 VS Code 或 Notepad 把1.py转成 UTF-8 编码。或者在脚本开头加# -*- coding: utf-8 -*-。如果报的是SyntaxError检查 Python 版本——Python 2 和 Python 3 的 print 语法不同这份实验大概率是 Python 3。4.3 jadx 反编译后代码不全现象jadx 打开 APK 后某些类显示「// decompilation failed」或只有空壳。原因代码被混淆了或者用了 jadx 不支持的字节码特性。也可能是 APK 做了加固dex 被加密了。解决换用dex2jar jd-gui组合试试。如果还是不行就看 smali 代码用apktool d反编译。smali 虽然可读性差但不会丢失逻辑。遇到加固的 APK需要先脱壳——常见工具是 Frida 或 Xposed但这超出了本实验的范围。4.4 APK 反编译后资源文件乱码现象res/values/strings.xml打开全是乱码或者resources.arsc无法解析。原因直接解压 APK 得到的resources.arsc是二进制格式不是文本。AndroidManifest.xml同理。解决用apktool反编译它会自动把二进制 XML 转成可读文本。如果apktool报错试试apktool --force或更新到最新版本。另一个工具是AXMLPrinter2专门转二进制 XML。4.5 实验答案对不上现象按照脚本跑出来的结果和ans.txt不一致。原因可能是脚本里的常量数据没更新或者 IDA 里看到的逻辑和脚本实现有偏差。也可能是ans.txt本身就是错的原作者留的坑。解决以 IDA 和 jadx 里看到的实际逻辑为准逐步调试。在 Python 脚本里加 print 输出中间结果对比 IDA 里的运行时数据。如果实在对不上检查样本文件是否完整——.exe可能被截断.dex可能被修改过。5. 进阶技巧用 Frida 动态验证静态分析结果静态分析再仔细也可能漏掉运行时才暴露的逻辑。比如 APK 里的校验函数可能依赖运行时生成的密钥或者 PE 样本在特定条件下才触发关键分支。这时候就需要动态分析来交叉验证。Frida 是目前最顺手的动态插桩工具。以 APK 实验为例假设你在 jadx 里看到checkPassword函数想确认它的实际输入输出// frida hook checkPassword 函数 Java.perform(function() { var MainActivity Java.use(com.example.alicrackme.MainActivity); MainActivity.checkPassword.implementation function(input) { console.log([*] checkPassword called); console.log([*] input: input); var result this.checkPassword(input); // 调用原函数 console.log([*] result: result); return result; }; });逻辑说明Java.perform是 Frida 的入口确保在 Java 虚拟机加载完成后执行。Java.use加载目标类implementation替换原函数。在替换函数里你可以打印参数、修改返回值、甚至完全重写逻辑。参数说明com.example.alicrackme.MainActivity需要替换成实际的包名和类名从AndroidManifest.xml里查。input是原函数的参数this.checkPassword(input)调用原始实现避免破坏原有逻辑。运行方式# 前提设备已 rootfrida-server 已运行 frida -U -f com.example.alicrackme -l hook.js --no-pause-U表示 USB 设备-f表示启动应用-l加载脚本--no-pause表示不暂停等待。对于 PE 实验可以用 x64dbg 做动态调试。在 IDA 里找到关键地址在 x64dbg 里下断点运行样本观察寄存器和内存变化。静态分析和动态调试结合基本能覆盖所有情况。注意Frida 需要 root 环境如果没有真机可以用模拟器如 Genymotion 或 Android Studio 自带的 AVD。模拟器要选 x86 架构frida-server 也要对应架构版本。从那以后我每次做逆向实验都强制走一遍「静态定位 → 脚本还原 → 动态验证」的流程。静态分析给你全局视野脚本还原验证逻辑理解动态调试兜底运行时行为。三管齐下基本不会翻车。希望帮到你。本文还有配套的精品资源点击获取
返回列表