NProtect GameGuard 쪼물딱 거려볼까??

dump_wmimmc.sys (rev 1001, kernel driver)
dump_wmimmc.idb
native_api_inline_hook_routine.gdl

간만에 업데이트된 커널 드라이버를 봤더니 .text영역에 알 수 없는 데이터만 가득
들어있는 마치 exe가 패킹되어 있는 듯한 모습을 가지고 있었다. 드라이버가 packing
되어 있는건 생소해서 조금 더 살펴 봤더니 아래와 같은 녀석을 발견했다.
Oreans사에서 나온 Code Virtualizer가 적용이 되어 있었다. 나중에 알게된 사실이지만
rev900이후부터 적용된 듯 싶다.
Code Virtualizer를 좀 찾아보니 x86 opcode를 PE안에 내장한 virtual machine에서
돌아가도록 가상 opcode로 변환시켜준다고 한다. 그리고 가상 opcode를 분석하기가
조금 까다로운 것이 다양한 VM이 있고 이들 VM들은 모두 다른 instruction으로 돌아가기
때문에 시간이 많이 필요하다. 하지만 짱께들처럼 집단으로 분석한다면 뭐 분석 시간은
얼마 걸리지 않을 것 같다. 물론 VirtualizerStart~End 블록에 대해서만이다.  일반적으로
VM블럭 내부에 있는 코드들은 퍼포먼스가 조금 떨어지기 때문에 아주 Critical한 부분에
대해서만 Virtualization 한 것 같다.  그리고 같은 회사 제품에서 나온 TheMida가
GameGuard.des에 적용이 되어 있었다. 아래는 드라이버 코드에서 어떻게 사용하는지
알려주는 예제이다.

#include <ntddk.h> 
#include "VirtualizerDDK.h"  // definitions for VirtualizerStart() and VirtualizerEnd() 

NTSTATUS 
DriverEntry( 
     IN PDRIVER_OBJECT  DriverObject, 
     IN PUNICODE_STRING RegistryPath 
     ) 

     PDEVICE_OBJECT      deviceObject; 
     PDEVICE_EXTENSION   deviceExtension; 
     UNICODE_STRING      ntDeviceName; 
     UNICODE_STRING      symbolicLinkName; 
     NTSTATUS            status; 
 
     DebugPrint(("==>DriverEntry %d\n", i)); 
 
    VirtualizerStart();     // area to protect starts here! 
 
     // 
     // Create the device object 
     // 
     RtlInitUnicodeString( &ntDeviceName, NTDEVICE_NAME_STRING ); 
 
     status = IoCreateDevice(  
                 DriverObject,               // DriverObject  
                 sizeof( DEVICE_EXTENSION ), // DeviceExtensionSize 
                 &ntDeviceName,              // DeviceName 
                 FILE_DEVICE_UNKNOWN,        // DeviceType 
                 FILE_DEVICE_SECURE_OPEN,  // DeviceCharacteristics 
                 FALSE,                       // Not Exclusive 
                 &deviceObject              // DeviceObject 
                 ); 

     if ( !NT_SUCCESS(status) ) { 
         DebugPrint(("\tIoCreateDevice returned 0x%x\n", status)); 
         return( status ); 
     } 

    VirtualizerEnd();       // area to protect finishes here! 
....
}

흠.... 일단 Code Virtualizer쪽으로 일단 찔러야 대략적인 동작을 알 수 있을거 같다.
그런데 이거 디버깅 하기가 아주 더럽겠다. ㅡㅡ;;;

그리고 SSDT쪽을 살펴보니 직접 그 주소를 바꾸지는 않는다. 그래서 드라이버 로딩
전,후의 NtOpenProcess의 모습을 살펴봤더니 아래와 같았다.

8057B0DA | 68 C4000000                | PUSH    C4
8057B0DF | 68 48274F80                | PUSH    804F2748
8057B0E4 | E8 9A9DF6FF                | CALL    804E4E83
8057B0E9 | 33F6                       | XOR     ESI, ESI
8057B0EB | 8975 D4                    | MOV     DWORD PTR [EBP-2C], ESI
8057B0EE | 33C0                       | XOR     EAX, EAX
8057B0F0 | 8D7D D8                    | LEA     EDI, DWORD PTR [EBP-28]
8057B0F3 | AB                         | STOS    DWORD PTR ES:[EDI]
8057B0F4 | 64:A1 24010000             | MOV     EAX, DWORD PTR FS:[124]

8057B0DA | E9 73C52B38                | JMP     B8837652      ; inline hook
8057B0DF | 68 48274F80                | PUSH    804F2748
8057B0E4 | E8 9A9DF6FF                | CALL    804E4E83
8057B0E9 | 33F6                       | XOR     ESI, ESI
8057B0EB | 8975 D4                    | MOV     DWORD PTR [EBP-2C], ESI
8057B0EE | 33C0                       | XOR     EAX, EAX
8057B0F0 | 8D7D D8                    | LEA     EDI, DWORD PTR [EBP-28]
8057B0F3 | AB                         | STOS    DWORD PTR ES:[EDI]
8057B0F4 | 64:A1 24010000             | MOV     EAX, DWORD PTR FS:[124]

예전처럼 SSDT의 함수 엔트리 주소를 변경하지 않고, 직접 커널 함수에 대해서
inline 후킹하는 것을 알 수 있다. 정확히는 기존의 SDT를 신뢰하지 않고 처음
구동시 ntoskrnl.exe를 참조하여 주요한 SDT를 복원하고, ntoskrnl.exe에 구현된
코드에 5바이트를 inline 후킹한다. 그리고 예전에 시도했었던 int1, int3에 대한
IDT 후킹은 찾아볼 수 없었다. 하지만 int1,3에 대한 IDT 후킹이 되어 있는 경우
이를 복원하였다.

요기서 머릿돌을 잠시 굴려보면 GG가 ntoskrnl.exe를 가지고 복원할 때 ntoskrnl의
무결성까지 체크하기란 쉽지 않을 것이다. 그렇기에 변조된 ntoskrnl을 올린다면
뭔가 재미있는 일이 가능할 것이다.

by nerd | 2007/04/12 15:06 | TrashCan | 트랙백 | 핑백(1) | 덧글(11)


트랙백 주소 : http://nerd.egloos.com/tb/3109902
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Linked at kkamagui의 끝없는 삽질.. at 2007/07/29 04:52

... nProtect에 무슨 일이 생겼는지... 꽤나 궁금했었는데...오늘 rss를 읽다가 우연히 한 분이 분석한걸 보게 되었다.http://nerd.egloos.com/3109902 SDT 쪽에 별 문제가 없길래 설마 설마 했었는데...kernel 함수를 직접 손볼줄이야.. @0@)/~!!방식이야 유저레벨의 DLL 조작하는 ... more

Commented at 2007/04/13 12:32
비공개 덧글입니다.
Commented by chpie at 2007/04/19 00:07
내장 가상머신 이라니 엄청나게 재미있는 아이디어네요 ㅋㅋ
이런걸 생각할 수 있다니 ㅋㅋ
Commented by nerd at 2007/04/19 15:44
그러게요. 덕분에 Code Virtualizer도 공부해야 될 거 같습니다.
지난번에 Code Virtualizer 문서 잠깐 봤었는데 쉽지 않더군요. -_-;;
Commented by 사특마녀 at 2007/04/22 23:04
허걱~~~ 너무 어려워요....ㅠ_ㅜ
Commented by nerd at 2007/04/23 00:43
외국쪽 UCE 포럼에 가보니 bypass 어떻게 할까 잔머리 굴리던 친구들도 맞불대응하고 나섰더군요.
UCE에 올라가는 드라이버에 Code Virtualizer를 적용하고 CE 실행파일과 DLL들을 패커로 중무장해서
어떻게든 패턴매칭을 피해가려고 하더군요. 흐미 앞으로 이런식으로 나아가면 점점 더 Anti Cheating이
힘들어지겠군요. ㅠㅠ;;
Commented by chp at 2007/06/29 17:23
참 재미있내요.
nprotect를 bypassing하는걸 재미로 만들어서 쓰고있다가..
어느날 갑자기 전부 바뀌어있길래 저렇게 바꿔놨었군요..
dump_wmimmc.sys를 덤프하는걸 몰라서
대충 SSDT쪽 보고 bypassing 했는데 앞으로 점점 재미있어지겠내요~
Commented by kkamagui at 2007/07/29 04:36
좋은 정보 감사 드립니다.
안그래도 어떻게 된건지 궁금했는데... 설마 설마 하는 부분이 고쳐졌군요...
방금 직접 확인했습니다.

약간 더 신경을 써야 겠군요... 흠...
Commented by 오픈마인드 at 2007/08/31 11:17
nprotect를 bypass하는 방법에 대해서 참고할 사이트들을 알려주시면 고맙겠습니다. 그리고 nprotect가 사용하는 드라이버파일(.sys)의 이름도...
좋은 실마리를 찾아쥐고 갑니다.

감사합니다.
Commented by 키르 at 2007/10/12 02:51
던파 하다 저거 관련 블루 스크린떠서 난감했는데.....
저파일 받아가면 되는건가요..?
system32 drivers에 세파일 다 넣었는데.. 다시 덤프 뜨더군요... 그후.... 보니까.. sys 파일만 없던데.ㅠ.ㅠ
근데 한번들어갔을때는... 안뜨던데.... 들어갔다 나왓다 한뒤 다시 들어갔다 나오니까.. 덤프 뜨네요..... [이파일 안 받았을땐... 한번에 덤프 떳었죠.ㅠ.ㅠ.
Commented by 닉트로 at 2008/02/01 13:15
이거 깔면 지워지고 깔면 지워지고 하는데 안없어지는법 없나요?

자꾸 게임가드만 실행시키면 지워짐 도와주세요 ㅠ
Commented by 투명인간 at 2008/11/20 20:48
저런방법이..

:         :

:

비공개 덧글

◀ 이전 페이지다음 페이지 ▶