https://war.sejongssg.kr/ < SSG ctf문제 사이트

test1.py



메세지와 인코딩 프로그램을 남겼다고 한다. 그 메세지를 디코드하면 된단다.

때는 작년 12월 말 문제 배점이 적도 문제이름에도 easy라고 하길래.. 문제 봤다가 포기 했었다. ida 헥스레이가 있다지만 그리고 

코드도 그렇게 길지 않았지만 

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
int v3; // edx 
 
signed int i; // [esp-19Ch] [ebp-19Ch] 
 
signed int j; // [esp-19Ch] [ebp-19Ch] 
 
signed int v7; // [esp-198h] [ebp-198h] 
 
int v8; // [esp-194h] [ebp-194h] 
 
char v9; // [esp-99h] [ebp-99h] 
 
int v10; // [esp-5Bh] [ebp-5Bh] 
 
_BYTE v11[3]; // [esp-57h] [ebp-57h] 
 
int v12; // [esp-20h] [ebp-20h] 
 
unsigned int v13; // [esp-1Ch] [ebp-1Ch] 
 
int *v14; // [esp-14h] [ebp-14h] 
 
 *(_DWORD *)
 
(char *)&v12
 
((unsigned int)((char *)&v10 - ((unsigned int)v11 & 4294967292) + 63) & 4294967292) >> 2 
cs

등등...

쓸떼없이 복잡한 변수와 자료형들이 뭘 뜻하는지 잘 몰랐기 때문이다.

후에도 차근차근 하나씩 해보자 했었지만 금방 접고 다른 걸 했었는데 어제 저녁, 내일 이 문제를 다시 풀기로 했다.

그리고 엄청 느린속도로 코드수정을 한 결과 풀 수 있었다. 별거 아니지만 내 생각이 맞았다는 생각에 뿌듯했다.





파일을 내려받아서 확장자를 zip으로 바꿔주고 압풀을 풀어주면 decode it.txt라는 텍스트 파일 하나와

easy_linux_reversing이라는 32bit elf파일이 나온다.

파일을 실행하면 Input the Message: 라는 문구와함께 문자열을 입력할 수 있는데

그 문자열이 아래 메모장의 result와 같이 인코딩 되어 출력 된다는 것이다.



파란 상자안에 코드는 헥스레이 수도코드 사이사이에 조금 더 이해하기 쉽게 다시 쓴 코드다. 

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
int __cdecl main(int argc, const char **argv, const char **envp) 
int v3; // edx 
signed int i; // [esp-19Ch] [ebp-19Ch] 
signed int j; // [esp-19Ch] [ebp-19Ch] 
signed int v7; // [esp-198h] [ebp-198h] 
int v8; // [esp-194h] [ebp-194h] 
char v9; // [esp-99h] [ebp-99h] 
==> char buffer[251?]="";
 
int v10; // [esp-5Bh] [ebp-5Bh] 
_BYTE v11[3]; // [esp-57h] [ebp-57h] 
int v12; // [esp-20h] [ebp-20h] 
unsigned int v13; // [esp-1Ch] [ebp-1Ch] 
int *v14; // [esp-14h] [ebp-14h] 
 
v10 = *(_DWORD *)"Tz1jWRprBqZDfC7OFVgu5N8yAslxL4Kab2cYt3QeH9dGhwkPXvMnIoUEi0SmJ6"
==> char msg1[]="Tz1jWRprBqZDfC7OFVgu5N8yAslxL4Kab2cYt3QeH9dGhwkPXvMnIoUEi0SmJ6";
 
strcpy((char *)&v12, "mJ6"); 
==> char msg2[]="mj6";
 
qmemcpy((void *)((unsigned int)v11 & 4294967292),(const void *("Tz1jWRprBqZDfC7OFVgu5N8yAslxL4Kab2cYt3QeH9dGhwkPXvMnIoUEi0SmJ6" - ((char *)&v10- ((unsigned int)v11 & 4294967292))),4 * (((unsigned int)((char *)&v10 - ((unsigned int)v11 & 4294967292+ 63& 4294967292>> 2));
==>qmemcpy( (void *)(msg2 & 4294967292),msg1- (msg1- (msg2 & 4294967292))),4 * ((msg1 - ((msg2 & 4294967292+ 63& 4294967292>> 2)); 
==>memcpy((msg2 & 0xfffffffc),(msg2 & 0xfffffffc),(msg1 - ((msg2 & 0xfffffffc+ 63& 0xfffffffc));  //  >> 2 우 쉬프트 연산은 나누기2^n의 효과
결국 memcpy함수의 src주소와 dest주소가 같고 3번째 인자의 값만큼 바이트를 복사하는데 그말은 곧 memcpy하기 전의 값이나 한 후의 값이나 변화가 없다는 뜻이다.
 
printf("Input the Message : ");
 
fgets(&v9, 60, stdin);
==> fgets(buffer,60,stdin); 
 
 
 
v7 = strlen(&v9) - 1;
==> int num = strlen(buffer)-1;
 
 
 
for ( i = 0; i < v7; ++i ) 
if ( (*((_BYTE *)&v10 + i) + (_BYTE)i) & 1 ) 
v3 = *(&v9 + i) - *((char *)&v10 + i); 
else 
v3 = *((char *)&v10 + i) + *(&v9 + i); 
*(&v8 + i) = v3; 
*(&v8 + i) ^= *((char *)&v10 + v7 - i); 
==>
for ( i = 0; i < num; ++i ) 
    { 
        if ((msg1[i]+i)&1)  //홀, 짝
            v3 = buffer[i] - msg1[i]; 
        else 
            v3 = msg1[i] + buffer[i];
        v8[i]= v3;
        v8[i]^= msg1[num-i]; 
    }  //핵심 결국
 
 
 
printf("Encode result = "); 
 
for ( j = 0; j<v7; ++j ) 
printf("%d "*(&v8 + j));
==>
for (j=0; j<num; ++1){
        printf("%d ", v8[i]);
}
 
return 0;
cs


내가 디코딩 해야할 input값은 이미 메모장에 적힌 222 -125 83 -115 -116 -79 -105 195 145 211 37 20 총 13글자이다.

즉 input이 13일때만 고려하면 된다. 예를 들어

첫번째 테스트에  "aaaaa" 와 두번째 테스트에서 "aaaaaa" 넣었을때 encode[0]의 값이 일정하지 않았던 이유는 for문안에 

v8[i]^= msg1[num-i];   이 구문 때문이다. 

encoding 값과 자릿값을 이미 알고 그값을 decoding할 때는 num가 13으로 고정이기 때문에 영향을 받지 않는다.

decode값을 수월하게 추측해 볼 수 있다. 



*XOR연산 특징 :  A^B=C  , B^C=A, C^A=B



'CTF' 카테고리의 다른 글

[PlaidCTF 2013] ropasaurusrex  (0) 2018.02.07
[Codegate 2017] babypwn  (0) 2018.02.06

+ Recent posts