겸손한 개발을 위한 자양분

우선, 커널 변수를 이용하여, 테이블 위치 확인

0: kd> dd KeServiceDescriptorTable
8055c700 80504450 00000000 0000011c 805048c4
8055c710  00000000 00000000 00000000 00000000
8055c720  00000000 00000000 00000000 00000000
8055c730  00000000 00000000 00000000 00000000
8055c740  00000002 00002710 bf80c0b6 00000000
8055c750  f719ba80 f6b89b60 86d74950 806f60c0
8055c760  00000000 00000000 ffea8ad6 ffffffff
8055c770  ee4ae396 01c90284 00000000 00000000

0: kd> dd KeServiceDescriptorTableShadow
8055c6c0  80504450 00000000 0000011c 805048c4
8055c6d0  bf999b80 00000000 0000029b bf99a890
8055c6e0  00000000 00000000 00000000 00000000
8055c6f0  00000000 00000000 00000000 00000000
8055c700  80504450 00000000 0000011c 805048c4
8055c710  00000000 00000000 00000000 00000000
8055c720  00000000 00000000 00000000 00000000
8055c730  00000000 00000000 00000000 00000000

KeServiceDescriptorTable 에서, NtOsKrnl 에 연결된 서비스.
KeServiceDescriptorTableShadow 에서, Win32K 에 연결된 서비스 를 확인 할 수 있다.

typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PULONG  ServiceTable;  // array of entry-points
PULONG  puCounterTable;  // array of counters
ULONG  uTableSize;   // number of table entries
PUCHAR  pbArgumentTable; // array of byte counts
} SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;

ServiceDescriptorTable의 구조가 위와 같으므로,
앞의 SDT에서는
ServiceTable Array of Entry 가 80504450
Entry의 개수는 0000011c 개 임을 알 수 있다.

출력하여 보면
0: kd> dds 0x80504450 L11c
80504450  805a4614 nt!NtAcceptConnectPort
80504454  805f0adc nt!NtAccessCheck
80504458  805f4312 nt!NtAccessCheckAndAuditAlarm
8050445c  805f0b0e nt!NtAccessCheckByType
80504460  805f434c nt!NtAccessCheckByTypeAndAuditAlarm
80504464  805f0b44 nt!NtAccessCheckByTypeResultList
80504468  805f4390 nt!NtAccessCheckByTypeResultListAndAuditAlarm
8050446c  805f43d4 nt!NtAccessCheckByTypeResultListAndAuditAlarmByHandle
80504470  806153a2 nt!NtAddAtom
...

위와 같이 List를 확인할 수 있다.
덧붙혀, 위의 순서가 바로 서비스 Index가 된다.