当前位置: 首页 > news >正文

BugkuCTF 逆向实战:从PyInstaller解包到Android APK分析

1. PyInstaller解包实战:从EXE到Pyc逆向分析

1.1 识别PyInstaller打包特征

遇到CTF逆向题目的可执行文件时,第一步永远是文件识别。用file命令查看文件类型时,如果显示PE32+ executable (GUI) x86-64,再用Detect It Easy工具分析,通常会看到PyInstaller的标识。这里有个快速判断技巧:用十六进制编辑器查看文件末尾,PyInstaller打包的文件往往会有MEI标记和明显的Python版本信息。

我遇到过不少题目会在资源段隐藏关键信息。比如某次比赛中,用Resource Hacker查看资源时发现PYTHONSCRIPT段里藏有加密的Python代码。这时候需要先用pyinstxtractor解包,再用uncompyle6反编译pyc文件。

1.2 使用pyinstxtractor拆解

GitHub上的pyinstxtractor.py是必备工具,实测Python 3.8+环境运行最稳定。解包命令很简单:

python pyinstxtractor.py target.exe

解包后会生成target.exe_extracted目录,里面有几个关键文件:

  • PYZ-00.pyz:压缩的Python字节码
  • struct文件:包含Python版本信息
  • 主脚本的pyc文件(通常没有文件名)

这里有个坑点:解包出来的pyc文件可能缺少魔数和时间戳。我常用的修复方法是:

import struct with open('fixed.pyc', 'wb') as f: f.write(b'\x42\x0D\x0D\x0A') # 魔数 f.write(b'\x00'*4) # 空时间戳 f.write(open('original').read()[8:]) # 跳过原文件头

1.3 反编译Pyc文件

拿到修复后的pyc文件后,推荐使用uncompyle6

uncompyle6 -o . fixed.pyc

如果遇到反编译失败,可能是代码被混淆了。这时候需要:

  1. pycdc工具尝试反编译
  2. 直接分析字节码:
python -m dis fixed.pyc

去年遇到一道题,出题人用marshal模块二次加密了代码。解决方法是从import marshal附近入手,找到加载代码的loads()调用点,dump出解密后的code对象。

2. Android APK逆向核心流程

2.1 基础工具链配置

Android逆向需要一套工具链:

  • apktool:解包APK文件
  • dex2jar:将dex转换为jar
  • jd-gui/jadx:查看Java源码
  • frida:动态调试

建议配置alias提高效率:

alias apkdecode='apktool d -f -o decoded' alias dex2jar='d2j-dex2jar.sh -f -o output.jar'

2.2 多层DEX处理技巧

现在的APK经常采用多DEX架构,遇到这种情况:

  1. 解压APK后会有多个classes.dex
  2. d2j-dex2jar逐个转换:
for i in $(seq 2 5); do d2j-dex2jar.sh classes$i.dex -o jar$i.jar done

某次比赛遇到DEX被分割存储的情况,需要先拼接文件:

with open('merged.dex', 'wb') as f: for part in sorted(glob('split_*.dex')): f.write(open(part, 'rb').read())

2.3 关键代码定位方法

在jd-gui中快速定位关键代码:

  1. 搜索checkverify等关键词
  2. 查看MainActivityonCreate方法
  3. 注意SharedPreferences读写操作
  4. 查找getString(R.string.xxx)资源引用

有个实用技巧是过滤onClick事件:

find . -name "*.smali" | xargs grep "Landroid/view/View\$OnClickListener"

最近一道题把关键逻辑藏在assets的so库里,需要用IDA分析System.loadLibrary加载的native代码。

3. CTF逆向高频考点解析

3.1 密码算法识别与逆向

常见加密模式识别特征:

  • TEA:0x9E3779B9魔数、delta变量
  • AES:S盒查找、轮密钥扩展
  • RC4:256字节的S盒初始化
  • Base64变种:自定义码表

遇到加密算法时,我通常会:

  1. 用PEiD的Krypto ANALyzer插件识别
  2. 在IDA中查找初始化向量(IV)
  3. 通过交叉引用定位密钥生成逻辑

某次比赛遇到魔改的XXTEA算法,关键点在:

for (i = 0; i < 32; i++) { v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); sum += 0x61C88647; // 特征值 v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); }

3.2 动态调试技巧

Android动态调试方案:

  1. Frida:适合hook Java层
Interceptor.attach(Module.findExportByName(null, "strcmp"), { onEnter: function(args) { console.log("strcmp:", args[0].readCString(), args[1].readCString()); } });
  1. IDA Pro:调试so文件时需要android_server

Windows平台常用:

  • x64dbg:条件断点设置
  • Cheat Engine:内存扫描

有个实用技巧是在JNI_OnLoad下断点,可以捕获so加载初期的关键操作。

4. 实战案例:Bugku逆向题解

4.1 Easy_Re题解

这道题用IDA打开后,直接搜索字符串能看到:

.rdata:00413E34 xmmword_413E34 xmmword 6C665F4433544354h

将十六进制转为ASCII就是DUTCTF的开头。

关键验证逻辑在:

if ( !strncmp(Destination, Str2, v5) ) puts("right flag!");

动态调试时在strncmp下断点,可以dump出Str2的值。

4.2 Timer题解

这道Android题需要分析MainActivity

public void run() { if (MainActivity.this.beg - MainActivity.this.now <= 0) { tv2.setText("alictf{" + MainActivity.this.stringFromJNI2(k) + "}"); } }

通过修改smali代码绕过时间检测:

const v0, 0x7FFFFFFF # 替换原beg值

4.3 非标准Base64处理

遇到自定义码表的Base64,可以用这个模板解码:

import base64 custom_table = 'AaBbCcDdEeFfGgHh...321+/' std_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ...+/' s = 'mTyqm7wjODkrNLcWl0eqO8K8gc1BPk1GNLgUpI==' trans = str.maketrans(custom_table, std_table) print(base64.b64decode(s.translate(trans)))

逆向工程就像侦探破案,需要耐心和技巧的结合。每次遇到新保护机制,都是学习的机会。建议多分析真实样本,积累特征库,这比单纯刷题提升更快。

http://www.jsqmd.com/news/1197702/

相关文章:

  • 上拉电阻设计全解析:从基础原理到6大典型应用场景
  • 救命!2026年AI论文工具排行榜,写论文卡壳的学生党直接抄作业
  • C语言文件大小获取:fseek+ftell、stat、fstat三种方法详解与工程实践
  • 从C1到C8:科学音高记谱法如何统一全球音乐语言?
  • VS Code + Claude Code + DeepSeek V4 API 智能编程工作流深度实践
  • 一个资深会计科莱特SAP培训后的薪资翻倍之路
  • 3D 魔方模拟器使用three.js开发:技术实现详解
  • n8n部署方式选型指南:npx、Docker单容器与Compose生产实践
  • 企业AI编程工具私有化部署实战指南:模型本地化、协议适配与合规落地
  • DeepSeek-V4推理操作系统:TUI+RLM+上下文编排实战指南
  • Part 2:WebGPU基本对象及其创建
  • Navisworks 2026安装深度指南:Vulkan渲染、Model Service与.NET 6.0.32配置
  • Android系统启动流程深度解析:从Zygote到Launcher的进程孵化与调度
  • 电竞直播反应视频创作:从李相浩经典表情看真实情感表达
  • 2026年校招面试优缺点安全回答框架:AI追问训练帮你避开3大翻车陷阱——STAR-C法则实战打磨
  • SCTP网络编程实战:利用多流特性构建高性能服务器
  • Cookie跨域限制
  • 【成员变量和局部变量类错误】
  • VS Code Remote 微信小程序远程开发实战指南
  • 从微分方程到传递函数:首1法与尾1法的形式转换与工程意义
  • C/C++多级指针详解:从内存模型到动态数组与函数参数传递
  • 常见MQ(消息队列),以及它们的区别
  • 开关电源MOSFET选型与热设计实战指南
  • 深研生物怎么样?三个维度拆解CGT上游技术实力
  • ABAP 没有 TemplateRef,但四类 SAP 技术可以承担相近职责
  • 【《CentOS7/7.9 ls 命令超详细实操教程|零基础运维必备》】
  • OpenCLI:让已登录的Chrome浏览器变成可编程RPC服务端
  • 中国汽车月度销量预测与市场趋势分析
  • C++多线程编程实战指南:从基础同步到高级并发工具
  • 基于Multisim的RC有源滤波器设计与仿真实践指南