飞道的博客

深入理解计算机系统|Attack Lab

214人阅读  评论(0)

Code Injection

Phase_1

任务
执行完 getbuf 函数之后不跳转到 test 函数,而是执行 touch1 函数。

分析流程

  • 首先得到getbuf的汇编代码

    得知getbuf的缓冲区大小为0x28(即40)。为了使它跳转到touch1,通过缓冲区溢出把栈帧上面的返回地址改掉;填充40字节内容+touch1地址即可。

  • 查看touch1的汇编代码

    得到touch1地址为0x4017c0。

  • 小端排列逆向填充,制作相应的字符文件attack1.txt

  • 执行,得

    成功

Phase_2

任务
插入一段代码,使得getbuf()函数返回时,执行touch2(),而不是返回test()

分析流程

  • 分析touch2可知,我们需要把cookie作为参数传入touch2中。

  • 要做的事情有

    • 注入代码,修改%rdi使它等于cookie(0x59b997fa)。
    • 改变getbuf的返回地址,使其跳转到我们输入的代码块。
    • 使注入的代码执行结束后跳转到touch2。
  • 首先观察touch2的汇编代码

    得到其地址为0x4017ec。

  • 接下来编写注入代码,制作相应文件injection2.s

  • 由于retq函数是从栈顶弹出一个值进行跳转,所以除了要改变%rdi的值,还要我们要压入touch2的首地址。具体代码如下

    将其编译得到

  • 我们的代码从栈顶注入,所以还需要得到栈顶指针

  • 在栈的开始位置为注入代码的指令序列,然后填充满至40个字节,在接下来的8个字节,也就是原来的返回地址,填充成注入代码的起始地址,也就是%rsp的地址。为了方便理解,画一下注入后的栈图

  • 制作相应的字符文件attack2.txt

  • 执行,得

    成功

Phase_3

任务
在getbuf()函数返回的时候,执行touch3()而不是返回test()。从touch3()可以看出我们需要注入新的代码,让touch3()以为它接收到的参数是自己的cookie的字符串表示。

分析流程

  • 首先分析hexmatch得源代码

查阅资料得
sprintf指的是字符串格式化命令,函数声明为 int sprintf(char *string, char *format [,argument,…]);,主要功能是把格式化的数据写入某个字符串中,即发送格式化输出到 string 所指向的字符串。sprintf 是个变参函数。使用sprintf 对于写入buffer的字符数是没有限制的,这就存在了buffer溢出的可能性。

  • 所以我们需要传入的字符串为“59b997fa”,通过查阅ASCII表,将其转为16进制序列“35 39 62 39 39 37 66 61 00”。我们要将这个序列赋值给%rdi作为参数传入函数,但是字符串类型无法直接传递,我们要把它存进内存

  • 在hexmatch中,由于有

    考虑到getbuf栈帧大小,所以把字符串放进getbuf栈帧并不安全。所以考虑将字符串放在test栈帧。剩下的工作就和任务二类似

  • 利用gdb得到test的栈顶地址

    可知是0x5561dca8

  • 再查看touch3的开始地址

    可知是0x4018fa

  • 编写注入代码,制作相应文件injection3.s

  • 将其编译得到

  • 画出栈图

  • 制作相应的字符文件attack3.txt

  • 执行,得

    成功

R O P


首先将farm.c编译,得到一个gadget farm

Phase_4

  • 任务和Phase_2相同,但是要使用rop方式进行攻击
  • 考虑的攻击方式为:通过缓冲区溢出漏洞将cookie写入栈,然后把它pop到某寄存器,再把它move到%rdi中
  • 为方便理解,画出栈图
  • 由此我们需要的汇编代码为
popq %rax
movq %rax, %rdi
  • 查表可知指令字节分别为:58,48 89 c7

  • 回到farm中查找,得到


    得到两条指令的地址:0x17,0x0e。

  • 制作相应的字符文件attack4.txt

  • 执行,得

    失败

  • 应该是farm里的指令地址出了问题。查询资料得知是没有把farm编译为可执行代码。

  • 重新利用gdb查找指令地址

    得到指令地址分别为:0x4019ab,0x4019a2

  • 编写字符文件

  • 重新执行

    成功

Phase_5

  • 任务和Phase_3相同,但是要使用rop方式进行攻击。

  • 但是由于每一次栈的位置是随机的,不能再像之前直接通过地址来索引字符串的起始地址,考虑先动态获取每次栈顶指针再加上偏移量来索引字符串的地址,再把地址传送到%rdi,调用touch3。

  • 需要做的事情有

    • 获取%rsp的地址。
    • 获取字符偏移量。
    • 计算得到字符串首地址再传送到%rdi。
    • 调用touch3。
  • 查找farm,得到

    • movq %rsp,%rax 的指令字节为48 89 e0,地址为0x401a06

    • movq %rax, %rdi的指令字节为48 89 c7,地址为0x4019a2

    • popq %rax的指令字节为58,地址为0x4019cc

    • movl %eax, %edx的指令字节为89 c2,地址为0x4019dd

    • movl %edx, %ecx的指令字节为89 d1,地址为0x401a70

    • movl %ecx, %esi的指令字节为89 ce,地址为0x401a13

    • lea (%rdi,%rsi,1),%rax的地址为0x4019d6

    • movq %rax, %rdi的指令字节为48 89 c7,地址为0x4019a2

  • 至此,字符串的地址已经被放进了%rdi中,画个栈图理清一下思路

    可知偏移量为8*9=72,即为0x48

  • 制作相应的字符文件attack5.txt

  • 执行,得

    成功

小结

在实验过程中对于栈有了更加深刻的理解,同时认识到了缓冲区溢出的危害。对于gcc和objdump的使用更加熟练


转载:https://blog.csdn.net/qq_45401156/article/details/115774060
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场