-
Windows System Patched File Analaysis카테고리 없음 2011. 2. 15. 12:36윈도우 시스템 파일이 패치(Patch)된 것 같다고 파일 하나가 접수되었습니다. 파일만 보았을 때는 이 것이 악성코드 인지 알 길이 없어 난감했습니다. 그러나 OllyDbg 로 해당파일을 열었을 때 EP(Entry Point) 에서 실행되는 코드를 보니 아무 의미 없는 코드들도 보였고 악성코드들이 kernel32.dll 의 ImageBase 위치를 찾는 코드들도 눈에 들어 왔습니다.
이제 감각적으로 변경되었다는 것은 알았는데, 어떤 부분이 얼만큼 변경되었는지? 왜 변경했는지? 치료할 방법은 있는지? 등등을 알아가려면 원본 파일이 절실히 필요했습니다. 다행이 정상파일들이 모여있는 곳이 있어 그 곳에서 그리 어렵지 않게 찾을 수 있었습니다.
이렇게 수집한 원본파일과 수정된 파일을 바이너리 수준으로 비교해 보니 변경된 곳이 눈에 바로 들어왔습니다.
변경된 부분 눈으로 확인하기
- IMAGE_OPTIONAL_HEADER32 OptionalHeader->MajorLinkerVersion 0x07 –> 0xBB
- IMAGE_OPTIONAL_HEADER32 OptionalHeader->MinorLinkerVersion 0x0A –> 0x07
- IMAGE_SECTION_HEADER .text->VirtualSize 0x00044c09 --> 0x00044d26 (= 0x11D)
- section .reloc –> IMAGE_BASE_RELOCATION 에서 조그만 부분이 변경되었다.
- Entry point
- 원본은 0x45009 (.text 섹션에 일정량이 NULL로 채워진 부분의 시작) 부터 285(0x11D) Byte 만큼 백업되어 있다.
패치된 파일을 비교할 때 010 Hex Editor 의 도움을 많이 받았다. Template 기능으로 PE 를 분석한 후, 바이너리 비교분석을 하였다. 바이너리 비교 분석한 결과가 화면 오른쪽에 표시된다. 빨간색으로 마크된 부분을 클릭하면 해당 부분으로 이동하게 되는데, 이 부분에 Ctrl+J (Jump To Template Variable) 를 클릭하면 해당 부분이 PE 포맷에서 어느 부분에 해당하는지를 쉽게 찾을 수 있다.
변경된 코드 분석
변경된 부분의 코드는 hlp.dat 파일을 읽어 메모리에 기록한 다음 실행하는 역할을 수행한다.
0101A55F >/$ 8BF6 MOV ESI, ESI
0101A561 |. 8BF6 MOV ESI, ESI
0101A563 |. 60 PUSHAD
0101A564 |. 8BEC MOV EBP, ESP
0101A566 |. 83C4 D0 ADD ESP, -30
0101A569 |. 64:8B1D 30000>MOV EBX, DWORD PTR FS:[30]
0101A570 |. 8B43 0C MOV EAX, DWORD PTR DS:[EBX+C]
0101A573 |. 8B40 14 MOV EAX, DWORD PTR DS:[EAX+14]
0101A576 |. 8B00 MOV EAX, DWORD PTR DS:[EAX]
0101A578 |. 8B00 MOV EAX, DWORD PTR DS:[EAX]
0101A57A |. 8B40 10 MOV EAX, DWORD PTR DS:[EAX+10]
0101A57D |. 8945 F4 MOV [dwBaseAddr], EAX ; / Kernel32.dll Base Address
0101A580 |. 8BC8 MOV ECX, EAX
0101A582 |. BE 40000000 MOV ESI, 40
0101A587 |. 56 PUSH ESI ; | flProtect - PAGE_EXECUTE_READWRITE
0101A588 |. BE 00300000 MOV ESI, 3000
0101A58D |. 56 PUSH ESI ; | flAllocationType - MEM_COMMIT|MEM_RESERVE
0101A58E |. 68 00300100 PUSH 13000 ; | dwSize
0101A593 |. 6A 00 PUSH 0 ; | lpAddress
0101A595 |. 81C1 F19A0000 ADD ECX, 9AF1
0101A59B |. FFD1 CALL ECX ; \ kernel32.VirtualAlloc()
0101A59D |. 8945 FC MOV [lpvAddr], EAX
0101A5A0 |. 8B7C24 EC MOV EDI, DWORD PTR SS:[ESP-14]
0101A5A4 |. 897D F0 MOV [LOCAL.4], EDI
0101A5A7 |. 816D F0 9DA50>SUB [LOCAL.4], 1A59D
0101A5AE |. 81EF 65736200 SUB EDI, 627365
0101A5B4 |. 6A 00 PUSH 0 ; / hTemplateFile
0101A5B6 |. 68 80000000 PUSH 80 ; | dwFlagsAndAttributes (FILE_ATTRIBUTE_NORMAL)
0101A5BB |. 6A 03 PUSH 3 ; | dwCreateionDisposition (OPEN_EXISTING)
0101A5BD |. 6A 00 PUSH 0 ; | lpSecurityAttributes
0101A5BF |. 6A 01 PUSH 1 ; | dwShareMode (FILE_SHARE_READ)
0101A5C1 |. 68 00000080 PUSH 80000000 ; | dwDesiredAccess (GENERIC_READ)
0101A5C6 |. B8 07746200 MOV EAX, 627407
0101A5CB |. 03C7 ADD EAX, EDI
0101A5CD |. 50 PUSH EAX ; | lpFileName ASCII "C:\Documents and Settings\All Users\Documents\Server\hlp.dat"
0101A5CE |. 8B4D F4 MOV ECX, [dwBaseAddr]
0101A5D1 |. 81C1 281A0000 ADD ECX, 1A28
0101A5D7 |. FFD1 CALL ECX ; \ CreateFile
0101A5D9 |. 50 PUSH EAX
0101A5DA |. 6A 00 PUSH 0 ; / lpOverlappped
0101A5DC |. 8D4D F8 LEA ECX, [LOCAL.2]
0101A5DF |. 51 PUSH ECX ; | lpNumberOfBytesRead
0101A5E0 |. 68 00190100 PUSH 11900 ; | nNumberOfBytesToRead
0101A5E5 |. 8B4D FC MOV ECX, [lpvAddr]
0101A5E8 |. 81C1 00100000 ADD ECX, 1000
0101A5EE |. 51 PUSH ECX ; | lpBuffer
0101A5EF |. 50 PUSH EAX ; | hFile
0101A5F0 |. 8B4D F4 MOV ECX, [dwBaseAddr]
0101A5F3 |. 81C1 12180000 ADD ECX, 1812
0101A5F9 |. FFD1 CALL ECX ; \ ReadFile()
0101A5FB |. 8B4D F4 MOV ECX, [dwBaseAddr]
0101A5FE |. 81C1 E79B0000 ADD ECX, 9BE7
0101A604 |. FFD1 CALL ECX ; CloseHandle()
0101A606 |. BF 5FA50100 MOV EDI, 1A55F
0101A60B |. BE 095C0400 MOV ESI, 45C09
0101A610 |. 8B5D F0 MOV EBX, [LOCAL.4]
0101A613 |. 03FB ADD EDI, EBX
0101A615 |. 03F3 ADD ESI, EBX
0101A617 |. 8B5D FC MOV EBX, [lpvAddr]
0101A61A |. 81C3 00100000 ADD EBX, 1000
0101A620 |. B8 00000000 MOV EAX, 0
0101A625 |. B9 1D010000 MOV ECX, 11D ; <-- 악성코드 크기
0101A62A |. 8B55 F4 MOV EDX, [dwBaseAddr]
0101A62D |. 81C2 D41A0000 ADD EDX, 1AD4 ; EXX = VirtualProtect
0101A633 |. 83EC D0 SUB ESP, -30
0101A636 |. 53 PUSH EBX ; hlp.dat 읽어서 기록한 첫 부분
0101A637 |. BB 00000001 MOV EBX, AD101118.01000000
0101A63C \. C3 RETN
0101A63D 90 NOP
0101A63E 90 NOP
0101A63F . 43 3A 5C 44 6>ASCII "C:\Documents and"
0101A64F . 20 53 65 74 7>ASCII " Settings\All Us"
0101A65F . 65 72 73 5C 4>ASCII "ers\Documents\Se"
0101A66F . 72 76 65 72 5>ASCII "rver\hlp.dat",0
0101A67C . 0001 ADD BYTE PTR DS:[ECX], AL
0101A67E . E9 038C0000 JMP AD101118.01023286위 코드를 보면 Kernel32.dll 의 함수를 사용하기 위해 함수의 RVA 상수 값을 Kernel32.dll 의 ImageBase 에 바로 더하는 방식을 사용했는데, 이는 감염된 시스템에 존재하는 Kernel32.dll 에 의존적인 코딩방식이다. 악성코드가 파일을 패치 시킬 때 해당 시스템의 Kernel32.dll 을 읽어 들여 사용하고자 하는 함수의 RVA 값을 그대로 사용한 것으로 판단된다. 따라서 패치된 파일을 OllyDbg 와 같은 동적 분석도구를 사용할 경우에는 분석 시스템의 kernel32.dll 이 패치된 시스템의 kernel32.dll 과 버전이 달라 함수의 위치를 잘못 지정하게 된다. 패치된 코드에서 어떤 함수들을 호출하려고 하는 것인지 알아보기 위해서는 패치된 파일이 있었던 시스템에서 Kernel32.dll 을 수집하는 것이 가장 빠를지도 모르겠다.
진단 조건 생각해보기
BOOL IsDetect()
{
if ( OptionalHeader->MajorLinkerVersion == 0xBB &&
OptionalHeader->MinorLinkerVersion == 0x07 )
{
for(;;)
{
Cmd = NextCmd();
if (Cmd == “RETN”) break;
else if (Cmd == "MOV ECX, ????????")
{
nSize = ????????;
for(int i=0; i<0x10; i++)
{
if (stricmp(pBuf[i], "C:\Documents and", 16)==0)
return TRUE;
}
}
}
}
return FALSE;
}