이번에 풀이할 문제는 pwnable.kr의 random 문제다. 문제 문구는 "아빠가 프로그래밍에서 랜덤 값을 어떻게 사용하는지 가르쳐 주셨다"다.
접속하니 flag, random, random.c가 주어져 있어서 먼저 cat random.c 명령어로 소스 코드를 확인해봤다.
#include <stdio.h>
int main(){
unsigned int random;
random = rand(); // 랜덤 값(?) 생성
unsigned int key=0;
scanf("%d", &key); // key 입력
if( (key ^ random) == 0xdeadbeef ){ // key xor random한 값이 0xdeadbeef와 같다면 flag 획득
printf("Good!\n");
system("/bin/cat flag");
return 0;
}
printf("Wrong, maybe you should try 2^32 cases.\n");
return 0;
}
랜덤 값을 생성하는 rand() 함수를 통해 만들어진 값을 random 변수에 저장하고 key를 입력받는데, 이 random 변수의 값과 key를 xor 연산했을 때 0xdeadbeef가 나오면 flag를 획득할 수 있는 문제다.
이번 문제는 비교적 쉬웠다. 최근 c++ 게임 개발 관련 대회에 나가 랜덤 함수를 자주 사용봐서 아는 사실인데 rand 함수는 srand 함수로 시드(seed)를 생성한 후 사용해야지 정상적으로 작동이 된다. 이 정상적으로 작동이 된다라는 말은 의도대로 랜덤한 값이 생성된다는 뜻이다. 보통은 rand 함수를 쓰기전 ctime 혹은 time.h를 include한 다음 srand((unsigned int)time(NULL));을 작성해 seed를 현재 시간으로 설정해준다.
이 문제 같은 경우는 srand 없이 rand만 써줬기 때문에 랜덤한 값이 아닌 항상 똑같은 값이 rand 함수의 리턴 값이 된다. 이 말인 즉슨 항상 똑같은 값이 random에 들어가므로 gdb를 통해 rand 함수의 리턴 값을 확인한 후 해당 값과 xor를 했을 때 0xdeadbeef가 나오는 값을 key 값으로 입력해주면 될 것 같다.
gdb로 rand 함수 바로 다음 부분에 bp를 걸고 실행한 후 rax에 저장돼 있을 반환 값을 확인해보니 0x6b8b4567인 것을 볼 수 있다. 여러 번 실행해보면 알겠지만 위에 정리한대로 매번 똑같은 값이 rand 함수의 반환 값이 된다.
입력 값을 x라 생각할 때
x xor 0x6b8b4567 = 0xdeadbeef
0xdeadbeef xor 0x6b8b4567 = x와 같으므로 0xdeadbeef xor 0x6b8b4567을 구하면 입력 값으로 넣어야할 값을 알 수 있게 될 것이다.
16진수로 0xB526FB88, 10진수로 3039230856이 나왔다. 이 10진수 값을 입력 값으로 넣어주면 flag를 얻을 수 있을 것이다.
'Wargame > Pwnable.kr' 카테고리의 다른 글
pwnable.kr [leg] (0) | 2021.04.08 |
---|---|
pwnable.kr [flag] (0) | 2021.04.08 |
pwnable.kr [bof] (0) | 2021.04.04 |
pwnable.kr [collision] (0) | 2021.04.02 |
pwnable.kr [fd] (0) | 2021.04.01 |