본문 바로가기

Write Up

2016 KDMHS-CTF times


200점으로 나온 리버싱 문제이다. 새벽에 나와서 별로 풀 의지가 다들 없었던거 같다ㅠㅠ

IDA로 까보면

argv[1]로 플래그를 전달받는다.

그 다음 이 부분을 보자. 먼저 타임스탬프를 가져와서 srand넣어주고 dword_804B060xor하는데 dword_804B060를 seed라고 하자.

seed를 타임스탬프와 xor하고 순차적으로 rand()값을 0xffffff, 0xffff, 0xff로 나눈 나머지와 xor 해 주고 그 밑에서 막 쉬프트 연산을 해 준다. 많은 분들이 이 부분에서 아 이게 뭐야 하고 걍 닫았을 거라고 생각하는데 이 부분은 그냥 더미에 불과하다. 이거를 디버깅 해 봤다면 알 수 있었을 텐데 이 구간을 좀 더 간단하게 표현해 보면, 

처음 seed값이 0x12345678이라고 하면 seed ^ i를 한 후에 seed값을 0x56781234로 바꾼다. 그러고 다시 (i <<16)xor을 한다. 결과적으로는 바뀐 값이 없다. 그 다음에 나오는 쉬프트 연산이 나오는데 이거는 걍
0x56781234 -> 0x56341278 -> 0x56123478 -> 0x12563478 -> 0x12345678 이렇게 1바이트 단위로 서로 자리를 바꿔주면서 교체해 주다가 결국 다시 처음 값으로 돌아간다. 이 행위를 256번 하므로 결국 seed는 반복문을 돌고 나와도 달라진 값이 없게 된다.

그러고 나서 다시 타임스탬프 가져와서 위에서 타임스탬프랑 rand()값으로 xor해 줬던 방식을 그대로 거꾸로 연산을 다시 한다. , 1초가 소요되지 않았다면 타임스탬프가 바뀌지 않고 seed는 처음 상태 그대로 라는 것이다. 디버깅을 하면서 1초라도 소요가 됬다면 seed는 완전히 망가지나 실제 프로그램이 실행될 때는 1초가 소요될 일은 턱없이 없으므로, 이 부분까지 진행이 됐을 때 seed는 결국 처음 값과 같은 값을 가지게 되는 것이다. 그리고 마지막으로 

dword_804B060 += (v16 >> 24) ^ (unsigned __int8)((v16 >> 16) ^ v16 ^ BYTE1(v16)); 이 구간이 있는데 여기서 v16은 카나리이다. 카나리가 0x12345600이면 0x12 ^ 0x34 ^ 0x56 ^ 0x00을 한 값을 seed에 더해준다. 그러고 나서 0x100크기의 테이블을 만든다. 그 후에 

걍 만들어진 테이블에서 값 두 개 가져와서 xor하고 argv[1]값이랑 바로 비교한다. 최종적으로 우리는 테이블을 연산하는 루틴만 계산하고 그 테이블을 계산하는 루틴에서 seed가 쓰이는데 이 seed는 총 256가지 경우의 수를 가지고 있으므로 테이블도 256가지 경우의 수가 있다. 이거를 코드를 짜던가 angr를 돌려서 위에 비교 구간의 두 값을 xor해서 출력해 보면서  flag가 나오는 경우를 찾으면 된다. 마지막으로 seed의 맨 처음 초기값은 constructor에서

ptrace로 디버깅 중인지를 판단하고 맨 처음에 초기화 해 준다. 디버깅이 아니라면 초기값은 36이 되고, 여기서부터 걍 플래그 찾으면 된다

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
 
int main(void) {
    unsigned int seed = 0x24;
    unsigned char table[0x100];
    for (int i = 0; i < 0x100; i++) {
        seed = 0x24 + i;
        table[0= 0x30;
        for (int j = 1; j < 0x100; j++) {
            table[j] = seed >> (j % 7);
            for (int k = 0; k < 0x10; k++) {
                table[j] = ((table[j] << (k & 2)) ^ (table[j] >> (k & 1)));
                table[j] = (table[j] ^ table[j - 1] ^ seed);
            }
            seed ^= (seed % 0x22);
        }
        if (((table[0] ^ table[185]) == 'f') && ((table[0] ^ table[150]) == 'l')) {
            printf("%c", table[0] ^ table[185]);
            printf("%c", table[0] ^ table[150]);
            printf("%c", table[121] ^ table[137]);
            printf("%c", table[247] ^ table[130]);
            printf("%c", table[0] ^ table[38]);
            printf("%c", table[0] ^ table[103]);
            printf("%c", table[121] ^ table[200]);
            printf("%c", table[247] ^ table[122]);
            printf("%c", table[121] ^ table[87]);
            printf("%c", table[247] ^ table[58]);
            printf("%c", table[0] ^ table[123]);
            printf("%c", table[247] ^ table[87]);
            printf("%c", table[0] ^ table[249]);
            printf("%c", table[0] ^ table[141]);
            printf("%c", table[1] ^ table[87]);
            printf("%c", table[0] ^ table[59]);
            printf("%c", table[121] ^ table[32]);
            printf("%c", table[0] ^ table[123]);
            printf("%c", table[121] ^ table[123]);
            printf("%c", table[121] ^ table[213]);
            printf("%c", table[247] ^ table[58]);
            printf("%c", table[0] ^ table[249]);
            printf("%c", table[121] ^ table[24]);
            printf("%c", table[247] ^ table[249]);
            printf("%c", table[247] ^ table[213]);
            printf("%c", table[121] ^ table[58]);
            printf("%c", table[121] ^ table[123]);
            printf("%c", table[0] ^ table[134]);
            printf("%c", table[0] ^ table[113]);
            printf("%c", table[48] ^ table[48]);
            puts("");
        }
    }
}
cs

브포 소스

실행하면 키 나와요.


key : flag{CPU_15_50_f457_15n7_17?}

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

2016 Layer7 CTF Write-UP  (4) 2016.09.07
YISF 2016 예선 Write-Up  (2) 2016.08.19
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