// passcode@prowl:~$ cat passcode.c
#include <stdio.h>
#include <stdlib.h>
void login(){
int passcode1;
int passcode2;
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);
}
}
void welcome(){
char name[100];
printf("enter you name : ");
scanf("%100s", name);
printf("Welcome %s!\n", name);
}
int main(){
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");
return 0;
}
gdb로 까보자!
일단 login부터 까보면, passcode1의 위치는 ebp-0x10이고, passcode2의 위치는 ebp-0xc이다.
또한 각각을 0x52836=338150, 0xcc07c9=13371337과 비교하는 것도 볼 수 있다.
그리고 name은 ebp-0x70에 위치해있다.
일단 passcode1까지만 입력을 받도록 브레이크를 잡아주고 실행해보았다.
원래는 0x70-0x10=96이니까 아무 생각없이 96개 아무거나 넣어주고 338150과 13371337을 입력하려 했다. 근데 데시멀 바이트가 리틀인가 싶어서 일단 아무거나 넣었는데 100개밖에 받지 못했다....! 그리고 내가 코드를 좀 더 유심히 봤어야 했다....
void login(){
int passcode1;
int passcode2;
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);
}
}
login() 부분만 보면, passcode1과 passcode2의 입력을 받는 부분(scanf)에서 &을 쓰지 않은 것을 볼 수 있다.
이렇게 되면, scanf에 들어가는 값을 주소로 인식하므로, 값이 주소가 되어 입력값을 저장할 수 있다.
정리하자면 지금 name에서 딱 passcode1이 위치한 곳까지(ebp-0x10) 값을 변경할 수 있다.
이렇게 name에서 [ebp-0x10]을 변경하면, passcode1의 입력을 받는 부분에서 &이 없으므로 [ebp-0x10]에 있는 값이 주소가 되어 그 주소에 해당하는 값을 입력한 값으로 변경할 수 있다.
passcode1을 입력받은후 fflush함수를 호출하므로, fflush의 GOT주소를 system 함수 주소로 변경할 수 있다면 좋을 것 같다. fflush의 GOT은 0x0804a004이다.