2017 Dimi CTF Final warmup

64bit 바이너리 warmup과 flag.enc가 주어졌다.

$ file warmup
warmup: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=387ae1f78e1eda40583739245d91ad9ce53a9442, stripped

flag.enc 파일은 뭔가 인코딩 되어 있는듯 알 수 없이 되어있었다.

우선 메인을 보게 되면 입력받은 값을 각종 연산을 하고 flag.enc에 한 글자씩 써 넣는다.

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  unsigned int v3; // eax
  int v4; // eax
  unsigned int v5; // eax
  size_t v6; // rbx
  unsigned int ptr; // [rsp+Ch] [rbp-54h]
  int i; // [rsp+10h] [rbp-50h]
  unsigned int v10; // [rsp+14h] [rbp-4Ch]
  FILE *s; // [rsp+18h] [rbp-48h]
  char v12[8]; // [rsp+20h] [rbp-40h]
  __int64 v13; // [rsp+28h] [rbp-38h]
  __int64 v14; // [rsp+30h] [rbp-30h]
  __int64 v15; // [rsp+38h] [rbp-28h]
  __int64 v16; // [rsp+40h] [rbp-20h]
  unsigned __int64 v17; // [rsp+48h] [rbp-18h]

  v17 = __readfsqword(0x28u);
  *(_QWORD *)v12 = 0LL;
  v13 = 0LL;
  v14 = 0LL;
  v15 = 0LL;
  v16 = 0LL;
  printf("INPUT: ", a2, a3);
  __isoc99_scanf("%20s", v12);
  v3 = time(0LL);
  srand(v3);
  s = fopen("flag.enc", "wb");
  for ( i = 0; ; ++i )
  {
    v6 = i;
    if ( v6 >= strlen(v12) )
      break;
    v4 = rand();
    v10 = (unsigned __int8)(((unsigned int)(v4 >> 31) >> 24) + v4) - ((unsigned int)(v4 >> 31) >> 24);
    v5 = (unsigned int)((signed int)(255 - (v10 & v12[i])) >> 31) >> 24;
    ptr = (v10 | v12[i]) & ((unsigned __int8)(v5 + -1 - (v10 & v12[i])) - v5);
    fwrite(&ptr, 1uLL, 1uLL, s);
  }
  fclose(s);
  return 0LL;
}

근데 여기서 문제는 여기서부터였다. 조금 게싱이 필요한 문제이다. 이 flag.enc 파일이 생성된 날짜가 필요했다.

위에 보면 v3 = time(0) 그리고 이 v3를 srand() 값으로 넣어주고 밑에 이 시드를 이용해 rand() 함수를 사용한다.

일단 time(0)를 하게되면 어떤 일이 일어나냐면 1970년 1월 1일 00:00:00 UTC 부터 현재까지의 경과 시간을 초로 리턴해준다.

-> 참고 : 유닉스 시간

그래서 1970년 1월 1일 00:00:00 UTC 부터 이 flag.enc 인코딩된 시간인 2017 7월 19일 9시 57분 27초까지 경과된 초를 가져와서 srand() 넣어주면 된다. 나는 유닉스 계산기를 이용해서 시간을 구했다.

자 이제 flag.enc가 생성된 날짜의 time(0)를 구했고 이제 1500425847 을 시드 값으로 넣어주고 rand()를 이용해서 막 엄청난 연산을 한다 :) 이제 인코딩된 문자들의 값을 구해주고 쉽게 풀 수 있다.

#!/usr/bin/python
# -*- coding: iso-8859-15 -*-

from ctypes import *
from z3 import *
import string

libc = CDLL('/lib/x86_64-linux-gnu/libc.so.6')
libc.srand(1500425847)
table=[0xAD,0xE4,0xAE,0x8D,0xA9,0x63,0xE0,0x48,0x79,0x34,0x10,0x1A,0xF4,0x51,0x2B,0xD3,0xCE,0x3C,0x98]

s = Solver()
a1 = [BitVec('a%i'%i,8)for i in range(len(table))]
for i in range(len(table)):
	random = libc.rand()
	shift_rand = (((random >> 31) >> 24) + random) - ((random >> 31) >> 24)
	s.add((shift_rand | a1[i]) & (((((255 - (shift_rand & a1[i])) >> 31) >> 24) + -1 - (shift_rand & a1[i])) - (((255 - (shift_rand & a1[i])) >> 31) >> 24)) == table[i])

print s.check()
print s.model()
m = s.model()
print ''.join(chr(int(str((m.evaluate(a1[i]))))) for i in range(len(table)))

FLAG : dimigo{Warming_up!}