대회 전체적으로 리버싱이 상당히 어렵게 나왔다.. 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] = { { 0x55, 0xB0, 0xC2, 0x2D }, { 0x55, 0xEE, 0x80, 0x7C }, { 0x3D, 0xEB, 0x9C, 0x79 }, { 0x78, 0xED, 0xC1, 0x2B } }; 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 == NULL) return 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
--------------------
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} 이렇게 인증했더니 풀렸다..
'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 |