인텐드 솔루션으로 푸신분이 아무도 없네요..ㅜㅜ
전부 치트엔진+게싱 했어요..ㅜㅜ
1. static analysis
아래는 정적 분석을 통해 작성한 코드 이고 이걸 돌리면 디컴파일이 샤샤샥 됩니다.
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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
| #include <stdio.h> #include <stdint.h> #include <windows.h> struct MT { uint32_t *next; uint32_t items; uint32_t mt[624]; }; static uint8_t MT_getnext(struct MT *MT) { uint32_t r; if (!––MT–>items) { uint32_t *mt = MT–>mt; unsigned int i; MT–>items = 624; MT–>next = mt; for (i=0; i<227; i++) mt[i] = ((((mt[i] ^ mt[i+1])&0x7ffffffe)^mt[i])>>1)^((0–(mt[i+1]&1))&0x9908b0df)^mt[i+397]; for (; i<623; i++) mt[i] = ((((mt[i] ^ mt[i+1])&0x7ffffffe)^mt[i])>>1)^((0–(mt[i+1]&1))&0x9908b0df)^mt[i–227]; mt[623] = ((((mt[623] ^ mt[0])&0x7ffffffe)^mt[623])>>1)^((0–(mt[0]&1))&0x9908b0df)^mt[i–227]; } r = *(MT–>next++); r ^= (r >> 11); r ^= ((r & 0xff3a58ad) << 7); r ^= ((r & 0xffffdf8c) << 15); r ^= (r >> 18); return (uint8_t)(r >> 1); } static void MT_decrypt(uint8_t *buf, unsigned int size, uint32_t seed) { struct MT MT; unsigned int i; uint32_t *mt = MT.mt; *mt=seed; for(i=1; i<624; i++) mt[i] = i+0x6c078965*((mt[i–1]>>30)^mt[i–1]); MT.items = 1; MT.next = MT.mt; while(size––) *buf++ ^= MT_getnext(&MT); } int main(void) { FILE *fp=fopen("AHK_MASTER.exe","rb"); fseek(fp , 0x54A00, SEEK_SET ); //00 4A 05 00 F4 29 07 93 <– file end / AHK~START(4) + CRC(4) unsigned char rawData[0x200] = {0,}; fread(rawData,1,0x200,fp); BYTE *pData = rawData; DWORD PWSum = 0; pData += 16; //Skip 16bytes header pData +=1; //must 3; //pw DWORD PWLen = *(DWORD *)pData ^ 0xFAC1; pData += 4; MT_decrypt(pData,PWLen,PWLen+0xC3D2); printf("password : "); for(int i=0; i<PWLen; i++) { PWSum += pData[i]; printf("%c",pData[i]); } printf("\n"); pData += PWLen; //const str MT_decrypt(pData,4,0x16FA); for(int i=0; i<4; i++) printf("%c",pData[i]); //must FILE printf("\n"); pData += 4; //Type DWORD Len2 = *(DWORD *)pData ^ 0x29BC; pData +=4; MT_decrypt(pData,Len2,Len2+0xA25E); printf("Type : "); for(int i=0; i<Len2; i++) printf("%c",pData[i]); printf("\n"); pData += Len2; //Org Exe DWORD Len3 = *(DWORD *)pData ^ 0x29AC; pData +=4; MT_decrypt(pData,Len3,Len3+0xF25E); printf("Org EXE : "); for(int i=0; i<Len3; i++) printf("%c",pData[i]); printf("\n"); pData += Len3; //JB01 Packed?! bool is_packed = pData[0]; pData += 1; //SizeGet DWORD CompressedSize = *(DWORD *)pData ^ 0x45AA; pData +=4; DWORD UnCompressedSize = *(DWORD *)pData ^ 0x45AA; pData +=4; pData += 16; BYTE *Output = (BYTE *)calloc(1,CompressedSize + 1); BYTE *OutputUnCompressed = (BYTE *)calloc(1,UnCompressedSize + 1); MT_decrypt(pData,CompressedSize,PWSum+0x22AF); memcpy(Output,pData,CompressedSize); printf("%d %d : %d\n\n\n",CompressedSize,UnCompressedSize,Len2); if(is_packed == 0) { srand(0x1000); for(int i=0; i<CompressedSize; i++) Output[i] ^= rand()&0xff; printf("%s",Output); } }
| cs |
2. dynamic analysis
"스크립트 복호화가 끝난 직후"에 메모리에 Break Point를 걸어주면 볼 수 있다.
(그냥 실행하고 cheat engine으로 스캔해봤자 안보임 ㅅㄱ)