본문 바로가기

Write Up

2016 ASIS CTF Quals - Catch Me!


대회 전체적으로 리버싱이 상당히 어렵게 나왔다.. 5문제 나왔는데 최종적으로는 이 문제 하나밖에 못풀었다. 아무래도 리버싱 문제를 풀 때 인내심이 약간 떨어진 것 같다. 본선 올라갔으니까 본선 문제는 빡세게 제대로 잡고 다 분석하겠다는 마음으로 풀어봐야겠다. 

이 문제는 x64 elf 바이너리이고 xmm 레지스터를 이용한 연산을 많이 한다. 

main함수의 코드는 이게 다이다.  sub_400820의 함수 리턴값은 항상 0xB11924E1로 같으므로 크게 신경쓸 것은 없다. 그 후에 이 값들을 이용해서 0x6012A8부터 네 바이트 값을 만들어 내고 ASIS와 CTF 환경변수의 값들을 가져와서 CTF 환경변수의 값과 0xB11924E1 이 값을 xor했을 때의 값이 0xFEEBFEEB이면 ASIS 환경변수에 있는 값을 0x6012AC부터 4바이트만큼 넣어준다. 이 부분은 동적 디버깅을 하면서 직접 넣어줄 수 있는 부분이라서 걍 환경변수는 무시하고 풀었다. 그 후에 haystack값과 0x6012A8에 있는 값을 한 글자씩 계속 xor해 나간 후에 막 xmm레지스터 연산들을 한다. 근데 저 부분이 엄청 어려워 보이는데 사실은 걍 xor해서 나온 플래그 값의 각 자리수 아스키 합이다. 즉, 걍 xor해서 합이 2388인 값을 찾으면 되는 것이다. 동적디버깅 해 보면 플래그 중 600d...._y0u...._637...._574.... 이 부분은 확실한 플래그 부분임을 알 수 있고, xor했을 때 나머지 값을 만족할 수 있는 4바이트를 찾아야 하는데 그 힌트로 글자수 합 2388이 주어졌는데 걍 게싱으로 풀었다. 

먼저 경우의 수를 최대한 줄이기 위해서 원래 haystack에 세팅되어 있는 값과 어떤 값을 xor했을 때 정상적인 문자가 나오는지를 찾아보았다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
 
char asciitable[] = "0123456789ABCDEFGHIJKLMNOPQRSTVWXYZabcdefghijklmnopqrstuvwxyz!@():-_";
bool isascii(char);
int main(void) {
    unsigned char table[4][4= { { 0x550xB00xC20x2D }, { 0x550xEE0x800x7C }, 
                            { 0x3D0xEB0x9C0x79 }, { 0x780xED0xC10x2B } };
 
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 0x100; j++) {
            if (isascii(table[0][i] ^ j) && isascii(table[1][i] ^ j) && isascii(table[2][i] ^ j) && isascii(table[3][i] ^ j))
                printf("%c  %c  %c  %c  %x \n", table[0][i] ^ j, table[1][i] ^ j, table[2][i] ^ j, table[3][i] ^ j, j);
        }
        printf("---------------------------------------------------------\n");
    }
}
 
bool isascii(char tmp) {
    if (tmp == NULLreturn false;
    for (int i = 0; i < sizeof(asciitable); i++) {
        if (tmp == asciitable[i])
            return true;
    }
    return false;
}
cs

이렇게 코딩하고 나온 값들을 선별하여 가장 플래그 스러운 문자열을 만들면 된다. 적당히 나온 값들을 선별해서 뽑아보면 

_  _  7  r  a 

Y  Y  1  t  c 

X  X  0  u  d 

Z  Z  2  w  f 

---------------------

0  n  k  m  80 

1  o  j  l  81 

2  l  i  o  82 

3  m  h  n  83 

4  j  o  i  84 

5  k  n  h  85 

6  h  m  k  86 

7  i  l  j  87 

8  f  c  e  88 

9  g  b  d  89 

:  d  a  g  8a 

h  6  3  5  d8 

i  7  2  4  d9 

j  4  1  7  da 

k  5  0  6  db 

l  2  7  1  dc 

m  3  6  0  dd 

n  0  5  3  de 

o  1  4  2  df 

---------------------

o  -  1  l  ad 

s  1  -  p  b1 

2  p  l  1  f0 

3  q  m  0  f1 

0  r  n  3  f2 

1  s  o  2  f3 

6  t  h  5  f4 

7  u  i  4  f5 

4  v  j  7  f6 

5  w  k  6  f7 

---------------------

5  d  a  3  18 

7  f  c  1  1a 

6  g  b  0  1b 

0  a  d  6  1d 

3  b  g  5  1e 

2  c  f  4  1f 

e  4  1  c  48 

d  5  0  b  49 

g  6  3  a  4a 

a  0  5  g  4c 

c  2  7  e  4e 

b  3  6  d  4f 

--------------------

이렇게 나온다. 먼저 여러 값을 넣어본 결과 각 자리 중 맨 앞은 _  _  7  r 이 들어가서 플래그가 600d_..._y0u_..._6377..._574r... 이렇게 이어나가는게 가장 자연스러울 것 같아서 이렇게 설정했고, 이제부터는 위 플래그를 평문으로 바꿔보았을 때
Good ___ you ___ gett___ star___ 이렇게 나오고 적당한 게싱을 통해 Good 뒤에는 job이 온다던가 you 뒤에는 are 이 온다는 것을 추측해 내어 적당히 게싱해 주면 된다. 나는 you 뒤에 are이 온다고 가정했고 (매쓰보이 하드캐리) 위에서 이를 만족할 수 있는 값들을 찾아 보았더니 4r3 이 만들어 질 수 있는 셋을 발견했고 이를 이용해서 
j  4  1  7,  0  r  n  3,  b  3  6  d 이런 값들을 발견했다. 이를 모두 플래그에 적용시켜보면 최종적으로 600d_j0b_y0u_4r3_63771n6_574r73d 라는 플래그를 만들 수 있다. 그래서 ASIS{600d_j0b_y0u_4r3_63771n6_574r73d} 이렇게 인증했더니 풀렸다..

key : ASIS{600d_j0b_y0u_4r3_63771n6_574r73d}


'Write Up' 카테고리의 다른 글

2016 KDMHS-CTF times  (0) 2016.05.15
2016 ASIS CTF Quals - firtog  (0) 2016.05.09
2016 CodeGate Final rev  (1) 2016.05.06
2016 CodeGate Final GMPQZ  (0) 2016.05.04
2016 CodeGate Final BMP  (0) 2016.05.04