dbg工具使用+首次脱壳记录
dbg
今天第一次手脱了壳(找不到工具,被迫脱壳),是 ASpack,搜了一下是压缩壳.
先介绍一下 dbg 工具的功能吧,真得好用,真的.
x64dbg 使用技巧与实用插件合集 - 吾爱破解 - 52pojie.cn
这篇就够了,然后我再贴上我手脱壳题目别人的 wp 吧,题目是攻防世界难度 3 的 Windows_Reverse2
有点烧脑的 ASPACK
EugeneL1 发布于 2022-08-25
首先拿到程序,将程序拖到 exeinfo 中,发现是一个利用 Aspack 加壳后的程序。
因为手里没有现成的 Aspack 脱壳工具,所以利用 OllDBG 对程序进行手动脱壳,Aspack 壳脱壳的过程很固定,下面将演示对本题目中程序的 Aspack 壳的脱壳过程。
【ASPACK 脱壳】
工具:吾爱破解 OllyDBG
过程: 1.首先使用 OllyDBG 打开题目中给出的可执行文件,首先可以看到程序的基址为0x296000
(记住这个基址,后面会用到),同时程序停止在0x296001
处,指令为pushad
,这是 Aspack 壳的一个显著特征。
2.按 F8 步过,此时程序停留在一个
call
指令,此时右键 ESP 寄存器,在该地址添加硬件断点,接着按 F9 执行到这个地址,此时程序已经完成了脱壳。
3.此时程序执行到一条
JNZ
指令,按两次 F8 步过直到执行完 push 指令,到达程序真正的 OEP。
4.此时到达程序真正的 OEP,在第一次分析时,需要右键重新分析代码。
5.此时,在程序停留的
call
指令处右键,利用 Ollydump 脱壳。
6.此时可以看到程序默认的起始地址为 0x400000,但是程序当前实际运行的基址为前面记录的 0x290000,因此要修改程序的起始地址,否则不能够 dump 内存。同时,要将程序 OEP 修改为脱壳后的程序实际 OEP,就是刚刚程序
JMP
之后的第一条call
指令地址偏移,为 0x170F。
修改后:
7.此时点击脱壳,就完成了对程序的脱壳。
【程序分析】
此时已经完成了脱壳的部分,正式进入到对程序的分析。利用 IDA 打开脱壳之后的程序,搜索字符串发现了关键字符串DDCTF{reverse+}
,到其交叉引用的位置,按 F5 进行反汇编,查看程序逻辑。图中标黄的是关键函数(函数名有自己修改)。
首先查看函数 sub_6211F0(),首先可以猜测它是对输入进行了判断,函数的逻辑也确实证实了我的猜测,if
中的判断逻辑限制输入的长度必须大于 0 并且是偶数,while 循环中的if
判断限定输入必须是 09,AF,这很明显,输入必须在 16 进制的表示范围之内。
回到上层,查看 calc 函数,这个函数对用户输入进行了处理,并最终将结果与reverse+
进行比较。可以看到,第一个 do/while 循环是将每两位用户输入处理成其对应的 16 进制数值,例如用户输入AD
,则结果等于('A'-55) * 0x10 + 'D'-55 = 0xAD
,因为 A 的 ASCII 为0x65
,因此 A 减去 55 等于 10,相当于是将其变为 16 进制中 A 的值,这是需要思考和理解的一点。
经过处理之后,用户输入存储在一个新的字符串中。接着看 return 中的函数,根据其特征可以看出是 Base64 编码的过程。
一个更明显的特征,函数对可能存在的最后两位空位填充时用了=
,这是 base64 的典型特征。
【编写注册机】
现在我们已经基本清楚了程序的逻辑,首先接收用户输入,并将其处理中其在 16 进制中的实际大小,之后对存储处理之后数据的字符串进行 base64 编码,将编码之后的字符串与reverse+
进行比较。
我们要做的就是将reverse+
进行 base64 解码,将其解码后的十六进制数值变成符合 09,AF 范围的字符串。
import base64
s = 'reverse+'
s = base64.b64decode(s)
print(s)
结果:
flag = flag{ADEBDEAEC7BE}
为什么要补上 IAT
关于导入表,
而为了开发更方便和更人性化,编译器提供了这个静态导入函数的功能,
也就是说你在编程的时候不需要 LoadLibrary(),不必每次调用一个函数都 GetProcAddress(),
你只需要在源代码中写函数名和参数即可,编译器会将你使用的<函数名>和函数所在的<DLL 文件名>
两个信息填写到输入表里,当程序启动运行时由操作系统根据这两个信息给程序加载
所需的 DLL,并将所需要的函数地址写入 IAT。
IAT 是指 PE 导入地址表,每个 IAT 就对应了一个 DLL 文件导入函数的地址表,
你的程序里调用的地址不是直接调用 DLL 里函数的地址,因为你不知道地址是多少,
而是直接调用了 IAT 里的地址。程序启动时操作系统加载所需的 DLL 并填充导入名称表 INT 对应的
函数地址到地址表 IAT 对应 PIMAGE_THUNK_DATA 结构里,然后程序就可以正常调用 IAT 中这些函数地址了。
壳的工作原理,
某些加壳程序加壳后会修改了原来导入目录表的位置为壳的导入表,
这样默认的导入表指向壳部分的导入表,你就看不到原来的导入表的内容了。
程序启动后,操作系统为壳的导入表加载,
在壳代码运行完成之后,壳代码会跳到原程序的入口点 OEP,壳模拟操作系统填充
原来导入表 IAT,这样保证代码段能正常调用函数。
一般壳的工作原理也就是这样了,随着现在加壳加密技术的进步,不是所有加壳软件都会这样。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)