본문 바로가기

My Study/Programming&Theory

ObCreateObjectType & ObjectType

NTSTATUS ObCreateObjectType(  

__in PUNICODE_STRING TypeName,  

__in POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,  

__in_opt PSECURITY_DESCRIPTOR SecurityDescriptor,  

__out POBJECT_TYPE *ObjectType  

);  


말 그대로 오브젝트를 생성하는 함수이다. 하지만 문서화 되지 않은 함수이므로 한번 함수 원형을 정의해 주고 사용하면 된다.



WinDbg에서 

!object \ObjectTypes

명령을 해주면 시스템에 존재하는 Object Type 들이 모두 보여집니다.


저기 제가 생성한 오브젝트가 존재하는군요.



코드는 위와 같습니다. 

중요한건 OBJECT_TYPE_INITIALIZER 구조체를 적절히 초기화 시켜주면 됩니다.


이러한 오브젝트가 왜 중요하냐? 위는 그냥 오브젝트가 생성 시켜보았을 뿐이고 이미 시스템에 의해 생성된 오브젝트들 중에 유용하게 사용될 오브젝트가 있습니다. 바로 Process 오브젝트입니다. 저 오브젝트 내용을 수정시키면 SSDT 후킹 같은 것을 이용하지 않고 프로세스 종료에 대한 보호 등등 여러가지 일을 할 수 있습니다.


전 포스팅에서 ObRegisterCallbacks 함수를 사용해 프로세스 오브젝트에 접근 시 Pre, Post 콜백을 각각 지정해 프로세스를 보호 할 수 있었다. ( 함수 후킹을 하는게 아니므로 오브젝트 내부 값을 바꿔서 보호 하는 방식 )


하지만 해당 함수는 Windows Vista SP1 이후부터 사용할 수 있는 함수이기 때문에 Windows XP에선 사용할 수 없는 방법이다. 그래서 XP에선 SSDT 후킹을 사용하지 않고 프로세스를 보호하는 방법 중 하나로 Process 라는 이름을 가진 Object Type을 후킹해서 보호하는 방법이 있다.


먼저 OBJECT_HEADER, OBJECT_TYPE, EPROCESS 구조체 간 상관 관계를 보겠다.

( Windows XP SP3 기준 )



WinDbg로 포인터 따라가면서 봐본 그림이다. 내 눈이 잘못된게 아니라면 저렇게 되어 있다.


각 프로세스 오브젝트들은 각 오브젝트 헤더에 포함되어 있다. 그리고 오브젝트 헤더의 Type 부분에는 해당 오브젝트의 타입을 나타내는 OBJECT_TYPE 구조체 포인터가 지정되어 있는데 바로 Object Type Name이 Process 인 Object Type을 가리키고 있다. 


그리고 OBJECT_TYPE 에서 TypeInfo 멤버변수에 중요한 정보가 있다. 해당 멤버변수의 자료형은 OBJECT_TYPE_INITIALIZER 인데 해당 구조체 내용은 다음과 같다.



아래 0x2C부터 각 상황에 맞는 프로시져들을 등록할 수 있는데 기본적으로


DeleteProcedure, SecurityProcedure 두 부분만 설정되어 있다.

만약 특정 프로세스가 없어질 때는 DeleteProcedure 함수가 호출된다.


그러면 다른 프로세스를 죽이기 위해선 먼저 해당 프로세스를 내 프로세스에서 핸들을 얻어야 하는데 이 때 OpenProcedure 부분에 프로시져가 등록되어 있으면 해당 프로시져가 호출된게 된다.


해당 프로세스에 접근했을 때 OpenProcedure 내부에서 BP를 걸고 CallStack을 봐보도록 하겠습니다.


00 b2163a6c 805bf08c OpenProcedure 에 있는 프로시져 호출

01 b2163b18 805bf611 nt!ObpIncrementHandleCount+0x352

02 b2163b78 805bdd10 nt!ObpCreateHandle+0x161

03 b2163c48 805cd625 nt!ObOpenObjectByPointer+0xa4

04 b2163d4c 8054361c nt!NtOpenProcess+0x229

05 b2163d4c 7c93e4f4 nt!KiFastCallEntry+0xfc

06 0007f80c 7c93d5ec ntdll!KiFastSystemCallRet

07 0007f810 7c830a1a ntdll!NtOpenProcess+0xc

08 0007f84c 0100c21d 0x7c830a1a

09 0007f88c 0100ceef 0x100c21d

0a 0007f8a0 0100d1d0 0x100ceef

0b 0007f90c 77cf8734 0x100d1d0

0c 0007f938 77d03ce4 0x77cf8734

0d 0007f9a4 77d03b30 0x77d03ce4

0e 0007facc 7c93e453 0x77d03b30

0f 0007fad0 0007fadc ntdll!KiUserCallbackDispatcher+0x13

10 0007fad4 77d11b7c 0x7fadc

11 0007fadc 00000000 0x77d11b7c


해당 프로세스를 종료 시키려 했고 OpenProcess 함수가 호출되었을 때의 결과입니다.


저 내부적으로 현재 접근되고 있는 프로세스의 PID가 보호하려는 PID랑 같으면 OpenProcedure 함수의 리턴 값을 STATUS_ACCESS_DENIED 로 리턴해주면 됩니다.


구현 방식은 간단하게 할 수 있습니다.


위에서 Object Type Name이 "Process" 인 OBJECT_TYPE 값은 커널에서 export 해주고 있습니다.

바로 PsProcessType 로 말이죠. 고로 우리의 디바이스 드라이버 내부적으론 PsProcessType 값을 가져와

각 프로시져가 있는 위치에 함수 값을 저장해주면 되는 것입니다.


PsProcessType -> OBJECT_TYPE_INITIALIZER -> OpenProcedure  요렇게 접근하면 되겠죠.


뭐 PsProcessType을 사용하지않더라도 항상 시스템 상에 존재하는 System 프로세스의 EPROCESS 값을 구하고 OBJECT_HEADER 값에 접근해가는 방식도 사용할 수 있습니다.


방식은 구현하는 사람 마음이겠죠. 따로 코드는 올리지 않겠습니다.


방금까진 Windows XP 에서만 봐왔는데 ObRegisterCallbacks 함수를 사용하는 Windows 7 에서도 이 방법을 사용할 수 있을까요??



위 구조체는 Windows 7 에서의 OBJECT_HEADER 값입니다.

Windows XP 에 존재하던 각 오브젝트 Type을 나타낸 OBJECT_TYPE 멤버가 없습니다.


고로 Windows XP 에서 사용하는 방식으론 안되겠네요.


2012년 마지막 포스팅을 끝냅니다. 2013년에는 더욱 열심히 포스팅을....


'My Study > Programming&Theory' 카테고리의 다른 글

윈도우 드라이버 로드 시 에러  (2) 2013.03.15
Windows 7 x86 Bypass UAC  (12) 2013.01.14
ObRegisterCallbacks 사용해보기  (2) 2012.12.27
Red-Black Tree - 3  (1) 2012.12.24
FltCancelFileOpen 궁금증  (4) 2012.12.20