constWORLDant

RansomeWare 본문

0x02 Reverse Engineer/0x02. Reverse.kr

RansomeWare

data type ConS_tanT 2017.07.28 16:05


Decrypt File (EXE)



By Pyutic



UPX 가볍게 UNPACKING` ~ ` 


Microsoft Visual C++ v.10


0044A775    68 ACC14400     push run_unpa.0044C1AC                                  ; ASCII "Key : "

0044A77A    FF15 B0C04400   call near dword ptr [<&MSVCR100.printf>]                ; MSVCR100.printf

0044A780    83C4 04         add esp,0x4

0044A783    E8 7868FBFF     call run_unpa.00401000

0044A788    68 70D34400     push run_unpa.0044D370                                  ; ASCII "ransomeware"

0044A78D    68 B4C14400     push run_unpa.0044C1B4                                  ; ASCII "%s"

0044A792    FF15 B8C04400   call near dword ptr [<&MSVCR100.scanf>]                 ; MSVCR100.scanf

0044A798    83C4 08         add esp,0x8

0044A79B    C745 E8 70D3440>mov dword ptr [ebp-0x18],run_unpa.0044D370              ; ASCII "ransomeware"  // 내가 입력한 값 



0044A856  |> /8B55 FC       /mov edx,[local.1]

0044A859  |. |52            |push edx                                               ; /stream

0044A85A  |. |FF15 C0C04400 |call near dword ptr [<&MSVCR100.feof>]                 ; \feof

0044A860  |. |83C4 04       |add esp,0x4                                            ;  end of file 파라미터 1개

0044A863  |. |85C0          |test eax,eax                                           ;  patch 해야할까?

0044A865     |74 30         je short run_unpa.0044A897                              ;  얘를 je로 패치

0044A867  |. |E8 9467FBFF   |call run_unpa.00401000

0044A86C  |. |8B45 FC       |mov eax,[local.1]

0044A86F  |. |50            |push eax                                               ; /stream

0044A870  |. |FF15 B4C04400 |call near dword ptr [<&MSVCR100.fgetc>]                ; \getc

0044A876  |. |83C4 04       |add esp,0x4

0044A879  |. |8B4D F8       |mov ecx,[local.2]

0044A87C  |. |8881 B8155400 |mov byte ptr [ecx+0x5415B8],al

0044A882  |. |E8 7967FBFF   |call run_unpa.00401000





0044A8B4     /75 49         jnz short run_unpa.0044A8FF                             ;  jne 로 패치

0044A8B6  |. |8B55 F8       |mov edx,[local.2]

0044A8B9  |. |0FBE8A B81554>|movsx ecx,byte ptr [edx+0x5415B8]                      ;  구글링해보니 파일 암호화

0044A8C0  |. |8B45 F8       |mov eax,[local.2]

0044A8C3  |. |33D2          |xor edx,edx

0044A8C5  |. |F775 F4       |div [local.3]                                          ;  내가 입력한 키의 길이

0044A8C8  |. |0FBE92 70D344>|movsx edx,byte ptr [edx+0x44D370]                      ;  내가 입력한 키

0044A8CF  |. |33CA          |xor ecx,edx                                            ;  0x31

0044A8D1  |. |8B45 F8       |mov eax,[local.2]

0044A8D4  |. |8888 B8155400 |mov byte ptr [eax+0x5415B8],cl                         ;  eax+0x5415B8안에 31을 넣고

0044A8DA  |. |E8 2167FBFF   |call run_unpa.00401000                                 ;  쌩까고

0044A8DF  |. |8B4D F8       |mov ecx,[local.2]

0044A8E2  |. |0FBE91 B81554>|movsx edx,byte ptr [ecx+0x5415B8]

0044A8E9  |. |81F2 FF000000 |xor edx,0xFF                                           ;  0x31 ^ 0xff (0X31은 숫자 1)

0044A8EF  |. |8B45 F8       |mov eax,[local.2]

0044A8F2  |. |8890 B8155400 |mov byte ptr [eax+0x5415B8],dl                         ;  결과가 31에서 CE로 바꼇다

0044A8F8  |. |E8 0367FBFF   |call run_unpa.00401000

0044A8FD  |.^|EB A6         \jmp short run_unpa.0044A8A5


내가 입력한 key : 123(0x31,0x32,0x33)


현재 찾은것은 

key값 ^ 0xff = 0xCE 




패치 한 바이너리


0044A8A5  |> /8B45 F8       /mov eax,[local.2]                       ;  LOOP

0044A8A8  |. |83C0 01       |add eax,0x1

0044A8AB  |. |8945 F8       |mov [local.2],eax

0044A8AE  |> |8B4D F8        mov ecx,[local.2]

0044A8B1  |. |3B4D F0       |cmp ecx,[local.4]

0044A8B4  |. |75 49         |jnz short run_unpa.0044A8FF             ;  패치해야하니?;;;;

0044A8B6  |. |8B55 F8       |mov edx,[local.2]

0044A8B9  |. |0FBE8A B81554>|movsx ecx,byte ptr [edx+0x5415B8]

0044A8C0  |. |8B45 F8       |mov eax,[local.2]

0044A8C3  |. |33D2          |xor edx,edx

0044A8C5  |. |F775 F4       |div [local.3]

0044A8C8  |. |0FBE92 70D344>|movsx edx,byte ptr [edx+0x44D370]       ;  내가 입력한 key[i]

0044A8CF  |. |33CA          |xor ecx,edx                             ;  key[i] ^ 0   = key[i]

0044A8D1  |. |8B45 F8       |mov eax,[local.2]

0044A8D4  |. |8888 B8155400 |mov byte ptr [eax+0x5415B8],cl          ;  [eax+0x5415B8]은 암호화 된 파일같다?

0044A8DA  |. |E8 2167FBFF   |call run_unpa.00401000

0044A8DF  |. |8B4D F8       |mov ecx,[local.2]

0044A8E2  |. |0FBE91 B81554>|movsx edx,byte ptr [ecx+0x5415B8]

0044A8E9  |. |81F2 FF000000 |xor edx,0xFF                            ;  key[i] ^ 0xff

0044A8EF  |. |8B45 F8       |mov eax,[local.2]

0044A8F2  |. |8890 B8155400 |mov byte ptr [eax+0x5415B8],dl

0044A8F8  |. |E8 0367FBFF   |call run_unpa.00401000

0044A8FD  |.^\EB A6         \jmp short run_unpa.0044A8A5


재 패치한 바이너리 

놉....재 패치하면 첨 부터 CMP ECX, [local.4] 에서 0 과 0이므로 점프됨... 

그렇다면, 분석하면서 패치해야한다.(1라운드 돌고)



다시 바이너리 돌려서


내가 입력한 key : 123(0x31,0x32,0x33)


현재 찾은것은 (이 key값은 정답 key값이 아니므로 루틴만 이해하고 넘어가야 한다)

key값 ^ 0xff = 0xCE 

key값 ^ 0xff = 0xCD


파일의 시그니처는 무엇일까.. 


1) EXE


2) PNG. JPG


3) DOCX


4) HWP 등등... 이 있을텐데 파일 복호화 니까 

힌트에 Decrypt(EXE)라고 되어있었으니 2 3 4 다 재꾸자


EXE를 나타내는 설명 ? 

54 68 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 6D 6F 64 65


이게 나오게 한번 짜볼까? 

정상바이너리[i] ="54 68 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 6D 6F 64 65"


정상바이너리 OFFSET 4E ~ 73 




정상바이너리[i]="0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x63,0x61,0x6E,0x6E,0x6F,0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20,0x44,0x4F,0x53,0x20,0x6D,0x6F,0x64,0x65"


랜섬바이너리[i]= ?? 얼라 0바이트 ?????????? 아.... 암호못풀면 pe구조 다 깨지는구나... 


ㅜㅜ 새로 바이너리 받아서 다시 했다.


이제 워게임 랜섬웨어랄지라도 VMWARE에서 하자 



랜섬바이너리[i]= "C7 F2 E2 FF AF E3 EC E9 FB E5 FB E1 AC F0 FB E5 E2 E0 E7 BE E4 F9 B7 E8 F9 E2 B3 F3 E5 AC CB DC CD A6 F1 F8 FE E9"

 


랜섬바이너리[i]="0xC7,0xF2,0xE2,0xFF,0xAF,0xE3,0xEC,0xE9,0xFB,0xE5,0xFB,0xE1,0xAC,0xF0,0xFB,0xE5,0xE2,0xE0,0xE7,0xBE,0xE4,0xF9,0xB7,0xE8,0xF9,0xE2,0xB3,0xF3,0xE5,0xAC,0xCB,0xDC,0xCD,0xA6,0xF1,0xF8,0xFE,0xE9"


키 값의 길이는 ??? ???? ???? ?????? 

97 9A 8C 8C 93 9A 

8B 8C 8F 93 9E 86 9C  =?> 13자리 


그렇다면 key[14] = {0x97 9A 8C 8C 93 9A 8B 8C 8F 93 9E 86 9C}; // 이 안에 진짜배기가 들어가야함



#include <stdio.h>

#include <string.h>



int main(void)

{

char binary_original[38] = {0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x63,0x61,0x6E,0x6E,0x6F,0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20,0x44,0x4F,0x53,0x20,0x6D,0x6F,0x64,0x65};

char binary_ransome[38]={0xC7,0xF2,0xE2,0xFF,0xAF,0xE3,0xEC,0xE9,0xFB,0xE5,0xFB,0xE1,0xAC,0xF0,0xFB,0xE5,0xE2,0xE0,0xE7,0xBE,0xE4,0xF9,0xB7,0xE8,0xF9,0xE2,0xB3,0xF3,0xE5,0xAC,0xCB,0xDC,0xCD,0xA6,0xF1,0xF8,0xFE,0xE9};

// key value

// key strlen = 13 

char decrypt_key[14]={0x97,0x9A,0x8C,0x8C,0x93,0x9A,0x8B,0x8C,0x8F,0x93,0x9E,0x86,0x9C};

char real_key[14]={"\0"};

// rule of game 

// ransome[i] ^ ransome[i] ^ 0xff ^ key[i] => original[i]

// key를 구하려면 

// original[i] ^ ransome[i] ^ 0xff 

//printf("strlen = %d\n", sizeof(binary_ransome)/sizeof(binary_ransome[0]));

int i;


// C7이 54가 되어야 함. 그래야 올바른 EXE가 됨.


// 그렇다면, C7 ^ FF ^ ? = 54 

// ? = C7 ^ FF ^ 54 가 됨 

// 바이너리랜섬은 38개, 공개키(DECRYPT_KEY)는 14자리 

// 공개키를 2번 반복하고 10번 더 써야하네?

// 키젠 문제랑 거의 흡사 ? 

// ? = 6C 

// l (엘)

// 하나만 더 해보자


/*

char binary_original[38] = {0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x63,0x61,0x6E,0x6E,0x6F,0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20,0x44,0x4F,0x53,0x20,0x6D,0x6F,0x64,0x65};

char binary_ransome[38]={0xC7,0xF2,0xE2,0xFF,0xAF,0xE3,0xEC,0xE9,0xFB,0xE5,0xFB,0xE1,0xAC,0xF0,0xFB,0xE5,0xE2,0xE0,0xE7,0xBE,0xE4,0xF9,0xB7,0xE8,0xF9,0xE2,0xB3,0xF3,0xE5,0xAC,0xCB,0xDC,0xCD,0xA6,0xF1,0xF8,0xFE,0xE9};

// key value

// key strlen = 13 

char decrypt_key[14]={0x97,0x9A,0x8C,0x8C,0x93,0x9A,0x8B,0x8C,0x8F,0x93,0x9E,0x86,0x9C};  // 확실한 키가 아니므로 스킵

*/


// ? = F2 ^ FF ^ 68  = 65

// ? = e


// real rule = binary_ransome[i] ^ 0xff ^ binary_original[i] = key[i];

// 그럼 14개면 써먹으면 되네?

// 플래그 느낌이 온다.... le ... ^,^

printf("랜섬웨어 키 \n");

for(i=0; i<13; i++)

{

real_key[i] = binary_ransome[i] ^ 0xFF ^ binary_original[i];

printf("%c",real_key[i]);

}



}





'0x02 Reverse Engineer > 0x02. Reverse.kr' 카테고리의 다른 글

CRC1  (0) 2018.01.05
PEpasswd  (0) 2017.12.01
RansomeWare  (0) 2017.07.28
MusicPlayer  (0) 2017.07.28
EasyUnpackMe  (0) 2017.07.28
EasyKeygen  (0) 2017.07.28
0 Comments
댓글쓰기 폼