http://blog.csdn.net/celestialwy/archive/2006/09/27/1292150.aspx
bool IsSystemService (LPCTSTR lpcszFunctionName, PBYTE pFunction, ULONG &nServiceId)
{
if (!lpcszFunctionName || !pFunction)
return false;
if ((lpcszFunctionName [0] != 'N')|| (lpcszFunctionName [1] != 't'))
return false;
//
// 77F5B438 B8 00000000 MOV EAX, _FUNCTION_ID_
// 77F5B43D BA 0003FE7F MOV EDX,7FFE0300
// 77F5B442 FF12 CALL EDX
// 77F5B444 C2 1800 RETN XX
//
//
// mov eax
//
if ( *pFunction != 0xB8 )
{
return false;
}
//
// since the address of the function which actually makes the call6 (SYSCALL) may change, we
// just check for mov edx
//
if ( *(pFunction + 5) != 0xBA )
{
return false;
}
//
// call edx
//
if ( *(PWORD)(pFunction + 10) != 0x12FF )
{
return false;
}
//
// retn
//
if ( *(pFunction + 12) != 0xC2 )
{
return false;
}
nServiceId = *(PDWORD)(pFunction + 1);
return true;
}
bool GetSystemService ()
{
//get the function's address
HMODULE hMod = GetModuleHandle ("ntdll.dll");
if (!hMod)
return false;
IMAGE_DOS_HEADER* dosheader;
IMAGE_OPTIONAL_HEADER* opthdr;
IMAGE_EXPORT_DIRECTORY* pExportTable;
DWORD* arrayOfFunctionAddresses;
DWORD* arrayOfFunctionNames;
WORD* arrayOfFunctionOrdinals;
DWORD functionOrdinal;
ULONG Base, x, functionAddress;
char* functionName;
PVOID BaseAddress = NULL;
SIZE_T size=0;
dosheader = (IMAGE_DOS_HEADER *)hMod;
opthdr =(IMAGE_OPTIONAL_HEADER *) ((BYTE*)hMod+dosheader->e_lfanew+24);
pExportTable =(IMAGE_EXPORT_DIRECTORY*)((BYTE*) hMod + opthdr->DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT]. VirtualAddress);
// now we can get the exported functions, but note we convert from RVA to address
arrayOfFunctionAddresses = (DWORD*)( (BYTE*)hMod + pExportTable->AddressOfFunctions);
arrayOfFunctionNames = (DWORD*)( (BYTE*)hMod + pExportTable->AddressOfNames);
arrayOfFunctionOrdinals = (WORD*)( (BYTE*)hMod + pExportTable->AddressOfNameOrdinals);
Base = pExportTable->Base;
ULONG nServiceId = 0;
for(x = 0; x < pExportTable->NumberOfFunctions; x++)
{
functionName = (char*)( (BYTE*)hMod + arrayOfFunctionNames[x]);
functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1; // always need to add base, -1 as array counts from 0
// this is the funny bit. you would expect the function pointer to simply be arrayOfFunctionAddresses[x]...
// oh no... thats too simple. it is actually arrayOfFunctionAddresses[functionOrdinal]!!
functionAddress = (DWORD)( (BYTE*)hMod + arrayOfFunctionAddresses[functionOrdinal]);
if (IsSystemService (functionName, (PBYTE)functionAddress, nServiceId))
{
printf ("0x%08x %s 0x%08x/n",
nServiceId,
functionName,
functionAddress);
}
}
FreeLibrary (hMod);
return TRUE;
}