MMORPG 유저라면 게임을 띄워놓고 치트엔진을 사용했던 경험이 한번씩은 있을겁니다. (..없나?)
만약 핵쉴드 혹은 게임가드가 붙어있는 게임에 치트엔진을 사용했다면 "프로세스를 열 수 없습니다" 메시지를 확인할 수 있습니다.
<그림 1 : 프로세스 열기 실패>
위와 같은 범용 치트엔진은 Win32 API인 OpenProcess를 통해서 프로세스에 접근을 하게 됩니다.
이 같은 방법을 막는데엔 여러가지 방법이 있겠지만, 백신같은 같은 보안 프로그램이 프로세스 핸들(오브젝트)를 보호하고 있다고 가정해보죠.
HANDLE hProcess = NULL;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 3752);
printf("%x %x",hProcess, GetLastError());
본 소스는 특정 프로세스(pid : 3752)의 핸들을 얻는 코드로, 치트엔진도 이와 같은 초벌작업을 합니다.
컴파일하여 출력하면 NULL과 5가 출력되는데, 5는 ERROR_ACCESS_DENIED 으로 액세스 거부를 뜻합니다.
(시스템 에러 코드 표 : http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx)
이처럼 정상적인 경로로 핸들을 얻지 못하는건 보안 프로그램에서 뭔가 작업(?)을 했다는 건데요.
지금부터 무슨 작업을 했길래 핸들을 얻지 못하는지 썰을 풀어보도록 하겠습니다.
# 본격 작업에 앞서서 핸들을 짚어보죠.
타겟 프로세스의 핸들을 찾는 과정을 windbg를 통해 트레이싱 해보겠습니다.
타겟은 국민 프로세스 지뢰찾기(winmine.exe)입니다.
치트엔진으로 winmine.exe을 오픈했으며, 프로세스 익스플로러로 이를 확인할 수 있습니다.
< 그림 2 : Process Explorer로 프로세스 핸들 확인>
치트엔진에서 winmine.exe의 프로세스 핸들(오브젝트)를 가지고 있습니다. 여기서는 0x89AF5DA0이며, 프로세스 핸들이기 때문에 EPROCESS 구조체로도 표현이 가능합니다.
# 프로세스 핸들을 보호해 볼까요?
우선 OpenProcess의 내부부터 살펴볼까요,
유저모드에서 sysenter를 타서 커널로 진입을 하여 NtOpenProcess를 여는건 누구나가 다 아는 사실일텐데요(모름 검색 고고~)
XP 커널 기준으로 NtOpenPorcess는 내부에서 ObOpenObjectByPointer, PsLookupProcessByProcessId, ObOpenObjectByPointer등과 같은 여러가지 API 들을 호출합니다.
자세한건 아래 첨부파일을 참조하세요.
여기서 ObOpenObjectByPointer라는 흥미로운 API가 있습니다.
MSDN의 설명을 빌리자면, ( http://msdn.microsoft.com/en-us/library/windows/hardware/ff550985(v=vs.85).aspx )
The ObOpenObjectByPointer function opens an object referenced by a pointer and returns a handle to the object.
오브젝트를 열고 핸들(HANDLE)을 반환한다는군요.
NTSTATUS ObOpenObjectByPointer(
_In_ PVOID Object,
_In_ ULONG HandleAttributes,
_In_opt_ PACCESS_STATE PassedAccessState,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_TYPE ObjectType,
_In_ KPROCESSOR_MODE AccessMode,
_Out_ PHANDLE Handle
);
중요한 것은 NtOpenProcess 실행 시 이 API의 Object값은 프로세스 핸들(오브젝트)이 된다는 점입니다.
뭔가 감이 오지 않나요? 이 API를 후킹해서 아래와 같은 코드를 작성하면 지뢰찾기 프로세스의 액세스 거부를 반환할 수 있습니다.
if (Object == 0x89AF5DA0) return STATUS_ACCESS_DENIED;
# ObOpenObjectByPointer 후킹 실전 코드
아래 링크는 대륙의 해커 dayed가 만든 후킹 소스입니다.
http://bbs.pediy.com/archive/index.php?t-67286.html
후킹 함수인 fake_ObOpenObjectByPointer() 함수를 살펴보면,
Object가 널이 아니면 -> Object가 프로세스이면 -> 보호된 프로세스가 자기자신 프로세스가 아니면 -> 보호된 프로세스와 Object가 일치하면 액세스 거부
이렇게 구성되어 있습니다.
wdk/ddk로 컴파일시 소스의 Notepad.exe부분만 타겟 프로세스로 바꿔주면 치트엔진에서 액세스가 거부되는 것을 볼 수 있습니다.
위와 언급한 코드처럼 하드코딩해서 입력해도 동작은 합니다.(많이 번거롭지만요)
# 마치며
이 외에도 오브젝트 관련 함수인 ObReferenceObjectByHandle() 함수를 후킹하는 방법도 있습니다.
만약 핸들을 보호하는것이 아닌 OpenProcess를 막고 싶다면 NtOpenProcess()를 후킹하는 게 가장 손쉬운 방법입니다.
'Windows > Hacking & Vulnerability' 카테고리의 다른 글
브라우저 취약점 - Shellcode의 bad char로 인한 에러 해결 (0) | 2014.03.22 |
---|---|
EMET 4.1 - Force ASLR (0) | 2014.03.20 |
EMET 4.1 - 주요 후킹 API 그리고 Deep Hooks란? (0) | 2014.03.18 |
EMET 4.1 - 패킹된 EXE의 오진 이슈 (0) | 2014.03.10 |
Windows 기반의 ROP 공격 #1 (0) | 2013.12.16 |