A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #9582  by madaboo
 Tue Nov 08, 2011 2:53 pm
Hello!

I need to locate unexported symbol of nt* function.
The way I want to do it is to load ntoskrnl.exe then get KeServiceDescriptorTable and then move KiServiceTable address of syscallidx to get it's name.

I was looking for many of the posts here but I still don;t catch the idea.

For now I'm doing something like this:


moduleHandle = (DWORD)LoadLibraryEx("ntoskrnl.exe", 0, 0);
if (NULL == moduleHandle)
{
printf("error occured - LoadLibraryEx!\n");
return;
}

keServiceDispatchTableFarProc = GetProcAddress(moduleHandle, "KeServiceDescriptorTable");

Now RVA for SDT is keServiceDispatchTableFarProc - moduleHandle.

And this is the place where I don't know what to do next?
Can you tell me the simplestr method of locating KiServiceTable in ntoskrnl.exe file?

Thank you.
 #9583  by rkhunter
 Tue Nov 08, 2011 3:09 pm
After you get keServiceDispatchTableFarProc, you need to walk by fixups for analyze code sections for special instruction -
mov _KeServiceDescriptorTable.ntoskrnl.ServiceTable, offset _KiServiceTable.

Look this function.
Code: Select all
DWORD GetSsdtAddress(PUCHAR pNtoskrnl, PDWORD ImageBase)
{
	PIMAGE_DOS_HEADER dos_hdr=NULL;
	PIMAGE_NT_HEADERS nt_hdr=NULL;
	PIMAGE_OPTIONAL_HEADER nt_opt_hdr=NULL;
	PIMAGE_BASE_RELOCATION query_reloc_block=NULL;
	PUCHAR pSDT = NULL;
	PDWORD pSSDT = NULL;
	
	struct BASE_RELOCATION_ENTRY {
		WORD PageOffset : 12;
		WORD Flags : 4;
	} *RelocEntry = NULL;

	pSDT = (PUCHAR)GetProcAddress((HMODULE)pNtoskrnl, "KeServiceDescriptorTable");

	if(!pSDT) return 0;
	
	dos_hdr = (PIMAGE_DOS_HEADER)pNtoskrnl;
	nt_hdr = (PIMAGE_NT_HEADERS)(dos_hdr->e_lfanew + pNtoskrnl);
	nt_opt_hdr = &nt_hdr->OptionalHeader;

	*ImageBase = nt_opt_hdr->ImageBase;

	if(nt_hdr->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
		return 0;

	for(query_reloc_block = (PIMAGE_BASE_RELOCATION)
			(nt_opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + pNtoskrnl);
			query_reloc_block->SizeOfBlock;
		query_reloc_block = (PIMAGE_BASE_RELOCATION)((PUCHAR)query_reloc_block + 
			query_reloc_block->SizeOfBlock)) 
	{
		
		ULONG cRelocsInBlock = (query_reloc_block->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION))/sizeof(WORD);
		RelocEntry = (BASE_RELOCATION_ENTRY*)((PUCHAR)query_reloc_block + sizeof(IMAGE_BASE_RELOCATION));

		for(ULONG i = 0; i < cRelocsInBlock; i++ ) 
		{
			PUCHAR pRelocPlace;
			DWORD RelocFixedContent;
			
			if(RelocEntry[i].Flags != IMAGE_REL_BASED_HIGHLOW) continue;

			pRelocPlace = RelocEntry[i].PageOffset + query_reloc_block->VirtualAddress + pNtoskrnl;
			RelocFixedContent = *((PDWORD)pRelocPlace) - nt_opt_hdr->ImageBase + (DWORD)pNtoskrnl;

			if(RelocFixedContent == (DWORD)pSDT) 
			{
				//check on mov _KeServiceDescriptorTable.ntoskrnl.ServiceTable, offset _KiServiceTable
				//instrucsion
				if(*((PSHORT)pRelocPlace - 1) == 0x5c7) 
				{
					return (DWORD) (*((PDWORD)pRelocPlace + 1) - nt_opt_hdr->ImageBase);
				}
			}
		}
	}

	return 0;
}
Note that:
Code: Select all
pNtoskrnl = (PUCHAR)LoadLibraryEx(ImagePath, 0, DONT_RESOLVE_DLL_REFERENCES);

if(!pNtoskrnl) {
	PrintError(L"InitSsdtProtection");
}
Note, that _KeServiceDescriptorTable.ntoskrnl.ServiceTable not initialize in file, only in memory.