AttackLab实验

实验内容

官网:http://csapp.cs.cmu.edu/3e/labs.html

“AttackLab”是一个Linux下的可执行C程序,包含了5个阶段(phase1~phase5)的不同内容。程序运行过程中,要求学生能够根据缓冲区的工作方式和程序的反汇编代码来确定攻击字符串长度和字符串中的关键内容。每次成功实现缓冲区溢出攻击时都会有提示相应内容,如果攻击失败则单纯的提示segmentation fault相关信息。

要求攻击字符串的执行不许绕开代码中的validate函数,缓冲区溢出之后对应ret的返回地址可以是以下类型:

  1. 函数touch1、touch2、touch3的首地址;
  2. 自行注入的攻击的首地址;
  3. 在后两个阶段中(ROP攻击),与farm.c的对应的可利用的gadget的起始地址,farm.c对应的机器码已经包含在可执行文件中。可以使用的gadget首地址需处于start_farm和end_farm之间的部分。

注意:前三个阶段使用ctarget作为攻击目标文件,后两个阶段中使用rtarget作为攻击目标文件。

每个阶段考察一个缓冲区溢出方式,难度逐级递增:

  • 阶段1:使用非ROP方式对ctarget进行攻击,调用touch1,且成功输出Touch1!: You called touch1。若不完全满足题目要求,则会提示“Misfire”和FAIL相关字段。
  • 阶段2:使用非ROP方式对ctarget进行攻击,调用touch2,且成功输出Touch2!: You called touch2。攻击过程中需要改写cookie变量的值。若不完全满足题目要求,则会提示“Misfire” 和FAIL相关字段。
  • 阶段3:使用非ROP方式对ctarget进行攻击,调用touch3,且成功输出Touch3!: You called touch3。攻击过程中需要使hexmatch的返回值能够正确引导validate函数。若不完全满足题目要求,则会提示“Misfire” 和FAIL相关字段。
  • 阶段4:使用ROP方式对rtarget进行攻击,调用touch2,且成功输出Touch2!: You called touch2。若不完全满足题目要求,则会提示“Misfire” 和FAIL相关字段。
  • 阶段5:使用ROP方式对rtarget进行攻击,调用touch3,且成功输出Touch3!: You called touch3。若不完全满足题目要求,则会提示“Misfire” 和FAIL相关字段。

ctarget和rtarget都从standard input读入数据,可以以重定向文件的形式进行输入。实验利用getbuf函数中的缓冲区。getbuf函数的结构如下:

unsigned getbuf()
{
    char buf[BUFFER_SIZE];
    Gets(buf);
    return 1;
}

函数中的Gets函数与标准库中的gets函数类似,它从standard input中读取字符(以\n或者EOF结尾)并将它们添加字符串结尾符\0后存入缓冲区中。学生需要根据ctarget和rtarget文件及其反汇编代码来确定缓冲区位置及大小,并想办法构建出攻击字符串。

实验材料

  1. cookie.txt 个人cookie。
  2. ctarget 阶段 1-3 的攻击对象程序。
  3. farm.c 可利用代码片段源码。
  4. hex2raw 将字符串转二进制程序。
  5. rtarget 阶段 4-5 的攻击对象程序。
  6. README.txt 实验介绍文件。

附录

运行时栈

在这里插入图片描述

函数间的转移控制

在这里插入图片描述

机器码表

在这里插入图片描述

注意:D 为 2 字节功能性 nop 指令的编码,对前后文无影响。

实验过程

分析 ctarget 程序

我们需要利用程序中的 getbuf 函数,我们需要查看 ctarget 中的 getbuf 函数。执行 objdump -d ctarget > ctarget.s 查看 ctarget 的汇编代码:
在这里插入图片描述

从中可以看出 getbuf 的栈结构为(地址从大到小):ret 返回地址,0x38 内存空间(sub $0x38,%rsp)。并且 Gets 函数存放数据从 getbuf 的栈底开始(mov %rsp,%rdi)。

阶段1

我们需要利用 getbuf 函数来非正常跳转,所以我们需要利用溢出来修改 ret 返回地址。填充 0x38 个空字节来抵达存储 ret 返回地址的空间,然后填写目标地址来覆盖正常返回的地址。

  1. 查看 touch1 函数的地址
    在这里插入图片描述

  2. 创建输入文件 phase1.txt 并写入 0x38 个空字节和 touch1 函数的地址(小端法)。
    在这里插入图片描述

  3. 使用 hex2raw程序将 phase1.txt 转换成二进制文件 phase1-raw.txt

    执行 ./hex2raw < phase1.txt > phase1-raw.txt

  4. 运行 ctarget 查看结果

    执行./ctarget < phase1-raw.txt -q
    在这里插入图片描述
    PASS 通过。

阶段2

我们需要在阶段1的基础上,修改 cookie 变量的值。

  1. 查看 touch2 函数
    在这里插入图片描述

    从中我们看出 touch2 的地址为 0x4018d5,cookie 变量存储在 %edi 中。我们需要一段代码(即攻击代码)将 %edi 的值修改为我们的 cookie 值。

  2. 查看 cookie.txt 文件中的值

    cookie.txt 文件中的值为 0x77058131

  3. 构造攻击代码

    所以我们需要的攻击代码为

    mov $0x77058131,%edi
    ret
    
  4. 创建 inject.s 文件,将攻击代码写入,并编译。

    执行gcc -c inject.s,得到 inject.o 文件

  5. 反编译 inject.o 文件得到攻击代码的机器码

    执行objdump -d inject.o
    在这里插入图片描述

  6. 寻找攻击代码可存放位置

    通过前文的分析我们知道,我们输入的起始地址是在 getbuf 的栈底,所以我们可以将攻击代码放到 getbuf 的栈底。通过 gdb 定位到 getbuf 函数中的 Gets 行,查看 %rsp 即 getbuf 的栈底。
    在这里插入图片描述
    在这里插入图片描述

    所以第一个 ret 我们需要跳转到 getbuf 的栈底,即 0x55660908 处先执行我们的攻击代码,再通过攻击代码的 ret 跳转到 touch2 中。

  7. 查看 touch2 的地址
    在这里插入图片描述

  8. 创建 phase2.txt 并将攻击代码和两个跳转地址写入
    在这里插入图片描述

  9. 使用 hex2raw 程序将 phase2.txt 转换成二进制文件 phase2-raw.txt

    执行./hex2raw < phase2.txt > phase2-raw.txt

  10. 运行 ctarget 查看结果
    在这里插入图片描述

    PASS 通过

阶段3

本阶段需要通过 touch3 函数。

  1. 查看 touch3 函数
    在这里插入图片描述

    从中我们了解 touch3 函数的地址为 0x4019ec ,且我们需要修改 %rdi 的值使其满足 hexmatch 函数。

  2. 查看 hexmatch 函数
    在这里插入图片描述

    发现 hexmatch 比较了两个字符串,所以我们需要修改 %rdi 的值,使其为我们 cookie 字符串的首地址。

  3. 构造 cookie 字符串

    字符串在机器中是以 0 结尾字符序列,我们采用的是 16 进制,对照 ascii 码表 cookie:0x77058131 的字符序列应该为37 37 30 35 38 31 33 31 00

  4. 寻找 cookie 字符串存放地址

    我们可以放到返回地址 2 后
    在这里插入图片描述

    所以字符串的地址为栈底地址+ 72 字节(即,0x48),根据前文栈底地址为 0x55660908 ,所以字符串地址为 0x55660950 。

  5. 构造攻击代码

    mov $0x55660950,%rdi
    ret
    
  6. 将攻击代码写入 inject.s 并编译
    在这里插入图片描述

    执行gcc -c inject.s得到 inject.o 文件。

  7. 反编译 inject.o 文件,得到攻击代码的机器码

    执行 objdump -d inject.o
    在这里插入图片描述

  8. 攻击代码存放位置同阶段 2 ,在 phase3.txt 文件写入攻击代码,返回地址 1,2,和字符串。
    在这里插入图片描述

  9. 使用 hex2raw 程序将 phase3.txt 转为二进制文件 phase3-raw.txt

    执行./hex2raw < phase3.txt > phase3-raw.txt

  10. 运行 ctarget 查看结果
    在这里插入图片描述

    PASS 通过

分析 rtarget 程序

阶段 4,5 要求我们使用 ROP 的方式来进行攻击,即我们无法自己编写攻击代码来,但我们可以利用程序中带 ret 的片段代码来构造我们需要的攻击代码。

  1. 反编译 rtarget 程序

    执行objdump -d rtarget > rtarget.s

  2. 对照附录机器码表,查找可利用片段
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    编号gadget地址机器码功能
    10x401a8f+0x3 | 0x401a9248 89 c7 c3mov %rax,%rdi
    20x401a8f+0x4 | 0x401a9389 c7 c3mov %eax,%edi
    30x401a9d+0x3 | 0x401aa058 c3pop %rax
    40x401acd48 8d 04 37 c3lea (%rdi,%rsi,1),%rax
    50x401af9+0x1 | 0x401afa89 d6 c3mov %edx,%esi
    60x401b1b+0x3 | 0x401b1e48 89 e0 c3mov %rsp,%rax
    70x401b1b+0x4 | 0x401b1f89 e0 c3mov %esp,%eax
    80x401b3e+0x2 | 0x401b4089 ca (20 d2) c3mov %ecx,%edx
    90x401b0d+0x2 | 0x401b0f89 c1 (08 c9) c3mov %eax,%ecx
    注意:括号内字节码可忽视
    

阶段4

阶段 4 的目标同阶段 2,但我们需要利用 gadget 来修改 %rdi。

  1. 查看可利用的 gadget

    我们可以利用 gadget3 来修改 %rax 的值,再利用 gadget1 将 %rax 赋给 %rdi。

    pop %rax
    mov %rax,%rdi
    ret
    
  2. 查看 touch2 地址
    在这里插入图片描述

  3. 编写 phase4.txt
    在这里插入图片描述

  4. 使用 hex2raw 将 phase4.txt 转二进制文件 phase4-raw.txt

    执行./hex2raw < phase4.txt > phase4-raw.txt

  5. 运行 rtarget 查看结果
    在这里插入图片描述

    PASS 通过

阶段5

阶段 5 同阶段 3 ,但没办法直接计算地址。不过我们可以通过 gadget4 来间接计算地址,通过 gadget 6,1 将 %rdi 改为 %rsp ,通过 gadget 3,9,8,5 修改 %rsi,然后通过 gadget 4 计算地址,再通过 gadget 1 将 %rdi 该为计算后的地址。

  1. 创建 phase5.txt 按顺序将 gadget 地址写入
    在这里插入图片描述

  2. 查看 touch3 地址
    在这里插入图片描述

  3. 将 touch3 地址和偏移量 0x48(即,72 字节)写入 phase5.txt
    在这里插入图片描述

  4. 使用 hex2raw 将 phase5.txt 转二进制文件 phase5-raw.txt

    执行./hex2raw < phase5.txt > phase5-raw.txt

  5. 运行 rtarget 查看结果
    在这里插入图片描述

    PASS 通过

Logo

更多推荐