성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Java - How to use the Foreign Funct...
[정성태] 제가 큰 실수를 했군요. ^^; Delegate를 통한 Bein...
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <div style='font-family: 맑은 고딕, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Windbg - 윈도우 핸들 테이블</div> <br /> Windbg를 이용해서 Handle Table을 확인해 보고 기록을 남깁니다. 이번 글은 다음의 책에서 139페이지의 내용을 실습해 본 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > Windows 구조와 원리: OS를 관통하는 프로그래밍의 원리 정덕영 저 | 한빛미디어 ; <a target='_tab' href='http://www.yes24.com/24/goods/1956142'>http://www.yes24.com/24/goods/1956142</a> </pre> <br /> 우선, Windows 2003 x86에서, <a target='_tab' href='http://www.sysnet.pe.kr/2/0/934'>LKD 상태</a>로 테스트를 해보았습니다.<br /> <br /> 1. 적당한 프로세스를 고르기 위해 "!process 0 0" 명령어를 실행하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> !process 0 0 ...[생략]... PROCESS 8da1b4a0 SessionId: 1 Cid: 0f84 Peb: 7ffdd000 ParentCid: 0ee8 DirBase: 7fb1d3c0 <b style='COLOR: blue'>ObjectTable: e14d04c8</b> HandleCount: 11. Image: <b style='COLOR: blue'>CppTest.exe</b> kd> !process: 현재 Active 스레드가 속한 프로세스 정보 kd> !process 0 1: Debuggee PC에서 동작 중인 모든 프로세스 정보 kd> !process 0 7: Debuggee PC에서 동작 중인 모든 프로세스 정보 및 그것의 스레드, 호출 스택 정보 </pre> <br /> 위의 "ObjectTable: e14d04c8" 값이 바로 해당 프로세스의 _HANDLE_TABLE 구조체 주소입니다.<br /> <br /> 2. _HANDLE_TABLE 구조체 값은 아래의 방법으로 구합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> <b style='COLOR: blue'>dt _HANDLE_TABLE e14d04c8</b> nt!_HANDLE_TABLE +0x000 <b style='COLOR: blue'>TableCode : 0xe2e33000</b> +0x004 QuotaProcess : 0x8da1b4a0 _EPROCESS +0x008 UniqueProcessId : 0x00000f84 Void +0x00c HandleTableLock : [4] _EX_PUSH_LOCK +0x01c HandleTableList : _LIST_ENTRY [ 0x808ae988 - 0xe2a8327c ] +0x024 HandleContentionEvent : _EX_PUSH_LOCK +0x028 DebugInfo : (null) +0x02c ExtraInfoPages : 0n0 +0x030 FirstFree : 0x30 +0x034 LastFree : 0 +0x038 NextHandleNeedingPool : 0x800 +0x03c HandleCount : 0n11 +0x040 Flags : 0 +0x040 StrictFIFO : 0y0 </pre> <br /> 위에서 "TableCode: 0xe2e33000" 값이 바로 핸들 테이블의 주소입니다.<br /> 구조체 이름이 기억나지 않는 경우에는 그냥 다음과 같이 dd 명령으로 4byte 정렬로 출력하면 핸들 테이블의 주소를 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> <b style='COLOR: blue'>dd e14d04c8</b> <b style='COLOR: blue'>e14d04c8 e2e33000</b> 8da1b4a0 00000f84 00000000 e14d04d8 00000000 00000000 00000000 808ae988 e14d04e8 e2a8327c 00000000 00000000 00000000 e14d04f8 00000030 00000000 00000800 0000000b e14d0508 00000000 00000000 0c15080a 7346744e e14d0518 00003dd5 00d40000 e11caa10 00d50000 e14d0528 00760000 00000000 000002d7 00030000 e14d0538 27681de6 01cb66b2 b036160e 01cb66b1 </pre> <br /> <a target='_tab' href='http://www.yes24.com/24/goods/1956142'>책</a>에 보면, 위와 같은 핸들 테이블이 바로 "Layer 1"에 해당하는 것일 텐데, 그 책은 Windows 2000이라서 그런 것 같고 Windows 2003에서 테스트했을 때는 위에서 구해진 "e2e33000" 핸들 테이블 값에서 곧바로 핸들 정보가 구해졌습니다. ('책이 옳겠지' 생각하며 실습하다 시간 다 보냈습니다. ^^;)<br /> <br /> 3. 그래서, 일단 e2e33000 값을 바로 덤프해서 핸들 목록을 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> <b style='COLOR: blue'>dd e2e33000</b> e2e33000 <b style='COLOR: blue'>00000000 fffffffe</b> e1002689 00000003 e2e33010 8dadd2e1 001f0003 e163cc09 00000003 e2e33020 8d2d2ec9 00100003 8d143589 00100003 e2e33030 8cd78823 00100020 8d3f89b1 001f0003 e2e33040 e28d3049 001f0001 e25fe639 0002000f e2e33050 8cfbcf41 001f0003 8da4f3c9 000f037f e2e33060 00000000 00000034 00000000 00000038 e2e33070 00000000 0000003c 00000000 00000040 </pre> <br /> Handle 테이블을 구성하는 "하나의 엔트리"는 8byte입니다. 핸들 정보를 가진 오브젝트 헤더 4byte와 Granted Access를 표현하는 4byte.<br /> <br /> 그런데, 위에서 보면 0번째 핸들 값의 Object Header 값이 00000000으로 나오는데, 즉 0번 값을 가지는 핸들이 없음을 나타냅니다.<br /> <br /> 4. 실습 삼아서, 7번 항목을 살펴보면 아래의 위치가 되겠죠.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> dd e2e33000 e2e33000 00000000 fffffffe e1002689 00000003 e2e33010 8dadd2e1 001f0003 e163cc09 00000003 e2e33020 8d2d2ec9 00100003 8d143589 00100003 e2e33030 8cd78823 00100020 <b style='COLOR: blue'>8d3f89b1 001f0003</b> e2e33040 e28d3049 001f0001 e25fe639 0002000f e2e33050 8cfbcf41 001f0003 8da4f3c9 000f037f e2e33060 00000000 00000034 00000000 00000038 e2e33070 00000000 0000003c 00000000 00000040 </pre> <br /> 이유는 알 수 없지만, 이렇게 구해진 "8d3f89b1" 주소는 정확히 _OBJECT_HEADER를 가리키지 않고 이 값에서 1을 빼주어야 합니다. (이유를 아시는 분... 댓글 부탁드립니다. ^^ 다른 글들을 봐도 그래야 한다고만 되어 있고, 이유는 안 써 있더군요.)<br /> <br /> 우선, _OBJECT_HEADER의 구조는 아래와 같고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> dt _OBJECT_HEADER nt!_OBJECT_HEADER +0x000 PointerCount : Int4B +0x004 HandleCount : Int4B +0x004 NextToFree : Ptr32 Void +0x008 Type : Ptr32 _OBJECT_TYPE +0x00c NameInfoOffset : UChar +0x00d HandleInfoOffset : UChar +0x00e QuotaInfoOffset : UChar +0x00f Flags : UChar +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION +0x010 QuotaBlockCharged : Ptr32 Void +0x014 SecurityDescriptor : Ptr32 Void +0x018 Body : _QUAD </pre> <br /> "8d3f89b0 = 8d3f89b1 - 1"로 구해진 "8d3f89b0" 주소로 구조체의 개별 값을 다음과 같이 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> dt _OBJECT_HEADER 8D3F89B0 nt!_OBJECT_HEADER +0x000 PointerCount : 0n2 // windbg에서는 10진수의 표현을 위해 0n prefix를 붙입니다. +0x004 HandleCount : 0n1 +0x004 NextToFree : 0x00000001 Void <b style='COLOR: blue'>+0x008 Type : 0x8e342990 _OBJECT_TYPE</b> <b style='COLOR: blue'>+0x00c NameInfoOffset : 0x10 ''</b> +0x00d HandleInfoOffset : 0 '' +0x00e QuotaInfoOffset : 0 '' +0x00f Flags : 0x20 ' ' +0x010 ObjectCreateInfo : 0x8d3f12a0 _OBJECT_CREATE_INFORMATION +0x010 QuotaBlockCharged : 0x8d3f12a0 Void +0x014 SecurityDescriptor : 0xe25f2097 Void +0x018 Body : _QUAD </pre> <br /> 5. "NameInfoOffset == 0x10" 값이 재미있습니다. 이 옵셋 값은 해당 _OBJECT_HEADER 항목과 연관된 것으로 개체의 이름 정보를 알 수 있는 주소에 대한 -(음수) 값입니다.<br /> <br /> 따라서, 이름 정보는 "8D3F89a0 = 8D3F89B0 - 0x10" 값으로 다음과 같이 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> dt _OBJECT_HEADER_NAME_INFO 8D3F89a0 nt!_OBJECT_HEADER_NAME_INFO +0x000 Directory : 0xe25fe650 _OBJECT_DIRECTORY <b style='COLOR: blue'>+0x004 Name : _UNICODE_STRING "MyEvent"</b> +0x00c QueryReferences : 1 </pre> <br /> 지금 살펴보고 있는 CppTest.exe에서는 다음과 같이 이벤트 개체를 생성했기 때문에, 위에서도 역시 "MyEvent" 값을 확인하게 된 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > int _tmain(int argc, _TCHAR* argv[]) { HANDLE hHandle = ::CreateEvent(NULL, TRUE, TRUE, <b style='COLOR: blue'>L"MyEvent"</b>); getchar(); ::CloseHandle(hHandle); return 0; } </pre> <br /> 6. 이어서 _OBJECT_HEADER에 있던 _OBJECT_TYPE도 구해봅니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> dt _OBJECT_TYPE 8e342990 nt!_OBJECT_TYPE +0x000 Mutex : _ERESOURCE +0x038 TypeList : _LIST_ENTRY [ 0x8e3429c8 - 0x8e3429c8 ] +0x040 Name : _UNICODE_STRING "Event" +0x048 DefaultObject : (null) +0x04c Index : 9 +0x050 TotalNumberOfObjects : 0xb06 +0x054 TotalNumberOfHandles : 0xb69 +0x058 HighWaterNumberOfObjects : 0x2664 +0x05c HighWaterNumberOfHandles : 0x2718 <b style='COLOR: blue'>+0x060 TypeInfo : _OBJECT_TYPE_INITIALIZER</b> +0x0ac Key : 0x6e657645 +0x0b0 ObjectLocks : [4] _ERESOURCE </pre> <br /> 7. _OBJECT_TYPE_INITIALIZER도 구해볼까요? 그런데, 이번에는 직접적인 값이 출력되지 않았습니다. ^^ 그래도 상관없습니다. 위에서 _OBJECT_TYPE의 주소가 "8e342990"이고, _OBJECT_TYPE_INITIALIZER 구조체의 옵셋값이 "0x060"으로 되어 있으니 "8E3429F0 = 8e342990 + 0x60"으로 구하면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> dt _OBJECT_TYPE_INITIALIZER 8E3429F0 nt!_OBJECT_TYPE_INITIALIZER +0x000 Length : 0x4c +0x002 UseDefaultObject : 0 '' +0x003 CaseInsensitive : 0 '' +0x004 InvalidAttributes : 0x100 +0x008 GenericMapping : _GENERIC_MAPPING +0x018 ValidAccessMask : 0x1f0003 +0x01c SecurityRequired : 0 '' +0x01d MaintainHandleCount : 0 '' +0x01e MaintainTypeList : 0 '' +0x020 PoolType : 0 ( NonPagedPool ) +0x024 DefaultPagedPoolCharge : 0 +0x028 DefaultNonPagedPoolCharge : 0x40 +0x02c DumpProcedure : (null) +0x030 OpenProcedure : (null) +0x034 CloseProcedure : (null) +0x038 DeleteProcedure : (null) +0x03c ParseProcedure : (null) +0x040 SecurityProcedure : 0x809733e0 long nt!SeDefaultObjectMethod+0 +0x044 QueryNameProcedure : (null) +0x048 OkayToCloseProcedure : (null) </pre> <br /> 8. 다시 처음의 _OBJECT_HEADER로 돌아가면, 마지막에 Body가 보이는데요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> dt _OBJECT_HEADER nt!_OBJECT_HEADER +0x000 PointerCount : Int4B +0x004 HandleCount : Int4B +0x004 NextToFree : Ptr32 Void +0x008 Type : Ptr32 _OBJECT_TYPE +0x00c NameInfoOffset : UChar +0x00d HandleInfoOffset : UChar +0x00e QuotaInfoOffset : UChar +0x00f Flags : UChar +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION +0x010 QuotaBlockCharged : Ptr32 Void +0x014 SecurityDescriptor : Ptr32 Void <b style='COLOR: blue'>+0x018 Body : _QUAD</b> </pre> <br /> 바로 그 부분이 다양한 커널 개체들의 구조체가 시작되는 부분입니다. 위에서 살펴본 개체가 Event이기 때문에 다음과 같이 _KEVENT로 매핑시켜서 확인해 볼 수 있는데요. 아래에서 보는 것처럼 _KEVENT는 _DISPATCHER_HEADER의 속성을 그대로 상속받은 것에 불과합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> dt _KEVENT nt!_KEVENT +0x000 Header : _DISPATCHER_HEADER </pre> <br /> 그래서 다음과 같이 덤프할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||1:lkd> dt _DISPATCHER_HEADER 8d3f89c8 nt!_DISPATCHER_HEADER +0x000 Type : 0 '' // (Event: 0, Semaphor: 5) +0x001 Absolute : 0x8a '' +0x001 NpxIrql : 0x8a '' +0x002 Size : 0x4 '' +0x002 Hand : 0x4 '' +0x003 Inserted : 0xe3 '' +0x003 DebugActive : 0xe3 '' +0x000 Lock : 0n-486241792 +0x004 SignalState : 0n1 +0x008 WaitListHead : _LIST_ENTRY [ 0x8d3f89d0 - 0x8d3f89d0 ] </pre> <br /> 9. 지금까지 힘들게 옵셋값들을 조정하면서 핸들 관련 정보를 살펴보았는데요. 사실, 핵심적인 정보들은 "!handle" 명령만으로 쉽게 찾아낼 수 있습니다.<br /> <br /> 다음은 (작업관리자에서 확인되는) 프로세스 ID가 F84인 프로세스가 소유한 핸들을 살펴보는 명령입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > <b style='COLOR: blue'>||1:lkd> !handle 0 2 0f84</b> Searching for Process with Cid == f84 PROCESS 8da1b4a0 SessionId: 1 Cid: 0f84 Peb: 7ffdd000 ParentCid: 0ee8 DirBase: 7fb1d3c0 <b style='COLOR: blue'>ObjectTable: e14d04c8 HandleCount: 11.</b> Image: CppTest.exe <b style='COLOR: blue'>Handle table at e2e33000</b> with 11 entries in use 0004: <b style='COLOR: blue'>Object: e10026a0</b> GrantedAccess: 00000003 <b style='COLOR: blue'>Entry: e2e33008</b> Object: e10026a0 <b style='COLOR: blue'>Type: (8e341ad0)</b> KeyedEvent <b style='COLOR: blue'>ObjectHeader: e1002688</b> (old version) ...[생략]... 001c: Object: 8d3f89c8 GrantedAccess: 001f0003 Entry: e2e33038 Object: 8d3f89c8 Type: (8e342990) Event ObjectHeader: 8d3f89b0 (old version) ...[생략]... </pre> <br /> <hr style='width: 50%' /><br /> <br /> 이어서, Windows Server 2008 R2에서도 동일하게 살펴보았습니다. <br /> <br /> 1. 실습 대상인 CppTest.exe를 고르고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> !process 0 0 ...[생략]... PROCESS fffffa800a4617d0 SessionId: 2 Cid: 0b9c Peb: 7fffffdd000 ParentCid: 0bd0 DirBase: 1640b000 <b style='COLOR: blue'>ObjectTable: fffff8a0026066f0</b> HandleCount: 8. Image: CppTest.exe ...[생략]... </pre> <br /> 2. _HANDLE_TABLE 구조체를 덤프<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> dt _HANDLE_TABLE <b style='COLOR: blue'>fffff8a0026066f0</b> nt!_HANDLE_TABLE <b style='COLOR: blue'>+0x000 TableCode : 0xfffff8a0`02746000</b> +0x008 QuotaProcess : 0xfffffa80`0a4617d0 _EPROCESS +0x010 UniqueProcessId : 0x00000000`00000b9c +0x018 HandleLock : _EX_PUSH_LOCK +0x020 HandleTableList : _LIST_ENTRY [ 0xfffff8a0`01945180 - 0xfffff8a0`016cdf20 ] +0x030 HandleContentionEvent : _EX_PUSH_LOCK +0x038 DebugInfo : (null) +0x040 ExtraInfoPages : 0 +0x044 Flags : 0 +0x044 StrictFIFO : 0y0 +0x048 FirstFreeHandle : 0x24 +0x050 LastFreeHandleEntry : 0xfffff8a0`02746ff0 _HANDLE_TABLE_ENTRY +0x058 HandleCount : 8 +0x05c NextHandleNeedingPool : 0x400 +0x060 HandleCountHighWatermark : 8 </pre> <br /> 3. _HANDLE_TABLE.TableCode 값을 덤프하는데, x64이기 때문에 4byte 덤프가 아니므로 "dd" 대신에 "dq"로 해봅니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> dq <b style='COLOR: blue'>0xfffff8a002746000</b> fffff8a0`02746000 <b style='COLOR: blue'>00000000`00000000 00000000`fffffffe</b> fffff8a0`02746010 fffff8a0`004cfd11 00000000`00000003 fffff8a0`02746020 fffffa80`0a49eef1 00000000`00100020 fffff8a0`02746030 fffffa80`0a4693c1 00000000`001f0003 fffff8a0`02746040 fffff8a0`025c0951 00000000`00020019 fffff8a0`02746050 fffffa80`0a339b11 00000000`001f0001 fffff8a0`02746060 fffffa80`0a167901 00000000`001f0001 fffff8a0`02746070 fffff8a0`01659601 00000000`0000000f </pre> <br /> x64이기 때문에 _OBJECT_HEADER에 대한 포인터도 8byte이고, Granted Access도 8byte이기 때문에 하나의 엔트리 당 총 16byte를 소비합니다. 위에서는 역시 0번째 엔트리의 _OBJECT_HEADER 값이 "00000000`00000000"으로 x86과 동일하게 비어있다는 것을 알 수 있습니다.<br /> <br /> 4. 8번째 항목을 덤프하려는데, 위에서 기본 "dq" 명령으로는 7번 항목까지만 보여주고 있으므로 "L[size]"를 부가적으로 지정해주어 값을 확인합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> dq 0xfffff8a002746000 L14 fffff8a0`02746000 00000000`00000000 00000000`fffffffe fffff8a0`02746010 fffff8a0`004cfd11 00000000`00000003 fffff8a0`02746020 fffffa80`0a49eef1 00000000`00100020 fffff8a0`02746030 fffffa80`0a4693c1 00000000`001f0003 fffff8a0`02746040 fffff8a0`025c0951 00000000`00020019 fffff8a0`02746050 fffffa80`0a339b11 00000000`001f0001 fffff8a0`02746060 fffffa80`0a167901 00000000`001f0001 fffff8a0`02746070 fffff8a0`01659601 00000000`0000000f fffff8a0`02746080 <b style='COLOR: blue'>fffffa80`0a3af5b1</b> 00000000`001f0003 fffff8a0`02746090 00000000`00000000 00000000`00000028 </pre> <br /> 역시 이번에도 "fffffa80`0a3af5b0 = fffffa80`0a3af5b1 - 1"과 같이 1을 빼서 확인합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> dt _OBJECT_HEADER <b style='COLOR: blue'>fffffa80`0a3af5b0</b> nt!_OBJECT_HEADER +0x000 PointerCount : 2 +0x008 HandleCount : 1 +0x008 NextToFree : 0x00000000`00000001 +0x010 Lock : _EX_PUSH_LOCK +0x018 TypeIndex : 0xc '' +0x019 TraceFlags : 0 '' +0x01a InfoMask : 0xa '' +0x01b Flags : 0 '' +0x020 ObjectCreateInfo : 0xfffffa80`09d9d980 _OBJECT_CREATE_INFORMATION +0x020 QuotaBlockCharged : 0xfffffa80`09d9d980 +0x028 SecurityDescriptor : 0xfffff8a0`017b59cf <b style='COLOR: blue'>+0x030 Body : _QUAD</b> </pre> <br /> x86과 차이점이 여기서 극명하게 나타나는데요. NameInfoOffset과 _OBJECT_TYPE을 확인할 수 있는 Type 멤버가 누락되어 있습니다. 방법을 모르니 그 부분은 넘어가고, Body를 알아보겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> dt _KEVENT nt!_KEVENT +0x000 Header : _DISPATCHER_HEADER </pre> <br /> _KEVENT가 _DISPATCHER_HEADER를 그대로 상속받은 것에는 변함이 없고, fffffa80`0a3af5b0 값에 Body의 옵셋값인 0x030을 더해서 다음과 같이 구해봅니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> dt _DISPATCHER_HEADER <b style='COLOR: blue'>fffffa80`0a3af5e0</b> nt!_DISPATCHER_HEADER +0x000 Type : 0 '' +0x001 TimerControlFlags : 0 '' +0x001 Absolute : 0y0 +0x001 Coalescable : 0y0 +0x001 KeepShifting : 0y0 +0x001 EncodedTolerableDelay : 0y00000 (0) +0x001 Abandoned : 0 '' +0x001 Signalling : 0 '' +0x002 ThreadControlFlags : 0x6 '' +0x002 CpuThrottled : 0y0 +0x002 CycleProfiling : 0y1 +0x002 CounterProfiling : 0y1 +0x002 Reserved : 0y00000 (0) +0x002 Hand : 0x6 '' +0x002 Size : 0x6 '' +0x003 TimerMiscFlags : 0 '' +0x003 Index : 0y000000 (0) +0x003 Inserted : 0y0 +0x003 Expired : 0y0 +0x003 DebugActive : 0 '' +0x003 ActiveDR7 : 0y0 +0x003 Instrumented : 0y0 +0x003 Reserved2 : 0y0000 +0x003 UmsScheduled : 0y0 +0x003 UmsPrimary : 0y0 +0x003 DpcActive : 0 '' +0x000 Lock : 393216 +0x004 SignalState : 1 +0x008 WaitListHead : _LIST_ENTRY [ 0xfffffa80`0a3af5e8 - 0xfffffa80`0a3af5e8 ] </pre> <br /> 5. 역시 위와 같은 과정은 거의 호기심에서 찾아보는 것일 뿐, !handle 작업으로 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> !handle 0 2 b9c processor number 0, process 0000000000000b9c Searching for Process with Cid == b9c PROCESS fffffa800a4617d0 SessionId: 2 Cid: 0b9c Peb: 7fffffdd000 ParentCid: 0bd0 DirBase: 1640b000 ObjectTable: fffff8a0026066f0 HandleCount: 8. Image: CppTest.exe Handle table at fffff8a002746000 with 8 Entries in use 0004: Object: fffff8a0004cfd40 GrantedAccess: 00000003 Entry: fffff8a002746010 Object: fffff8a0004cfd40 Type: (fffffa8009091930) Directory ObjectHeader: fffff8a0004cfd10 (new version) ...[생략]... 0020: Object: fffffa800a3af5e0 GrantedAccess: 001f0003 Entry: fffff8a002746080 Object: fffffa800a3af5e0 <b style='COLOR: blue'>Type: (fffffa80090f4570)</b> Event ObjectHeader: fffffa800a3af5b0 (new version) </pre> <br /> 재미있는 점은, _OBJECT_HEADER에서 구할 수 없던 Type 값이 여기서 확인할 수 있습니다. ObjectHeader와 Type 값의 차이를 보면, 왠지 일반적인 Offset 값 정도로는 어림없을 것 같고... 도대체 어떤 연관고리가 있는 걸까요? ^^ 암튼, 지금은 능력밖이므로, 그냥 _OBJECT_TYPE만 확인해 봅니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> dt _OBJECT_TYPE fffffa80090f4570 nt!_OBJECT_TYPE +0x000 TypeList : _LIST_ENTRY [ 0xfffffa80`090f4570 - 0xfffffa80`090f4570 ] +0x010 Name : _UNICODE_STRING "Event" +0x020 DefaultObject : (null) +0x028 Index : 0xc '' +0x02c TotalNumberOfObjects : 0xb83 +0x030 TotalNumberOfHandles : 0xbb5 +0x034 HighWaterNumberOfObjects : 0xd69 +0x038 HighWaterNumberOfHandles : 0xdb5 +0x040 TypeInfo : _OBJECT_TYPE_INITIALIZER +0x0b0 TypeLock : _EX_PUSH_LOCK +0x0b8 Key : 0x6e657645 +0x0c0 CallbackList : _LIST_ENTRY [ 0xfffffa80`090f4630 - 0xfffffa80`090f4630 ] </pre> <br /> 그래도 역시 개체의 "이름"은 확인할 방도가 없습니다. 이 값은, !handle의 옵션을 통해서 좀 더 자세한 출력을 얻어내야 알 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> !handle 0 b b9c processor number 0, process 0000000000000b9c Searching for Process with Cid == b9c PROCESS fffffa800a4617d0 SessionId: 2 Cid: 0b9c Peb: 7fffffdd000 ParentCid: 0bd0 DirBase: 1640b000 ObjectTable: fffff8a0026066f0 HandleCount: 8. Image: CppTest.exe Handle table at fffff8a002746000 with 8 Entries in use 0004: Object: fffff8a0004cfd40 GrantedAccess: 00000003 Entry: fffff8a002746010 Object: fffff8a0004cfd40 Type: (fffffa8009091930) Directory ObjectHeader: fffff8a0004cfd10 (new version) HandleCount: 40 PointerCount: 78 Directory Object: fffff8a000004c90 Name: KnownDlls ... [생략]... <b style='COLOR: blue'>0020</b>: Object: fffffa800a3af5e0 GrantedAccess: 001f0003 Entry: fffff8a002746080 Object: fffffa800a3af5e0 Type: (fffffa80090f4570) Event ObjectHeader: fffffa800a3af5b0 (new version) HandleCount: 1 PointerCount: 2 Directory Object: fffff8a001659630 <b style='COLOR: blue'>Name: MyEvent</b> </pre> <br /> <span style='text-decoration: line-through'>핸들을 직접 지정해서 "Optional Headers"를 지정해서 얻어내는 방법이 있긴 한데, 어찌된 일인지 이 목록은 "!handle 0 0 b9c"에서 구한 핸들 목록과 인덱스가 같지 않습니다. 보는 것처럼 위에서 0x20은 "Event" 유형인데 아래에서는 "ALPC Port"임이 확인됩니다.</span> 아래의 명령어는 커널 모드의 정보를 구하기 때문에 다릅니다. 출력 결과에 보면 "Kernel Handle table"이라고 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ||2:lkd> !handle <b style='COLOR: blue'>0x20</b> 13 b9c processor number 0, process 0000000000000b9c Searching for Process with Cid == b9c PROCESS fffffa800a4617d0 SessionId: 2 Cid: 0b9c Peb: 7fffffdd000 ParentCid: 0bd0 DirBase: 1640b000 ObjectTable: fffff8a0026066f0 HandleCount: 8. Image: CppTest.exe Kernel Handle table at fffff8a001150000 with 596 Entries in use 0020: Object: fffffa80090e7070 GrantedAccess: 001f0001 Entry: fffff8a000003080 Object: fffffa80090e7070 Type: (fffffa80090e2db0) <b style='COLOR: blue'>ALPC Port</b> ObjectHeader: fffffa80090e7040 (new version) HandleCount: 1 PointerCount: 4 Directory Object: fffff8a000004c90 Name: PowerPort Optional Headers: NameInfo(<b style='COLOR: blue'>fffffa80090e7020</b>) HandleInfo(<b style='COLOR: blue'>fffffa80090e7010</b>) ||2:lkd> <b style='COLOR: blue'>dt _OBJECT_HEADER_NAME_INFO fffffa80090e7020</b> nt!_OBJECT_HEADER_NAME_INFO +0x000 Directory : 0xfffff8a0`00004c90 _OBJECT_DIRECTORY <b style='COLOR: blue'>+0x008 Name : _UNICODE_STRING "PowerPort"</b> +0x018 ReferenceCount : 0 ||2:lkd> <b style='COLOR: blue'>dt _OBJECT_HEADER_HANDLE_INFO fffffa80090e7010</b> nt!_OBJECT_HEADER_HANDLE_INFO +0x000 HandleCountDataBase : 0xfffffa80`090b9740 _OBJECT_HANDLE_COUNT_DATABASE +0x000 SingleEntry : _OBJECT_HANDLE_COUNT_ENTRY </pre> <br /> 이번엔 여기까지!<br /> <br /><br /><hr /><span style='color: Maroon'>[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
8865
(왼쪽의 숫자를 입력해야 합니다.)