몇달 전에 있었던 hack.lu ctf 문제 중 exploit 문제 Guess the Flag 입니다.
그 날 이 문제 풀면서 멘붕이 왔었는데 바쁜 일 다 끝나고 학교동아리 홈페이지에 이 문제를 아주 약간 바꿔서 올린걸 풀어보았습니다.
문제의 원래 코드는 이렇게 생겼습니다. 전 동아리 서버에 올린 문제로 풀이를 하겠습니다.
문제의 서버환경은 64bit이지만 동아리 서버는 32bit입니다. 문제풀이 하실 때에 크게 차이 없을거에요.
이 문제의 핵심적인 부분을 설명드리자면,
* guess> 뒤에 100글자를 입력해야 하고
위의 is_flag_correct() 함수에서
char value1 = bin_by_hex[flag_hex[i * 2 ]];
char value2 = bin_by_hex[flag_hex[i * 2 + 1]];
에서 * value1 에는 16진수의 앞자리가 들어가고 value2는 16진수의 뒷자리가 들어갑니다.
char diff = 0;
for (i = 0; i < 50; i++)
{
diff |= (flag[i] ^ given_flag[i]);
printf("diff = %d\n", diff);
}
return (diff == 0);
* 이 부분은 서버의 flag값과 자신이 입력한 100글자 값이 모두 일치할 경우 ( |= 를 썼기 때문에 하나라도 삐끗하면 diff 값이 절대 0이 나올 수 없습니다.) return 1을 반환합니다. 이럴 경우 handle() 함수에서는 correct, 일치했다고 받아들입니다.
* rtrim() 함수에서는 입력한 문자열에 \r\n 가 포함될 경우 그걸 짤라냅니다.
코드를 찬찬히 훑어보면 이 코드에는 문제가 전혀 없습니다. 아주 완벽하게!! 코딩되었어요. untrusted input 값은 보이지도 않고요.
브루트 포스로 100글자를 돌려야되나요? 절대 안됩니다. 너무 오래걸려요.
이 문제는 배열을 음수로 쓸 수도 있다는 걸 감안해서 브루트포스 어택을 시도해야 합니다.
가령 a[1] 이 있다면 a[-1]도 있겠죠.
char value1 = bin_by_hex[flag_hex[i * 2 ]];
char value2 = bin_by_hex[flag_hex[i * 2 + 1]];
여기에서는 입력한 값을 이용해서
given_flag[i] = (value1 << 4) | value2;
given_flag 값을 생성합니다. 이 given_flag 는 실제 flag 배열에 있는 값과 xor연산을 하게 되는데
만약 배열을 역참조해서 flag값에 접근할 수 있다면 given_flag 값에 뭐가 들어있는지는 모르겠지만 flag 값에 접근할 수 있는 offset값을 찾아서(given_flag[offset]) flag값과 xor연산을 했을 때 , flag[i] ^ given_flag[i] == 0 이 나온다면 결국 correct, 일치한다는 답을 얻어오겠죠.
일치해서 출력되는 결과값 Yaaaay! you guessed the flag ... 가 나온다면 게임 끝.
앞에서건 뒤에서건 여러분이 원하는 방향에서 한글자 한글자씩 brute force로 값을 얻어올 수 있습니다.
* 위 flag값은 hack.lu 의 flag값은 아니고 임의로 지정한 flag입니다.
guess_the_flag 는 당시 hack.lu에 올라와있던 tar 파일이고
q2.c는 원본 텍스트를 한글로 조금 바꾼 파일
guess.py 는 제가 짠 exploit 코드입니다.
guess_the_flag_cb153ec1260946d13f5f1f0605e4dff9.tar
'Let's Study > Hacker's CTF' 카테고리의 다른 글
[2015 Plaid CTF] pwnable_EBP 160p (0) | 2015.04.21 |
---|---|
[2015 Nullcon] exploitable 300 (2) | 2015.01.14 |
[2014 화이트햇 콘테스트] 한글치환암호 (0) | 2014.11.10 |
[2014 화이트햇 콘테스트]Cold War (0) | 2014.11.10 |