Smiscer - #2.실행압축해제.난독화B 에서 유효코드만을 골라 분석.
수행루틴은 크게 다음과 같다.
1. Kernel32.dll 핸들 찾기
2. GetProcAddress() API 주소 찾기
3. LoadLibrary, LocalAlloc 등 필요한 API 주소 가져오기
4. 동적 메모리 할당 후, 실행압축 되어 있는 원본 데이터를 복호화
5. 동적 메모리 할당 후, Unpack 루틴 복사
6. Unpack된 원본 파일을 실행중인 이미지에 덮어 쓰기
7. Unpack된 원본 파일의 EntryPoint로 JMP
;; 자신의 Handle, 즉 ImageBase 값을 지정한다.
3068045B B8 FFFF6630 MOV EAX, 3066FFFF
; EAX = 0x30670000 = hHandle
3068392E 40 INC EAX
30683B13 9C PUSHFD
30680CA5 60 PUSHAD
30683164 6A 00 PUSH 0
30681632 50 PUSH EAX
30683C90 60 PUSHAD
306843D6 8D7C24 20 LEA EDI, DWORD PTR SS:[ESP+20]
306820CE 50 PUSH EAX
30680571 51 PUSH ECX
30684653 52 PUSH EDX
30681911 56 PUSH ESI
30680C2D 57 PUSH EDI
30683834 55 PUSH EBP
30684478 FC CLD
;; PEB(Process Environment Block)을 이용하여 Kernel32.dll의 핸들을 찾는다.
; http://churack.tistory.com/entry/PEBProcess-Environment-Block을-이용하여-Kernel32dll-핸들-찾기
306815D2 B8 30000000 MOV EAX, 30
; FS:[0x30] = [7FFDF030] = 0x7FFD6000 = _TEB->ProcessEnviromentBlock;
30683352 64:8B00 MOV EAX, DWORD PTR FS:[EAX]
; DS:[7FFD600C] = 0x00251E90 = _PEB->LoaderData = 프로세스의 로드된 DLL 목록 저장
306830FD 8B40 0C MOV EAX, DWORD PTR DS:[EAX+C]
; DS:[0x00251EA4] =0x00251EC8 = _PEB_LDR_DATA.InMemoryOrderModuleList->Flink
30680A6C 8B40 14 MOV EAX, DWORD PTR DS:[EAX+14]
30683FB5 8BD0 MOV EDX, EAX
; DS:[0x00251EF0] = 0x000205FA = _LDR_MODULE->BaseDllName->Buffer = (UNICODE "zzz.exe")
30684794 8B72 28 MOV ESI, DWORD PTR DS:[EDX+28]
306805DD B9 18000000 MOV ECX, 18
30681E73 33FF XOR EDI, EDI
306814A0 33C0 XOR EAX, EAX
30681A0D AC LODS BYTE PTR DS:[ESI]
30682998 3C 61 CMP AL, 61
30680C11 /0F8C 81280000 JL zzz.30683498
30682DD4 2C 20 SUB AL, 20
30683498 C1CF 0D ROR EDI, 0D
30682F41 03F8 ADD EDI, EAX
306841C8 49 DEC ECX
30683E01 ^\0F85 99D6FFFF JNZ zzz.306814A0
; DS:[0x00251EE0] = _LDR_MODULE->SizeOfImage : 0x00050000
3068095D 8B42 18 MOV EAX, DWORD PTR DS:[EDX+18]
30683DB9 81F7 0918F562 XOR EDI, 62F51809
; Kernel32.dll 인지 확인
30684119 81FF 52A4BF08 CMP EDI, 8BFA452
; DS:[0x00251ED8] = 0x30670000 = _LDR_MODULE->BaseAddress
30680778 8B5A 10 MOV EBX, DWORD PTR DS:[EDX+10]
; DS:[0x00251EC8] = 0x00251F20
; 만약 Kernel32.dll이 아닐 경우 Flink를 따라간다.
30682A89 8B12 MOV EDX, DWORD PTR DS:[EDX]
30684460 /0F85 2E030000 JNZ zzz.30684794
;; kernel32.dll의 로드된 이미지에서 Export 테이블을 검색하여 GetProcAddress() 주소를 찾는다.
; EBX = 0x7C800000 = kernel32.handle
3068314C 8B73 3C MOV ESI, DWORD PTR DS:[EBX+3C]
; ESI = 0x0000262C = IMAGE_OPTIONAL_HEADER.DirectoryTable[ExportTable].RVA
30684162 8B741E 78 MOV ESI, DWORD PTR DS:[ESI+EBX+78]
; ESI = 0x7C80262C = ExportTableVA
30683388 03F3 ADD ESI, EBX
; ECX = 0x00000001 = IMAGE_EXPORT_DIRECTORY.OrdinalBase
3068376A 8B4E 10 MOV ECX, DWORD PTR DS:[ESI+10]
; EDI = 0x00002654 = IMAGE_EXPORT_DIRECTORY.AddressTableRVA
30682526 8B7E 1C MOV EDI, DWORD PTR DS:[ESI+1C]
; EBP = 0x0000441C = IMAGE_EXPORT_DIRECTORY.OrdinalTableRVA
30681321 8B6E 24 MOV EBP, DWORD PTR DS:[ESI+24]
; ESI = 0x00003538 = IMAGE_EXPORT_DIRECTORY.NamePointerTableRVA
30684243 8B76 20 MOV ESI, DWORD PTR DS:[ESI+20]
30681863 03F3 ADD ESI, EBX
3068087F 03FB ADD EDI, EBX
306846B9 03EB ADD EBP, EBX
30684608 56 PUSH ESI
306827D5 33D2 XOR EDX, EDX
30681C26 F7D2 NOT EDX
3068281E 42 INC EDX
30684198 5E POP ESI
30682B38 56 PUSH ESI
; ESI = ExportNamePointerTable
30682EC3 8B3496 MOV ESI, DWORD PTR DS:[ESI+EDX*4]
30681F9B 03F3 ADD ESI, EBX
306816B4 8B06 MOV EAX, DWORD PTR DS:[ESI]
30683CAB 35 AC220E6B XOR EAX, 6B0E22AC
; ExportName이 GetProcAddress 인지 확인.
30682572 3D EB477A3B CMP EAX, 3B7A47EB
30682D58 ^\0F85 C0FAFFFF JNZ zzz.3068281E
306826D9 83C6 04 ADD ESI, 4
306818AB F706 8D909CBE TEST DWORD PTR DS:[ESI], BE9C908D
30683266 ^\0F85 B2F5FFFF JNZ zzz.3068281E
30683E49 D1E2 SHL EDX, 1
30680B7D 0FB7042A MOVZX EAX, WORD PTR DS:[EDX+EBP]
3068219C 8B0487 MOV EAX, DWORD PTR DS:[EDI+EAX*4]
; EAX = Kernel32.GetProcAddress
30682918 03C3 ADD EAX, EBX
30680E2F 5E POP ESI
30680F72 5D POP EBP
30682003 5F POP EDI
3068153B 5E POP ESI
30683B8E 5A POP EDX
30683CDD 59 POP ECX
306822D2 59 POP ECX
306833BB 8947 E4 MOV DWORD PTR DS:[EDI-1C], EAX
30681D48 8D6F E0 LEA EBP, DWORD PTR DS:[EDI-20]
30681B62 6A 00 PUSH 0
;; GetProcAddress(kernel32.dll, "LoadLibrary")
30682428 B9 9E8D86BE MOV ECX, BE868D9E
3068050B 51 PUSH ECX
30680DFF F71424 NOT DWORD PTR SS:[ESP]
30682838 B9 4C696272 MOV ECX, 7262694C
306819D8 51 PUSH ECX
3068265D B9 B3909E9B MOV ECX, 9B9E90B3
306825A2 51 PUSH ECX
306832CC F71424 NOT DWORD PTR SS:[ESP]
306818F8 54 PUSH ESP
306809F1 53 PUSH EBX
; kernel32.GetProcAddress()
30682AA1 FF55 04 CALL DWORD PTR SS:[EBP+4]
; Stack DS:[0x0012FC90] = kernel32.LoadLibraryA
30681E8C 8947 E0 MOV DWORD PTR DS:[EDI-20], EAX
30683467 83C4 10 ADD ESP, 10
;; GetProcAddress(kernel32.dll, "VirtualProtect")
30682D8B B9 9C8BFFFF MOV ECX, FFFF8B9C
30681B93 51 PUSH ECX
306805C5 F71424 NOT DWORD PTR SS:[ESP]
30682BA2 B9 EF8F2419 MOV ECX, 19248FEF
30680B47 51 PUSH ECX
30681CC1 B8 9DE0507C MOV EAX, 7C50E09D
3068474B 310424 XOR DWORD PTR SS:[ESP], EAX
30681043 B9 E8813C2C MOV ECX, 2C3C81E8
3068357D 51 PUSH ECX
306821E6 310424 XOR DWORD PTR SS:[ESP], EAX
30683E91 B9 CB892257 MOV ECX, 572289CB
30683F09 51 PUSH ECX
3068289B B8 9DE05023 MOV EAX, 2350E09D
306829C8 310424 XOR DWORD PTR SS:[ESP], EAX
306828E4 54 PUSH ESP
30680FDC 53 PUSH EBX
; kernel32.GetProcAddress()
30682AF0 FF55 04 CALL DWORD PTR SS:[EBP+4]
; Stack DS:[0x0012FC98] = kernel32.VirtualProtect
30681815 8947 E8 MOV DWORD PTR DS:[EDI-18], EAX
306836BC 57 PUSH EDI
3068428B 54 PUSH ESP
; kernel32.LoadLibraryA()
30681746 FF57 E0 CALL DWORD PTR DS:[EDI-20]
30680D21 59 POP ECX
30681EA4 85C0 TEST EAX, EAX
306833D4 ^\0F84 99FBFFFF JE zzz.30682F73
;; GetProcAddress(kernel32.dll, "LocalAlloc")
30682F73 83C4 10 ADD ESP, 10
306840D0 B9 6F630000 MOV ECX, 636F
30682DF2 51 PUSH ECX
30681357 B9 F4AC3F33 MOV ECX, 333FACF4
30681E5B 81F1 98ED535F XOR ECX, 5F53ED98
30684421 51 PUSH ECX
30681A92 B9 76895D0E MOV ECX, 0E5D8976
3068248B 51 PUSH ECX
3068297F B8 3AE63E6F MOV EAX, 6F3EE63A
30681A3F 310424 XOR DWORD PTR SS:[ESP], EAX
30683C22 54 PUSH ESP
30682CAD 53 PUSH EBX
; kernel32.GetProcAddress
30680F42 FF55 04 CALL DWORD PTR SS:[EBP+4]
; Stack DS:[0x0012FC9C] = kernel32.Alloc
30682C26 8947 EC MOV DWORD PTR DS:[EDI-14], EAX
3068378A 83C4 0C ADD ESP, 0C
;; GetProcAddress(kernel32.dll, "LocalFree")
30681C6E B9 65000000 MOV ECX, 65
30682410 51 PUSH ECX
30684703 B9 45F3216B MOV ECX, 6B21F345
30683BDA 51 PUSH ECX
3068063F B8 29B5530E MOV EAX, 0E53B529
30684409 310424 XOR DWORD PTR SS:[ESP], EAX
30683C0A B9 65DA306F MOV ECX, 6F30DA65
30683564 51 PUSH ECX
306808F9 310424 XOR DWORD PTR SS:[ESP], EAX
30680DCD 54 PUSH ESP
30682BBB 53 PUSH EBX
; kernel32.GetProcAddress
30683EF1 FF55 04 CALL DWORD PTR SS:[EBP+4]
; Stack DS:[0x0012FCA0] = kernel32.LocalFree
306811D8 8947 F0 MOV DWORD PTR DS:[EDI-10], EAX
30682FA5 83C4 0C ADD ESP, 0C
;; LoadLibraryA("expsrv.dll")
30680E47 6A 00 PUSH 0
306837A2 68 6C6C0000 PUSH 6C6C
306812A5 68 72762E64 PUSH 642E7672
30680473 68 65787073 PUSH 73707865
30681126 54 PUSH ESP
; kernel32.LoadLibraryA(expsrv.dll) = 0x0F9C0000
306806A3 FF57 E0 CALL DWORD PTR DS:[EDI-20]
30681C0E 83C4 10 ADD ESP, 10
306842A3 81EC 00020000 SUB ESP, 200
3068456F 56 PUSH ESI
30683946 57 PUSH EDI
30682F5B 53 PUSH EBX
30681C56 8BD8 MOV EBX, EAX
306842F1 46 INC ESI
306839AD 8B83 6E600000 MOV EAX, DWORD PTR DS:[EBX+606E]
306823F6 0383 635B0000 ADD EAX, DWORD PTR DS:[EBX+5B63]
30681F51 /0F84 1D430100 JE zzz.30696274
306844AB 5B POP EBX
306836EC 5F POP EDI
30682357 5E POP ESI
306817FB 81C4 00020000 ADD ESP, 200
;; LocalAlloc( LMEM_ZEROINIT, 0x3EB2E) = 0x00155938 : 내부에 암호화되어 저장된 PE 파일 복호화
30682806 68 00300300 PUSH 33000
306807E0 8BEC MOV EBP, ESP
306841E0 B8 B2020000 MOV EAX, 2B2
30681B7B 8945 28 MOV DWORD PTR SS:[EBP+28], EAX
30682868 68 2EEB0300 PUSH 3EB2E
30681D61 6A 40 PUSH 40
; kernel32.LocalAlloc
306829B0 FF55 10 CALL DWORD PTR SS:[EBP+10]
30681716 50 PUSH EAX
;; 0x30671F00에서 0x1494 Size 만큼 복호화 하여 0x00155938에 저장
30680673 8B75 24 MOV ESI, DWORD PTR SS:[EBP+24]
; ESI = 0x30671F00
306807C8 81C6 001F0000 ADD ESI, 1F00
3068294B 8BF8 MOV EDI, EAX
306844C3 B9 94140000 MOV ECX, 1494
30681553 33C0 XOR EAX, EAX
306822EA 85C9 TEST ECX, ECX
30683009 ^\0F84 6FE6FFFF JE zzz.3068167E
30680D53 AC LODS BYTE PTR DS:[ESI]
30683B5E AA STOS BYTE PTR ES:[EDI]
3068306C 49 DEC ECX
3068381C ^\0F84 5CDEFFFF JE zzz.3068167E
30682C07 51 PUSH ECX
306831B8 8BD0 MOV EDX, EAX
306808E1 80E2 33 AND DL, 33
306837D2 ^\0F85 88E2FFFF JNZ zzz.30681A60
306830CC 46 INC ESI
30681E42 46 INC ESI
3068425B 46 INC ESI
30682CDE FF0C24 DEC DWORD PTR SS:[ESP]
30681B14 FF0C24 DEC DWORD PTR SS:[ESP]
30683A68 FF0C24 DEC DWORD PTR SS:[ESP]
30682C95 /E9 7C0C0000 JMP zzz.30683916
30681A60 90 NOP
306847DF 50 PUSH EAX
30684321 5A POP EDX
30682472 80E2 0A AND DL, 0A
306808AF /0F85 61300000 JNZ zzz.30683916
30683916 59 POP ECX
306806BE /E9 271C0000 JMP zzz.306822EA
;; 0x30673455에서 0x22D16 Size 만큼 복호화 하여 0x00156AC3에 저장
; 0x30673394 + 0xC1 = 0x30673455
3068167E 81C6 C1000000 ADD ESI, 0C1
30683D56 33DB XOR EBX, EBX
3068233D B9 162D0200 MOV ECX, 22D16
30680B15 33C0 XOR EAX, EAX
30683116 85C9 TEST ECX, ECX
306844F4 ^\0F84 47FFFFFF JE zzz.30684441
3068105B AC LODS BYTE PTR DS:[ESI]
306809BE AA STOS BYTE PTR ES:[EDI]
306815EA 43 INC EBX
306824A8 A8 02 TEST AL, 2
3068192A /0F85 A41D0000 JNZ zzz.306836D4
306826A5 ^\E9 FCE2FFFF JMP zzz.306809A6
306836D4 81FB 00D00000 CMP EBX, 0D000
30683DE9 ^\0F82 B7CBFFFF JB zzz.306809A6
3068182E 33D2 XOR EDX, EDX
30680BE1 3955 28 CMP DWORD PTR SS:[EBP+28], EDX
30680811 /0F84 8F010000 JE zzz.306809A6
30683CF6 FF4D 28 DEC DWORD PTR SS:[EBP+28]
30682850 83C6 17 ADD ESI, 17
30683BA7 83E9 17 SUB ECX, 17
306809A6 49 DEC ECX
306843A5 /0F84 96000000 JE zzz.30684441
306845B8 51 PUSH ECX
30683A10 8BD0 MOV EDX, EAX
30684526 80E2 33 AND DL, 33
30682E91 /0F85 17190000 JNZ zzz.306847AE
306821B5 46 INC ESI
30682100 46 INC ESI
30682C78 46 INC ESI
306824DA 83C3 03 ADD EBX, 3
30682882 FF0C24 DEC DWORD PTR SS:[ESP]
3068128B FF0C24 DEC DWORD PTR SS:[ESP]
306805F6 FF0C24 DEC DWORD PTR SS:[ESP]
306847C7 ^\E9 ADDBFFFF JMP zzz.30682379
306847AE 8BD0 MOV EDX, EAX
30682379 59 POP ECX
3068336B ^\E9 A6FDFFFF JMP zzz.30683116
;; 0x306A5D98에서 0x00018CE8 Size 만큼 0x00170C50에 복사
30684441 BE 985D0300 MOV ESI, 35D98
30684684 0375 24 ADD ESI, DWORD PTR SS:[EBP+24]
306842BE B9 E88C0100 MOV ECX, 18CE8
306804D8 F3:A4 REP MOVS BYTE PTR ES:[EDI], BYTE PTR>
;; LocalAlloc(LMEM_ZEROINIT, 0x00034004) = 0x00194470
306842D6 58 POP EAX
30681DDE 8BF0 MOV ESI, EAX
30680FC3 BB 04400300 MOV EBX, 34004
30680866 53 PUSH EBX
30682E73 6A 40 PUSH 40
; kernel32.LocalAlloc
30680897 FF55 10 CALL DWORD PTR SS:[EBP+10]
;; 0x00155938 -> 0x00194470 으로 0x00034004 만큼 복사
306816E5 8BCB MOV ECX, EBX
30682A10 60 PUSHAD
30681223 8BF8 MOV EDI, EAX
3068409C F3:A4 REP MOVS BYTE PTR ES:[EDI], BYTE PTR>
3068389A 61 POPAD
;; LocalFree(0x00155938)
30680975 93 XCHG EAX, EBX
30683232 50 PUSH EAX
30682440 56 PUSH ESI
; kernel32.LocalFree
30681388 FF55 14 CALL DWORD PTR SS:[EBP+14]
;; PE 파일에 대한 전체 복호화
30681FE7 59 POP ECX
30682184 8BF3 MOV ESI, EBX
3068048F 8BFE MOV EDI, ESI
30682152 C1E9 02 SHR ECX, 2
30680B95 B8 37000000 MOV EAX, 37
306834CC 85C0 TEST EAX, EAX
306831D2 ^\0F84 BADCFFFF JE zzz.30680E92
30681273 8BC0 MOV EAX, EAX
306839DF 50 PUSH EAX
306807F8 51 PUSH ECX
3068209E 56 PUSH ESI
306840B5 57 PUSH EDI
3068463A AD LODS DWORD PTR DS:[ESI]
30682FD9 2BC1 SUB EAX, ECX
3068347F 35 9621EF93 XOR EAX, 93EF2196
30680F8A C1C8 19 ROR EAX, 19
30681426 AB STOS DWORD PTR ES:[EDI]
30683FEC 49 DEC ECX
30681BDE /0F85 562A0000 JNZ zzz.3068463A
306841F9 5F POP EDI
306826C1 5E POP ESI
30682288 59 POP ECX
3068175E 58 POP EAX
30680EC3 49 DEC ECX
306825C0 83C6 04 ADD ESI, 4
30683021 8BFE MOV EDI, ESI
30681E29 8BC0 MOV EAX, EAX
3068156E 48 DEC EAX
30681156 /0F85 83280000 JNZ zzz.306839DF
;; VirtualProtect(0x30670000, 0x36000, PAGE_EXECUTE_READWRITE, &)
;; 원본 실행 이미지에 복호화 한 PE로 덮어 쓰기 위하여 이미지의 메모리에 대한 권한을 PAGE_EXECUTE_READWRITE로 변환한다.
30680E92 8BC3 MOV EAX, EBX
30681CF2 0340 3C ADD EAX, DWORD PTR DS:[EAX+3C]
306804A7 8BD0 MOV EDX, EAX
30684101 8D4D 28 LEA ECX, DWORD PTR SS:[EBP+28]
30682E3B 51 PUSH ECX
; PAGE_EXECUTE_READWRITE
30681972 6A 40 PUSH 40
; SizeOfImage -> 0x00036000
3068102B FF72 50 PUSH DWORD PTR DS:[EDX+50]
; zzz.30670000
3068270E FF75 24 PUSH DWORD PTR SS:[EBP+24]
; kernel32.VirtualProtect
3068453E FF55 0C CALL DWORD PTR SS:[EBP+C]
;; LocalAlloc(LMEM_ZEROINIT, 0x33000) = 0x00155938
;; 현재 실행 되는 이미지를 새로 생성한 메모리영역에 복사한다.
3068053B 60 PUSHAD
30681075 035B 3C ADD EBX, DWORD PTR DS:[EBX+3C]
30684273 FF75 00 PUSH DWORD PTR SS:[EBP]
30684080 6A 40 PUSH 40
; kernel32.LocalAlloc
30684180 FF55 10 CALL DWORD PTR SS:[EBP+10]
30682BEE 50 PUSH EAX
;; VirtualProtect(0x00155938, 0x33000, PAGE_EXECUTE_READWRITE, &)
;; 코드 실행을 위하여 생성한 메모리영역을 PAGE_EXECUTE_READWRITE로 설정한다.
306845D3 8D4D 28 LEA ECX, DWORD PTR SS:[EBP+28]
30682F24 51 PUSH ECX
30683F21 6A 40 PUSH 40
30680EAA FF75 00 PUSH DWORD PTR SS:[EBP]
3068198A 50 PUSH EAX
; kernel32.VirtualProtect
30680FF8 FF55 0C CALL DWORD PTR SS:[EBP+C]
306821FE 58 POP EAX
;; EntryPoint(0x306733A1)에서 0x33000 크기 만큼 0x00155938로 복사
; ESI = 0x30670000
306829F8 8B75 24 MOV ESI, DWORD PTR SS:[EBP+24]
306846EA 56 PUSH ESI
30683198 8B4E 3C MOV ECX, DWORD PTR DS:[ESI+3C]
; 0x306700A8->AddressOfEntryPoint = 0x306733A1
30682D3F 037431 28 ADD ESI, DWORD PTR DS:[ECX+ESI+28]
30681DC6 8BF8 MOV EDI, EAX
3068352D 57 PUSH EDI
306835FB 8B4D 00 MOV ECX, DWORD PTR SS:[EBP]
30681F08 F3:A4 REP MOVS BYTE PTR ES:[EDI], BYTE PTR>
306843EF 5F POP EDI
30680D08 5E POP ESI
;; 실행 이미지를 덮어쓰는 작업을 새로 생성한 메모리영역으로 이동하여 수행한다.
;; 그렇지 않고 계속 현재 이미지 영역내에서 수행할 경우…. Error!!
306831EA E8 6BF3FFFF CALL zzz.3068255A
; zzz.306831EF -> 자신이 실행시킬 다음 코드를 가져온다.
3068255A 8B0424 MOV EAX, DWORD PTR SS:[ESP]
; zzz.30670000 -> RVA값을 구한다.
306834E4 2B45 24 SUB EAX, DWORD PTR SS:[EBP+24]
; 0x00155938 에서 현재 RVA값을 구하고.
30683B76 03C7 ADD EAX, EDI
306832B2 8B4E 3C MOV ECX, DWORD PTR DS:[ESI+3C]
; AddressOfEntryPoint 값을 빼면.
30680C8D 2B4431 28 SUB EAX, DWORD PTR DS:[ECX+ESI+28]
; 나오는 위치로 JMP, 0x00165786
30681E11 890424 MOV DWORD PTR SS:[ESP], EAX
306834B3 C3 RETN
;; Unpack한 이미지를 원본 실행 이미지에 덮어 쓰는 작업
00163C33 87C9 XCHG ECX, ECX
00163624 897D 28 MOV DWORD PTR SS:[EBP+28], EDI
001648BC 61 POPAD
00165830 60 PUSHAD
00166031 68 00000000 PUSH 0
00166B83 5E POP ESI
00162F6F 68 00000000 PUSH 0
00164D20 5F POP EDI
00162FB8 85F6 TEST ESI, ESI
001636A5 /E9 AE130000 JMP 00164A58
00164A58 61 POPAD
001640C8 53 PUSH EBX
001651D6 8BF3 MOV ESI, EBX
00164FD8 8BCB MOV ECX, EBX
; DS:[0x00194470+0x3C] = DS:[0x001944AC] = 0x000000E8 -> PE Header
00165E7B 0349 3C ADD ECX, DWORD PTR DS:[ECX+3C]
00163064 51 PUSH ECX
; EAX = SizeOfOptionalHeader = 0x00E0
00164090 0FBF41 14 MOVSX EAX, WORD PTR DS:[ECX+14]
00164073 83C0 18 ADD EAX, 18
; ECX = SizeOfHeader = 0x00000400
001630F6 8B49 54 MOV ECX, DWORD PTR DS:[ECX+54]
00164C24 8B7D 24 MOV EDI, DWORD PTR SS:[EBP+24]
00164B8D 60 PUSHAD
;; LocalAlloc(LMEM_ZEROINIT, 0x500) = 0x00188940
001666C8 68 00050000 PUSH 500
00165F14 6A 40 PUSH 40
; kernel32.LocalAlloc
00166305 FF55 10 CALL DWORD PTR SS:[EBP+10]
00163C94 8945 18 MOV DWORD PTR SS:[EBP+18], EAX
;; 0x30670000 에서 0x400크기만큼 0x00188940으로 복사
;; 현재 실행 이미지의 PE 헤더에 대한 정보를 백업해 둔다.
00163BB1 8BF8 MOV EDI, EAX
0016423E B9 00010000 MOV ECX, 100
00163D79 8B75 24 MOV ESI, DWORD PTR SS:[EBP+24]
00164928 F3:A5 REP MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
001664D0 61 POPAD
;; 헤더 부분 복사(IMAGE_DOS_HEADER, IMAGE_NT_HEADERS, IMAGE_SECTION_HEADERS)
00165D9B 60 PUSHAD
00164CD6 8BC1 MOV EAX, ECX
; SectionAlignment에 맞게 사이즈 구하기
001632D2 E8 2E150000 CALL 00164805
00164805 60 PUSHAD
00162EC0 8BCB MOV ECX, EBX : ECX = 0x00194470
00166338 0349 3C ADD ECX, DWORD PTR DS:[ECX+3C]
; ECX = 0x00001000 = SectionAlignment
00163D2B 8B49 38 MOV ECX, DWORD PTR DS:[ECX+38]
00165C3B ^\E9 F7DEFFFF JMP 00163B37
00163B37 33D2 XOR EDX, EDX
00166018 F7F1 DIV ECX
00162ABA 85D2 TEST EDX, EDX
00165472 ^\0F84 47D8FFFF JE 00162CBF
001645CD 40 INC EAX
00162CBF F7E9 IMUL ECX
00165F8F 894424 1C MOV DWORD PTR SS:[ESP+1C], EAX
001649F0 61 POPAD
00165B45 C3 RETN
00165BDA 8BC8 MOV ECX, EAX
00164BC2 33C0 XOR EAX, EAX
001641D5 C1E9 02 SHR ECX, 2
00164B75 F3:AB REP STOS DWORD PTR ES:[EDI]
001645FD 61 POPAD
; 0x00194470 에서 0x3067000 으로 0x400 크기만큼 복사
001646AF F3:A4 REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
001647B5 59 POP ECX
;; 각 섹션 복사
; EDX = 0x0004 = NumberOfSections
00162B24 0FBF51 06 MOVSX EDX, WORD PTR DS:[ECX+6]
00165441 03C8 ADD ECX, EAX
0016625A 8BF2 MOV ESI, EDX
00163A6D C1E6 03 SHL ESI, 3
00163334 C1E2 05 SHL EDX, 5
00163989 8D1432 LEA EDX, DWORD PTR DS:[EDX+ESI]
0016304C 03D1 ADD EDX, ECX
; SectionHeader->PointerToRawData
00164BDA 8B71 14 MOV ESI, DWORD PTR DS:[ECX+14]
00165AE2 50 PUSH EAX
00164C88 51 PUSH ECX
001642AB 52 PUSH EDX
00162EA8 8BC6 MOV EAX, ESI
0016495D 8BCB MOV ECX, EBX
001650EB 0349 3C ADD ECX, DWORD PTR DS:[ECX+3C]
; ECX = 0x200 = FileAlignment
00162CD9 8B49 3C MOV ECX, DWORD PTR DS:[ECX+3C]
00165555 33D2 XOR EDX, EDX
; EAX = PointerToRawData / FileAlignment
0016315F F7F1 DIV ECX
00163287 0FAFC8 IMUL ECX, EAX
00166470 56 PUSH ESI
0016334C 59 POP ECX
0016548A 5A POP EDX
00165A93 59 POP ECX
00162D27 58 POP EAX
; ESI = 0x00194470 + 0x400 = 0x00194870 = Section Start
00166564 03F3 ADD ESI, EBX
; EDI = 0x00001000 = Section RVA
00163675 8B79 0C MOV EDI, DWORD PTR DS:[ECX+C]
; 0x30670000 + 0x1000 = 0x30671000 = Section Start
00163D43 037D 24 ADD EDI, DWORD PTR SS:[EBP+24]
0016467E 56 PUSH ESI
00165BF3 57 PUSH EDI
001644D0 51 PUSH ECX
; SectionHeader->VirtualSize
001657B1 8B41 08 MOV EAX, DWORD PTR DS:[ECX+8]
; SectionAlignment에 맞게 사이즈 구하기
00164AA2 E8 5EFDFFFF CALL 00164805
00164AD9 8BC8 MOV ECX, EAX
0016593D 9C PUSHFD
0016451A 33C0 XOR EAX, EAX
; Section Data 0으로 초기화
00165FC4 F3:AB REP STOS DWORD PTR ES:[EDI]
0016389C 59 POP ECX
00163CC5 5F POP EDI
00166680 5E POP ESI
; EAX = 0x7000 = SectionHeader->SizeOfRawData
0016438E 8B41 10 MOV EAX, DWORD PTR DS:[ECX+10]
; FileAlignment에 맞게 크기 구함
00164D38 E8 A40A0000 CALL 001657E1
001657E1 60 PUSHAD
0016418D 8BCB MOV ECX, EBX
00164502 034B 3C ADD ECX, DWORD PTR DS:[EBX+3C]
; ECX = 0x200 = FileAlignment
001644B7 8B49 3C MOV ECX, DWORD PTR DS:[ECX+3C]
00163B37 33D2 XOR EDX, EDX
00166018 F7F1 DIV ECX
00162ABA 85D2 TEST EDX, EDX
00165472 ^\0F84 47D8FFFF JE 00162CBF
001645CD 40 INC EAX
00162CBF F7E9 IMUL ECX
00165F8F 894424 1C MOV DWORD PTR SS:[ESP+1C], EAX
001649F0 61 POPAD
00165B45 C3 RETN
0016607A 51 PUSH ECX
001668D0 8BC8 MOV ECX, EAX
00166458 85C9 TEST ECX, ECX
00164F77 /0F85 E50E0000 JNZ 00165E62
; 복사를 위하여 사이즈를 4로 나눔
00165E62 C1E9 02 SHR ECX, 2
; Section 내용 복사
001662BD F3:A5 REP MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
00164221 59 POP ECX
; 다음 섹션
00165E95 83C1 28 ADD ECX, 28
00165E49 3BCA CMP ECX, EDX
00165BC2 ^\0F85 12F0FFFF JNZ 00164BDA
00166189 E8 FFD4FFFF CALL 0016368D
0016368D 60 PUSHAD
00166519 8BF3 MOV ESI, EBX
0016599B 0376 3C ADD ESI, DWORD PTR DS:[ESI+3C]
; ESI = 0x0019458C = 0x30670000 = ImageBase
00163DE2 8B7E 34 MOV EDI, DWORD PTR DS:[ESI+34]
00162CF1 3B7D 24 CMP EDI, DWORD PTR SS:[EBP+24]
00162ED8 /0F84 12210000 JE 00164FF0
00164FF0 61 POPAD
001646D0 C3 RETN
;; Import Address Table 세팅
0016618E 9C PUSHFD
00166BB9 8B75 24 MOV ESI, DWORD PTR SS:[EBP+24]
00165588 0376 3C ADD ESI, DWORD PTR DS:[ESI+3C]
; DirectoryTable[ImportTableRVA]
00163AA2 8BB6 80000000 MOV ESI, DWORD PTR DS:[ESI+80]
00164E63 85F6 TEST ESI, ESI
00163190 ^\0F84 8CFAFFFF JE 00162C22
; 0x30670000 + 0x00032F4C = ImportTableVA
00165309 0375 24 ADD ESI, DWORD PTR SS:[EBP+24]
; [ESI+10] = ImportDirectoryTable->ImportAddressTableRVA = 0x000080DC
00165799 837E 10 00 CMP DWORD PTR DS:[ESI+10], 0
00163757 ^\0F84 C5F4FFFF JE 00162C22
001647EC 56 PUSH ESI
; EBX = 0x0003392C = ImportDirectoryTable->NameRVA
001665E6 8B5E 0C MOV EBX, DWORD PTR DS:[ESI+C]
; EBX = 0x306A392C = "ntdll.dll"
00163C63 035D 24 ADD EBX, DWORD PTR SS:[EBP+24]
; EDI = [0x306A2F5C] = 0x80DC = ImportDirectoryTable->ImportAddressTableRVA
00163787 8B7E 10 MOV EDI, DWORD PTR DS:[ESI+10]
0016415C 037D 24 ADD EDI, DWORD PTR SS:[EBP+24]
001653A1 833E 00 CMP DWORD PTR DS:[ESI], 0
; ImportDirectoryTable->ImportNameTableRVA가 0인지 확인하여...
00166D8E ^\0F84 B3F9FFFF JE 00166747
; ESI = [0x306A2F4C] = 0x000330B4 = ImportDirectoryTable->ImportNameTableRVA
00166A72 8B36 MOV ESI, DWORD PTR DS:[ESI]
00163B99 0375 24 ADD ESI, DWORD PTR SS:[EBP+24]
00166DBF ^\E9 26E6FFFF JMP 001653EA
00166747 8BF7 MOV ESI, EDI
001653EA 53 PUSH EBX
; kernel32.LoadLibraryA
00164144 FF55 04 CALL DWORD PTR SS:[EBP+4]
; ntdll.7C930000
001667A8 8BD8 MOV EBX, EAX
; DS:[ESI] = [0x306A30B4] = 0x000336A8 = ImportNameTable
00166DD9 AD LODS DWORD PTR DS:[ESI]
; Ordinal 일 경우
00166CFA A9 00000080 TEST EAX, 80000000
001665FF ^\0F85 E0DFFFFF JNZ 001645E5
00162D41 0345 24 ADD EAX, DWORD PTR SS:[EBP+24]
; ImportName
00164EC9 83C0 02 ADD EAX, 2
00165069 ^\E9 08E4FFFF JMP 00163476
001645E5 2D 00000080 SUB EAX, 80000000
00163476 50 PUSH EAX
0016386C 53 PUSH EBX
; kernel32.GetProcAddress()
001651F2 FF55 08 CALL DWORD PTR SS:[EBP+8]
; Function Address 저장
00164345 AB STOS DWORD PTR ES:[EDI]
00163A05 F707 FFFFFFFF TEST DWORD PTR DS:[EDI], FFFFFFFF
00164487 /0F85 4C290000 JNZ 00166DD9
001655D0 5E POP ESI
; 다음 ImportDirectoryTable
00162A8A 83C6 14 ADD ESI, 14
001663C8 ^\E9 CCF3FFFF JMP 00165799
;; PE 헤더 보정
00162C22 8B7D 24 MOV EDI, DWORD PTR SS:[EBP+24]
001655E8 037F 3C ADD EDI, DWORD PTR DS:[EDI+3C]
; EDI = 0x000016EA = AddressOfEntryPoint
00164566 8B7F 28 MOV EDI, DWORD PTR DS:[EDI+28]
0016561B 037D 24 ADD EDI, DWORD PTR SS:[EBP+24]
0016393A 5E POP ESI
001634F1 60 PUSHAD
; ESI = 0x00188940
00165F5C 8B75 18 MOV ESI, DWORD PTR SS:[EBP+18]
00163FBE 8B7D 24 MOV EDI, DWORD PTR SS:[EBP+24]
00162FD1 0376 3C ADD ESI, DWORD PTR DS:[ESI+3C]
00166CCA 037F 3C ADD EDI, DWORD PTR DS:[EDI+3C]
; IMAGE_FILE_HEADER->Characteristics
00163E12 66:8B4E 16 MOV CX, WORD PTR DS:[ESI+16]
00164453 66:894F 16 MOV WORD PTR DS:[EDI+16], CX
00166C33 61 POPAD
00163ED9 60 PUSHAD
00165CCE 8B4D 24 MOV ECX, DWORD PTR SS:[EBP+24]
00163854 8B41 3C MOV EAX, DWORD PTR DS:[ECX+3C]
; PeHeader->CheckSum
001654A2 8D4401 58 LEA EAX, DWORD PTR DS:[ECX+EAX+58]
001640E0 C700 28000000 MOV DWORD PTR DS:[EAX], 28
00163EF1 64:A1 30000000 MOV EAX, DWORD PTR FS:[30]
00166368 8B40 0C MOV EAX, DWORD PTR DS:[EAX+C]
001660DC 8B40 14 MOV EAX, DWORD PTR DS:[EAX+14]
001639A1 52 PUSH EDX
001666E0 5A POP EDX
00165B7A 50 PUSH EAX
00164D50 3948 10 CMP DWORD PTR DS:[EAX+10], ECX
00166AED 8B00 MOV EAX, DWORD PTR DS:[EAX]
00164E94 /0F85 46180000 JNZ 001666E0
00163ABA 58 POP EAX
0016446E 8BD1 MOV EDX, ECX
;; Unpack한 이미지의 AddressOfEntryPoint로 JMP
; EDX = 0x306700E8
001667C1 0352 3C ADD EDX, DWORD PTR DS:[EDX+3C]
; ECX = 0x000016EA = AddressOfEntryPoint
00166157 034A 28 ADD ECX, DWORD PTR DS:[EDX+28]
001665B3 8948 14 MOV DWORD PTR DS:[EAX+14], ECX
00164041 61 POPAD
001637F1 8B45 14 MOV EAX, DWORD PTR SS:[EBP+14]
00163033 894424 44 MOV DWORD PTR SS:[ESP+44], EAX
00165CB4 8B45 28 MOV EAX, DWORD PTR SS:[EBP+28]
00166092 894424 40 MOV DWORD PTR SS:[ESP+40], EAX
00164BA6 83C4 2C ADD ESP, 2C
00163F8A 897C24 1C MOV DWORD PTR SS:[ESP+1C], EDI
0016363D 61 POPAD
001638D6 8BC8 MOV ECX, EAX
001665CD 9D POPFD
0016373A 83C4 04 ADD ESP, 4
00163BF9 C9 LEAVE
00166DA6 83C4 18 ADD ESP, 18
001661D2 5B POP EBX
0016337D 5F POP EDI
00164CBE 5E POP ESI
001652A6 C9 LEAVE
001650B7 51 PUSH ECX
;; 0x306716EA로 JMP Unpack 완료!!
0016516D C3 RETN
크리에이티브 커먼즈 라이선스