对书籍《0day软件漏洞精要分析-第二版》中的样本进行了调试分析
很喜欢书中的一句话:
所有漂亮的 exploits 背后都隐藏着无数个对着寄存器发呆的不眠之夜
《0day2》实战笔记:part1 - 基础知识
Lab
记录调试代码时碰到的不懂或有趣、顿悟的地方
Ollydbg,首先调试到需要进行标准输入的地方
在调用scanf
地方,从标准输入流中读入的数据写在栈上的位置
写入后然后调用crack_me.00401000
,进入后查看到字符串,我们很直接的猜测可能就是密码
调试的时候发现,执行了一个循环的过程,然后进行字符的比较
一个思路就是直接输入1234567
通关
第二个思路就是打patch
,修改汇编语句为jne short 0040107F
正确的patch应该是使用010editor类工具修改PE文件中的二进制数据,此处不再演示了。
《0day2》实战笔记:part2 - 栈溢出原理与实践
Lab
IDA反汇编,存在栈溢出
攻击思路有:
- 使用栈溢出覆盖栈上的数据,完成变量覆盖
- 使用栈溢出劫持EIP,改变程序的执行流
- shellcode注入
变量覆盖
IDA静态分析的时候发现了
最终密码校验的v3标志位和strcpy中的v3在栈上的关系如下:
查看源码,v2完全可控
只需要偏移8个字节,就可以覆盖,输入类似aaaaaaaa
即可符合验证
劫持eip
既然可以覆盖变量,何不覆盖掉返回地址
主要看大端小端序,可以动态调试的时候查看
报错是因为覆盖掉上一个栈帧地址
栈上的shellcode注入
我们搓出shellcode如下
1 | xor ebx, ebx |
然后使用pwntools的asm模块,将汇编转字节码,当然也可以使用AI工具帮忙转,然后就是查看栈溢出点
偏移0x30+0x4,然后再填入4字节的跳转到shellcode地址
动态调试查看写入点的基址,一个trick是可以写一些显眼的脏数据查看
所以写入buffer的数据为如下,0x90
对应着nop
,注意小端
弹窗成功
《0day2》实战笔记:part3 - 开发shellcode的艺术
jmp esp技术
主要是如果将shellcode
注入到函数的栈空间中,可能由于动态链接库的装载导致shellcode
的定位出现问题
做法就是(如图所示),将shellcode
写入到ret
指令之前的栈里(可以先填充一段nop
指令提高利用的成功率),然后在ret
位置覆盖为指令jmp esp
的地址作为跳板(这个可以通过爆搜内存进行查找)
内存搜索
内存搜索的相关代码解析:
思路就是LoadLibrary将DLL映射到当前进程的内存空间后,进行爆搜,粗暴而有效
1 |
|
这里笔者其实有个疑惑,既然将DLL加载到主进程的内存空间中,那么爆搜到的内存地址不应该是主进程中的内存地址吗?
经过调试,LoadLibrary返回了一个句柄(Windows上的句柄的概念类似于Linux中的文件描述符),通过句柄,我们可以访问动态链接库中的资源。
编写shellcode
之后就是exploit
在这之前,需要查看:
kernel32.dll
中的exit
:0x7C81CB12
- MessageBox的函数地址:
0x77D507EA
源码:
1 |
|
使用OD调试时转储shellcode
注入
此部分演示使用上个lab的shellcode
黑色高亮部分是jmp esp
,然后用nop填充,再存shellcode,最后nop填充
抬高esp保护shellcode的完整性
多搞点nop?
《0day2》实战笔记:part5 - 堆溢出利用
微软操作系统堆管理机制发展大致分为三个阶段:
- Windows 2000 ~ Windows XP SP1 堆管理系统没有丝毫考虑安全
- Windows XP2 ~ Windows 2003 ,加入安全因素,如修改块首格式并加入cookie,双向链表节点在删除时会做指针验证
- Windows Vista ~ Windows 7 是堆管理算法的里程碑
书中主要涉及Windows 2000 ~ Windows XP SP1平台的堆管理策略
堆的结构
程序员申请内存返回的指针指向的是块身
块首对程序员是透明的,堆表中只索引所有空闲堆块
两种堆表:
- 空闲双向链表,Freelist(空表)
块首包含两个指针,用于组织双向链表
free[1]
标识堆中所有8字节空闲堆块,然后从1
到127
呈现按8字节大小进行递增
free[0]
存储的是所有1024B < x < 512KB
的空闲堆块,按大小升序
- 快速单向链表,Lookaside(快表)