-
Random KeyCTF/HackCTF 2021. 2. 1. 02:24
Disassembly 디스어셈블리
void main(void) { undefined4 uVar1; undefined8 extraout_RDX; int64_t iVar2; uint32_t *puVar3; uint64_t uVar4; int64_t in_FS_OFFSET; uint32_t var_10h; uint32_t var_ch; int64_t var_8h; var_8h = *(int64_t *)(in_FS_OFFSET + 0x28); setbuf(_reloc.stdout, 0); var_ch = 0; var_10h = 0; uVar1 = time(0); srand(uVar1); var_ch = rand(); puts(0x400928); puts("======= 인증 프로그램 ======"); puts(0x400928); printf("Input Key : "); puVar3 = &var_10h; __isoc99_scanf(0x400978, puVar3); if (var_ch == var_10h) { puts("Correct!"); system("cat /home/random/flag"); exit(0); } puts("Nah..."); uVar4 = 0; exit(0); }
main은 scanf("%d", &var_10h)로 정수를 입력받고 srand(time(0)), rand()를 통해 생성한 난수 var_ch와 비교해 같으면 flag를 출력한다.
Breaking rand()
srand(time(0))은 rand()의 seed를 time(0), 즉 1970년부터 프로그램이 실행중인 시각까지 경과된 시각으로 설정하는 함수이다. 따라서 실행되는 시각의 초 단위가 같은 경우 rand는 항상 같은 seed로 실행되어 일정한 값을 가진다.
srand(time(0))을 seed로 한 rand 값을 rand.txt에 출력하는 rand.cpp를 작성하자. 이제 exploit 코드에서 rand.cpp를 실행한 뒤 rand.txt의 값을 읽어와 payload로 전송하도록 하면 문제를 해결할 수 있다. 만약 실패한다면 random 바이너리에서 srand가 실행되는 시각과 rand.cpp가 실행되는 시각이 초 단위로 일치하지 않은 것이니 여러 번 실행해주면 된다.
Code
더보기from pwn import * from os import system binary = "./random" server = "ctf.j0n9hyun.xyz" port = 3014 # context.log_level = 'debug' context.binary = binary p = remote(server, port) e = ELF(binary) p.recvuntil("Input Key : ") system("./rand") f = open("rand.txt","r") payload = f.read() p.sendline(payload) p.interactive()
#include <bits/stdc++.h> int main() { srand(time(0)); FILE* fd = fopen("rand.txt","w"); fprintf(fd, "%d", rand()); }
Flag
HackCTF{5087686686858549173307745189}