初探 RE:从入门认知到 BUUCTF 简单题练习
初探 RE:从入门认知到 BUUCTF 简单题练习
这篇文章记录我刚开始接触 CTF 逆向时的学习过程。第一天主要是了解 RE 到底在做什么、常见工具和大致解题流程;第二天开始上手刷一些 BUUCTF 的简单题,在做题里熟悉最基础的分析方法。
目前我的想法也比较明确:先通过题目建立直觉,遇到不会的知识点再回头补,这样学起来更有目标感。
Day1
第一天没有急着做题,主要先梳理方向,尽量对 CTF 逆向建立一个整体认识。
逆向学习框架
我参考了一篇系统性入门文章,感觉下面这句话很适合初学阶段:
在逆向工程领域知识碎片化的今天,强大的自学能力和持之以恒的精神尤为关键。教程可以帮助我们建立方向感,但真正的提升还是要靠持续练习。

CTF 中的逆向工程在做什么
CTF 里的逆向工程,核心目标通常是从题目给出的程序或文件中找出隐藏的 flag。
如果用一个更形象的比喻来理解:
- 出题人像厨师,把“配料”通过一系列加工步骤做成成品。
- 做逆向的人则需要通过观察程序行为、分析代码逻辑、还原处理流程,最终推导出被藏起来的核心信息,也就是
flag。
为什么需要逆向工具
程序从高级语言编译到二进制之后,很多信息都会丢失,比如:
- 注释
- 变量名
- 函数名
- 原始代码结构
因此我们通常没法把程序完整还原成最初的高级语言源码,只能借助逆向工具把它转换成更容易分析的汇编代码或伪代码,再继续往下看逻辑。
我目前主要使用的工具还是 IDA。
常见逆向类型
拿到一道题后,第一步通常是先判断文件类型。最直观的方法是看后缀,但也不能完全相信后缀,因为有些题会故意伪装。
| 逆向类型 | 核心文件格式 | 常见文件后缀 / 类型 | 说明 |
|---|---|---|---|
| Windows 逆向 | PE | .exe、.dll、.sys |
Windows 可执行文件大多是 PE 格式。 |
| Linux 逆向 | ELF | 无固定后缀、.so、.ko |
Linux 下可执行文件通常没有固定后缀。 |
| Android 逆向 | DEX、APK、ELF | .apk、.dex、.so |
APK 本质上是压缩包,内部可能同时包含 Java 层和 Native 层内容。 |
看完这些基础内容之后,我给自己定的路线是:
- 先从 Windows 逆向入手。
- 再逐步过渡到 Linux 逆向。
- 前两部分打一些基础之后,再去接触 Android 逆向。
逆向题常见解题流程

1. 判断文件类型
这一阶段的目标是先确认题目文件的格式,例如 ELF、PE、Python 字节码等,方便后续选择分析工具和环境。
常见方法:
- 使用
file命令识别文件类型。 - 结合题目名称、文件名、附件说明一起判断。
- 注意后缀名可能是伪装的,不能只看表面。
2. 静态分析
静态分析是在不运行程序的情况下,通过 IDA、Ghidra 等工具分析程序逻辑。
这一阶段通常会做这些事情:
- 查字符串
- 看关键函数
- 判断是否存在加壳、花指令、反调试
- 分析是否有明显的加密或校验逻辑
3. 脱壳与修复函数
如果程序有壳,通常要先脱壳。
- 如果是常见
UPX壳,可以直接用upx -d 文件名。 - 如果是魔改壳,就可能需要手动调试,找到
OEP再脱壳。
脱壳之后,有时还要修复函数结构,不然反汇编和伪代码可能都比较混乱,不方便继续分析。
4. 厘清逻辑
把程序主流程捋顺之后,题目大致会落到几种情况里:
- 直接显示
flag
这种题可能能直接从字符串或关键逻辑里看到答案。 - 存在加密逻辑
这时就需要逆向算法,再写脚本还原明文。 - 静态分析受阻
如果变量是运行时生成的,或者代码有动态行为,就需要进一步动态调试。
5. 动态调试
动态调试就是把程序跑起来,用调试器跟踪关键位置,比如:
- 验证函数
- 加密函数
- 字符串处理函数
常用工具包括:
IDA动态调试x64dbggdb
通过断点、单步、查看寄存器和内存,往往能更直观地看到数据是怎么变化的。
6. 写脚本解密
如果题目最终落在某种编码或加密逻辑上,通常就要写脚本。
例如,若程序逻辑是:
1 | input[i] ^ 0x12 == cipher[i] |
那就可以直接逆回来:
1 | flag = bytes([c ^ 0x12 for c in cipher]) |
7. 解出 Flag
最终目标其实很明确,就是通过静态分析、动态调试或者脚本还原,把题目里的 flag 找出来。
看完几篇入门文章之后,我对 RE 已经有了一个比较基础的认识。接下来我更想直接做题,在题目里学习不会的知识点。
参考文章
- CTF中的逆向Re:零基础系统性入门教程-1 - Penetr4t10n - 博客园
- CTF逆向Re:零基础系统性入门教程-2-工具 - Penetr4t10n - 博客园
- CTF逆向Re:零基础系统性入门教程-3-解题流程 - Penetr4t10n - 博客园
Day2
第二天开始正式刷题,顺手练一练最基础的静态分析和简单脚本还原。
UPX 脱壳
先记录一个最常见的脱壳命令:
1 | upx -d "E:\3 pwn题文件\rebuuctf\93c43c5c-3d4d-4d17-a9a1-4ffb65ebb2fb\新年快乐.exe" -o 1.exe |

刷题记录
reverse1

这题的核心就是字符串替换,把 ASCII 码为 111 的字符替换成 48,也就是把 o 替换成 0。


最后得到:
1 | flag{hell0_w0rld} |
reverse2

这题同样是字符串替换,把 ASCII 码为 105 和 114 的字符替换成 49,也就是把 i 和 r 替换成 1。
最终可以得到:
1 | flag{hack1ng_fo1_fun} |
内涵的软件

进去之后就能看到明文内容,我一开始尝试了几种解码方式,但最后发现只需要把 DBAPP 换成 flag 即可。
最终结果:
1 | flag{49d3c93df25caad81232130f3d2ebfad} |
新年快乐

这题是 UPX 壳,先脱壳。


脱壳之后就能直接看到 flag,补上格式即可:
1 | flag{HappyNewYear!} |
xor

这题是经典异或逻辑。题目数据是逐位和前一个字符异或后的结果,因此只要按照逆过程还原,就能恢复原始字符串。
1 | target = [ |
得到:
1 | flag{QianQiuWanDai_YiTongJiangHu} |
reverse3

这题的核心逻辑在主函数 _main_0 中。程序先读取输入,然后调用一个函数对输入进行处理。通过分析可以发现,这个函数内部用到了典型的 Base64 字符表:
1 | ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= |
所以可以判断这一步是在做 Base64 编码。
随后程序把编码结果复制到目标数组,再额外执行一轮变换:
1 | Destination[j] += j; |
也就是让每个字符的 ASCII 值都加上自己的下标。最后程序拿结果去和常量字符串:
1 | e3nifIH9b_C@n@dH |
进行比较。
因此逆向思路就是:
- 先把目标字符串每一位减去对应下标,恢复出原始 Base64 字符串。
- 再对恢复后的 Base64 字符串解码,得到原始输入。
还原脚本如下:
1 | import base64 |
最终得到:
1 | flag{i_l0ve_you} |
小结
这两天的学习下来,我对 RE 的整体流程已经有了一个初步认识:
- 先判断文件类型
- 再做静态分析
- 必要时脱壳、修复函数
- 遇到复杂逻辑就调试或写脚本还原
现在这个阶段,我还是会继续以刷简单题为主,把字符串处理、编码转换、异或、简单加密这些基础题型先打熟。等这些内容更熟练一些之后,再继续往更复杂的 Windows 和 Linux 逆向题里走。