/*
this routine is to help get system sevices number
by specified service name
*/
NTSTATUS
IhkGetSystemServicesNumber(
IN PCHAR ServiceName, //ZwXxx or NtXxx
OUT PULONG ServiceNumber
)
{
UNICODE_STRING usModuleName;
HANDLE moduleFileHandle;
NTSTATUS status;
OBJECT_ATTRIBUTES objectAttrib;
IO_STATUS_BLOCK ioStatus;
HANDLE sectionHandle;
PUCHAR baseAddress = NULL;
SIZE_T size = 0;
PIMAGE_OPTIONAL_HEADER optHeader;
PIMAGE_EXPORT_DIRECTORY exprotTable;
PULONG routineAddrs;
PULONG routineNames;
PSHORT routineOrdinals;
ULONG i;
PCHAR name;
ULONG index;
PVOID addr;
//ntdll.dll
// note : we use ntdll.dll because the routine it exports is
// more than ntoskrnl and
// the header ZwXxx or NtXxx in it is all start as
// mov eax, <services number>(32bit)
//
RtlInitUnicodeString (&usModuleName, L"\\SystemRoot\\system32\\ntdll.dll");
// now we can get the exported functions, but note we convert from RVA to address
routineAddrs = (PULONG)( baseAddress + exprotTable ->AddressOfFunctions );
//search
for(i = 0; i < exprotTable ->NumberOfFunctions ; i++){
name = (PCHAR)(baseAddress + routineNames [i]);
if(!strcmp(name, ServiceName )){
//found
// always need to add base, -1 as array counts from 0
index = routineOrdinals [i] + exprotTable ->Base - 1;
// this is the funny bit. you would expect the function pointer to
// simply be routineAddrs[i]...
// oh no... thats too simple. it is actually routineAddrs[index]!!
addr = (PVOID)(baseAddress + routineAddrs [index]);
//get the index of serviecs in ZwXxx's or NtXxx's header
*ServiceNumber = *(PULONG)((PUCHAR)addr + 1);