BLOG main image
분류 전체보기 (224)
Reversing (13)
Pwnable (4)
Linux Kernel (3)
Crypto (2)
Wargames (68)
Programming (18)
Write Up (32)
Project (22)
Web (2)
My Life (52)
Memo (3)
etc (2)
발표자료 (1)
42,654 Visitors up to today!
Today 2 hit, Yesterday 27 hit
daisy rss
tistory 티스토리 가입하기!
2016.05.09 21:09


대회 전체적으로 리버싱이 상당히 어렵게 나왔다.. 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 ASIS CTF Quals - Catch Me!  (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
Name
Password
Homepage
Secret