https://war.sejongssg.kr/ < SSG ctf문제 사이트
메세지와 인코딩 프로그램을 남겼다고 한다. 그 메세지를 디코드하면 된단다.
때는 작년 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 |