CTF 문제 중에서, random으로 추출되는 값을 예측하는 문제가 있었다. 코드는 다음과 같다.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(void)
{
char c, t[4] = "RPS";
int i, p, r;
srand(time(NULL));
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
for(i = 1; i <= 10; i++)
{
printf("Round %d of 10\n", i);
printf("Put your hand out(R, P, S): ");
scanf("%c", &c);
while(getchar() != '\n');
switch(c)
{
case 'R':
p = 0;
break;
case 'P':
p = 1;
break;
case 'S':
p = 2;
break;
default:
printf("Nope!\n");
return 0;
}
sleep(1);
r = rand() % 3;
printf("You: %c Computer: %c\n", t[p], t[r]);
if((r - p + 1) % 3)
{
printf("Nope!\n");
return 0;
}
}
int fd = open("./flag", O_RDONLY);
char flag[64] = { 0, };
read(fd, flag, 64);
printf("Flag is %s\n", flag);
close(fd);
return 0;
}
가위, 바위, 보를 봇은 무작위로 생성하고, 우리는 이 값을 모른 상태에서 10번 연속으로 가위바위보를 이겨야 한다. -> 사실, 10번 연속으로 이긴다는건 불가능하기 때문에 다른 방법을 찾아보았다.
조금만 생각해보면, 우리가 srand 값을 문제 환경과 동일하게 맞춰준다면 랜덤으로 나오는 값을 예측할 수 있을 것이다. 그러면 파이썬으로 srand 함수를 구현할 수 있을까?
ctypes
ctypes 라이브러리는 파이썬에서 C 호환 데이터형을 제공하는 라이브러리이다.
이 라이브러리를 사용하면, C언어에서 사용하는 함수를 파이썬에서도 사용할 수 있다.
사용법은 다음과 같다.
from ctypes import *
다음과 같이 선언하면, C언어 함수들을 사용할 수 있다. 그러면 여기서 srand 함수는 어떻게 사용할 수 있을까? 아래 코드는 srand 함수를 사용한 문제 Exploit 코드이다.
from ctypes import *
p = process('./chall')
libc = CDLL('/ilb/x86_64-linux-gnu/libc.so.6')
libc.srand(libc.time(0))
for a in range(10):
key = rand() % 3
answer = ''
if key == 0:
answer = 'P'
elif key == 1:
answer = 'S'
else:
answer = 'R'
p.sendlineafter(': ', answer)
p.interactive()
다음과 같이 사용하면, 서버에서 생성하는 랜덤값을 미리 추출할 수 있기에 가위바위보를 모두 이길 수 있다.