Kernel Mode에서는 프로세스, 스레드 보호를 위해 보통 아래와 같은 방법을 이용한다.
x86 : Inline Hook
x64 : ObRegisterCallbacks - Callback
하지만 ObRegisterCallbacks 함수의 경우 VISTA SP1부터 지원을 하기 때문에 XP x64와 VISTA SP0?의 경우 사용을 하지 못하며, PatchGuard로 인해 인라인 후킹도 사용 하기가 어렵다.
그래서 나온 방법이 _OBJECT_TYPE_INITIALIZER 구조체의 OpenProcedure필드에 함수를 등록하여 Callback을 받는 것이다.
OpenProcedure가 뭔지 알기 위해서는 프로세스나 스레드, 이벤트 등과 같은 커널 오브젝트의 구조에 대해 알아야한다.
(자세한 내용은 구글링하시거나 http://ezbeat.tistory.com/421 요기를 참조하세요)
커널 오브젝트(_EPROCESS, _ETHREAD, ...)는 각각의 타입별로 동일한 _OBJECT_TYPE 구조체를 참조하고 있다.
- EPROCESS -> PsProcessType
- ETHREAD -> PsThreadType
우선 !process 0 0 명령어를 쳐서 2개의 대상 프로세스 확인.
_EPROCESS 구조체의 주소가 나오는데 각 커널 오브젝트는 각각 _OBJECT_HEADER라는 구조체를 가지고 있다.
위치는 x86의 경우 -0x18의 위치이며, x64의 경우 -0x30이다.
|
_OBJECT_HEADER + 0x008 위치에 Type 필드를 보면 동일한 _OBJECT_TYPE 구조체를 가리키고 있다.
해당 구조체를 따라가보면 아래와 같다.
|
오브젝트 타입 이름은 Process이며 _OBJECT_TYPE_INITIALIZER 구조체의 포인터를 가지고 있다.
|
_OBJECT_TYPE_INITIALIZER 구조체의 모습이다.
여러 종류의 프로시져가 존재한다.
여기서 주목할 것은 OpenProcedure 이놈이다.
이곳에 함수 포인터를 등록 시켜놓으면 프로세스의 핸들을 Open, Duplicate 하려고 할 때마다 해당 함수가 호출이 되어진다.
다른 프로시져는 테스트해보지 못했지만 핸들을 이용한 작업을 할 때마다 각각의 프로시져가 호출 될 것이다.
여기서 잠깐!
위의 내용은 Windows XP에서 확인한 것이다.
Windows 7에서 확인해보자.
|
_OBJECT_HEADER에 _OBJECT_TYPE 구조체를 가리키는 Type 필드가 없다.
7에서는 불가능한 방법일까? 아니면 어떻게 찾아가야 할까?
방법은 이곳에 http://www.codemachine.com/article_objectheader.html
Object Type Struct 항목을 보면 ObTypeIndexTable이라는 테이블을 참조하고 있다.
ObTypeIndexTable이란 모든 오브젝트의 타입(_OBJECT_TYPE)의 구조체 주소가 있는 테이블이다.
이 ObTypeIndexTable에 TypeIndex 필드에 있는 위치에 해당 _OBJECT_TYPE 구조체가 있다.
(Windows 7에서 프로세스 Type Index는 7이지만 OS마다 조금씩 값이 틀리다. 예전에 정리해놓은게 있는데 잃어버려서 패스 ㅠㅠ)
그렇다면 ObTypeIndexTable 주소는 어디서 구해야할까?
구글링을 해보니 ObGetObjectType이라는 함수 내부에서 해당 테이블을 참조하고 있는 것을 볼 수 있다.
만약 드라이버 코드내에서 해당 테이블의 주소가 필요하다면 이 함수의 내부를 패턴으로 검색하여 주소를 찾아야 할 것이다.
아니면 ObGetObjectType 함수에 EPROCESS를 넣어 리턴되는 포인터가 프로세스의 _OBJECT_TYPE(PsProcessType)인지를 확인하면 된다.
(http://forum.sysinternals.com/finding-obtypeindextable_topic29016.html)
한번 확인해보자.
내가 찾던 _OBJECT_TYPE 구조체 모양대로 나와주었다.
|
다시 _OBJECT_TYPE_INITIALIZER를 따라가보면 다음과 같다.
XP에서 확인한 구조체와는 조금 다른 모습이지만 OpenProcedure이 존재한다.
고로 이 방법을 통하여 모든 OS에 적용시킬 수 있겠다.
아래는 Windows 7 x86에서 프로세스와 스레드 오브젝트의 OpenProcedure를 후킹한 모습이다.
|
실제로 드라이버 코드에서 OpenProcedure 위치는 찾을때는 위에처럼 _EPROCESS부터 구조체 위치를 계산해가면서 찾지는 않는다. 커널에서 export해주는 PsProcessType과 PsThreadType을 이용하면 바로 프로세스와 스레드의 _OBJECTT_TYPE 구조체 주소를 알 수 있다. 그러므로 위의 계산 과정은 필요가 없다.
Windows 8까지 x86/x64 모두 테스트를 해보았으며 모두 정상 동작 되는 것을 확인했다. (믿으세요)
-> 커널 디버깅 상태에서는 모두 정상 동작을 한다.
하지만 정상 OS 부팅 환경에서는 패치가드에 의해 Bugcheck(CRITICAL_STRUCTURE_CORRUPTION 0x109) 발생.
단, XP 64bit의 경우는 패치가드 버전이 낮아서 그런지 패치가드가 감지하지 못한다.
XP 64bit도 패치가드가 감지한다.
'Kernel mode' 카테고리의 다른 글
ConfigFlags (0) | 2013.11.15 |
---|---|
Prefetch / Process Carving : 종료된 프로세스 탐지 (0) | 2013.10.31 |
Windows Kernel (0) | 2013.08.20 |
PsLoadedModuleList (0) | 2013.08.19 |
ddkbuild - #pragma message (0) | 2013.08.06 |