攻击
- 首先使用(gdb)disas doSomething查看doSomething函数的汇编代码
可以看到,这个函数在开始的时候开辟了一个大小为0x28的栈,并在最后释放这个栈。也就是说会获取0x28字节的字符串(即40个字符),最后执行retq指令。
- entrance函数需要一个参数,并且该参数的值为cookie值。从已经学到的知识可以知道,传入的参数是放在%rdi寄存器中。所以现在我们要注入自己的代码将变量存储到%rdi中。指导文档中提到,不要尝试使用jmp或call指令实现跳转,因为很难生成一条完整地带有目标地址的jmp或call指令;而ret指令实现跳转是一种最容易实现的方式。所以现在我们需要使gets函数中的retq指令返回到我们注入的代码首地址,之后再由我们注入的代码,通过retq指令返回到entrance函数。由于现在只可能通过输入的字符串注入代码,注入代码的地址便是输入的字符串首地址。
- 使用disas entrance查看entrance函数的汇编代码
可以得到entrance函数的首地址为0x4018a4,由cmp $0xdf4b73a8,%ebp可以得到cookie的值为0xdf4b73a8
- 获取字符串的首地址,思路是先用break doSomething在doSomething函数处下一个断点,r运行程序执行到该处,用info registers rsp查看寄存器%rsp的值。
得到rsp寄存器的地址为0x55585ff8-0x28=0x55585fd0
- 综上,我们注入的代码应该为
movq $0xdf4b73a8,%rdi
pushq $0x4018a4
retq
先将cookie值(0xdf4b73a8)存入到%rdi寄存器中,用于传参数给entrance函数;再将entrance函数地址(0x4017ec)压栈,使得retq返回到entrance函数。
- 把以上代码存储为test.s,用gcc和objdump把汇编代码翻译为机器码:
gcc -c test.S //得到test.o文件
objdump -d test.o > test.d//得到test.d文件
(这里有一个易错点:拓展名.S中的S一定是大写,否则会爆出如下错误)
得到机器码test.d如下:
- 创建data文件如图:
拆弹
- 首先对exam文件进行反汇编:
- 定位到phase_0函数:
可知答案字符串应该存储在rdi寄存器中,地址为OX4013E3+0XC75=0X402058
得到答案In the sepulchre there by the sea
- 定位到phase_1函数:
由cmp $0x4,%eax可知,字符串数字必须大于4个,
查阅acsii表得知0x38,0x2a对应8, ,中间随便输入三个字符(如zhr,姓名缩写),8zhr
- 定位到phase_2函数:
由lea 0X7C2(%rip),%rbp得到字符串(Eu8[]?<yW:
再定位到recursion函数:
每个字符加一得到:)Fv9^@=zX
程序局部性特征分析
sum_2
虚拟内存分析
exam程序总体的虚拟内存
- 打开终端,运行exam
- 打开另一个终端,ps aux 查看进程,得到exam进程号为2568
- 使用cat指令查看内存进程
(1) exam程序虚拟内存大小为10660KB。(VmSize)
(2) 程序目前已经锁住的物理内存(不能交换到硬盘的物理内存)大小为0KB。(VmLck)
(3) 程序目前正在使用的物理内存大小为764KB(VmRSS)
(4) 程序数据段占用的虚拟内存大小为2224KB(VmData)
(5) 程序在用户态的栈大小为4232KB(VmStk)
(6) 程序所拥有的可执行虚拟内存大小为8KB(VmExe)
(7) 程序被映像到任务的虚拟内存空间的库大小为2136KB(VmLib)
(8) 程序所有的虚拟页表大小为60KB(VmPTE)
elf文件
- 使用readelf的 -S选项查看节头表(注意,S一定是大写)
- 查出4个节的情况,由于虚拟页的pagesize=4KB,即4000字节
得到:
(1)text
实际使用内存空间大小:0xb25字节
内存中的起始地址(虚拟地址):0x401140
需要的虚拟页个数:1
(2)rodata
实际使用内存空间大小:0x2e7字节
内存中的起始地址(虚拟地址):0x402000
需要的虚拟页个数:1
(3)data
实际使用内存空间大小:0x10字节
内存中的起始地址(虚拟地址):0x4040a0
需要的虚拟页个数:1
(4)bss
实际使用内存空间大小:0x200050字节
内存中的起始地址(虚拟地址):0x4040c0
需要的虚拟页个数:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。