请你轻轻留下来
让梦卷走这尘埃
香飘在书厢之外
奏响美丽的天籁
——奢香夫人
完整代码见:CSAPP/attack at main · SnowLegend-star/CSAPP (github.com)
Lab3主要是考察我们对栈结果的理解,对汇编代码的阅读考察并没有Lab2那么深。
Level 01
这个lab是让我们修改getbuf()函数的返回地址,使之最后会返回到touch1执行,而不是正常返回到test()里面。我们现在在0x4017ac除打个断点,这时getbuf的栈帧空间已经被分配好了,我们查看rsp的值发现是0x5561dc78,这时把这个数据加上40就可以得到在执行getbuf()这个函数之前rsp的位置,即0x5561dca8。通过查看0x5561dca0的内容,我们发现是“420082210 =0x40197616 ”,即这个地址里面存的是将会返回到的test()内部的地址。和我们预期的一致。
我们又在0x4017b4处打个断点,看看输入了正确的字符串之后0x5561dca0里面藏着什么。开始我犯了个错误,直接把“Hex1.txt”文件里面的内容输入了,结果栈的内容变得十分奇怪,仔细思考后才发现应该先拿“hex2raw”这个函数把十六进制数全部转换成字符串,同时这个函数会去掉“空格、换行符”等。输入了正确的字符串格式后,再次查看栈帧的内容。
= ,我们发现输入的溢出部分果然跑到了这个位置,这样就可以顺利通过这题。
这里可能会有一个疑问,此时0x5561dca0里面存着的不就只有一个地址吗,一个地址怎么会自己执行呢?
其实这个地址表示着的是调用函数下一条指令的地址,被调用函数执行ret可以看成是配合这个地址一起使用的,即跳转到这个地址。
程序栈和栈帧的关联:对于同一个源代码文件(.c文件)中的函数,它们的栈帧通常都会存储在同一个调用栈中。这是因为所有这些函数共享相同的全局栈,栈是在程序运行时分配的内存区域,用于存储函数的栈帧和控制信息。
Level 02
这个lab要求我们执行完getbuf返回到touch2继续执行,同时传递一个参数cookie到touch2里面。众所周知,这汇编语言的参数传递里面第一个参数是用edi传递的,我们让getbuf返回到touch2继续执行就可以认为是touch2调用了getbuf这个函数。所以我们先把cookie赋值给edi,然后把touch2的首地址0x4017ec进行push推入栈中,再跟ret返回到这个地址。
现在问题来了,我们要怎么执行上面这段汇编代码呢,首先得跳转到这块汇编代码才能执行吧,所以溢出区得填入这段汇编代码的首地址,即0x5561dca0,这样就可以顺利通过了。
Level 03
这次的要求看上去和touch2差不多,不过它要求的是传递指向cookie的指针到touch3里面。所以这个lab需要完成的就是两大点:
- 把cookie的地址赋给edi传给touch3,注意这个地址不能放在getbuf开辟的缓冲区里,否则可能被hexmatch和strncmp覆盖。
- 跳转到存放汇编代码的首地址
- 跳转到touch3
为了好好保存cookie的内容,我们得把cookie存在一个不会被覆盖的区域,把这个区域放在rsp开辟的40byte缓冲区之前就正好。由于我们已经向0x5561dca0这个地址里面存入了指向缓冲区的首地址0x5561dc78,所以cookie的内容得放在(0x5561dca0+8)的前面,如0x5561dca8或者0x5561dca9都行,只是要注意这个地址和汇编代码里赋值给edi的地址值相呼应。
但是我这里有个疑问,按理说cookie只要存放在0x5561dca0+4这个地址后面就行,那我把它存放在0x5561dca4怎么就报错了呢?难道在0x5561dca0~0x5561dca8里面的内容只能是“78 dc 61 55 00 00 00 00”吗?
Level 04
到这里感觉就抽象起来了,我一开始看了许多题解都是处于懵懵懂懂的状态——一直不理解“POP X”后面跟“RET”到底是要干嘛。