A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #29948  by evelyette
 Fri Feb 10, 2017 11:01 pm
Hi,

The http://www.rohitab.com/discuss/topic/42 ... functions/ article obtains the indexes of SSDT entries by doing the following:

1. ZwOpenFile: Open the "\SystemRoot\System32\ntdll.dll" file.
2. ZwQueryInformationFile: Obtain the information about a file, like its file size.
3. ExAllocatePool; Allocate nonpaged pool of memory for the entire file.
4. ZwReadFile: Read the entire file into allocated nonpaged memory.
5. ExAllocatePool: Allocate a nonpaged pool of memory for pINH->OptionalHeader.SizeOfImage.
6. memcpy: Copy the headers and sections of the executable file into the allocated memory.
7. Walk over export table to locate the function we're interested in.
8. Return the index of the found entry.

I'm interested in code optimization. We could've used the following functions istead:

1. ZwOpenFile: Open the "\SystemRoot\System32\ntdll.dll" file.
2. ZwCreateSection: Create a section object of the opened file.
3. ZwMapViewOfSection: Create a section view giving us a view of the file.
4. Walk over export table to locate the function we're interested in.
5. Return the index of the found entry.

1. The ZwMapViewOfSection returns BaseAddress, which is a pointer to the address of the view. We can use this address to read the contents of the entire file; when we're walking over the image exports and locating the actual function (that can be anywhere in the file), the file will be read into the program automatically. This enables us to use far less memory than if we would read in a whole file directly. Do you have any doubts about this techniques and whether or not the memory from the ntdll.dll is made available in the section view when we traverse the DLL's export table (and afterwards access the exported function we're looking for).

2. Instead of opening the "\SystemRoot\System32\ntdll.dll" file (with ZwOpenFile) and creating a section (with ZwCreateSection), can we instead use ZwOpenSection on the "\\KnownDlls\\ntdll.dll"? I have the following code, where the ZwOpenSection returns error status code 0xC000003B. Do you have any idea why that status error code is returned?
Code: Select all
HANDLE hSection;
UNICODE_STRING name;
RtlInitUnicodeString(&name, L"\\KnownDlls\\ntdll.dll");

OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
oa.ObjectName = 0;

NTSTATUS status = ZwOpenSection(&hSection, SECTION_MAP_READ, &oa);
Is there any way we can use the "\\KnownDlls\\ntdll.dll" section object directly, without having to use ZwOpenFile/ZwCreateSection, but rather use ZwOpenSection directly. If I use WinObj, the \KnownDlls\ntdll.dll doesn't actually have Read access regardless of the group. However, I don't think this is playing a role here, since we're doing the above in a windows driver from a kernel-mode.
ntdll.png
ntdll.png (51.03 KiB) Viewed 452 times
 #29954  by Brock
 Sun Feb 12, 2017 7:52 pm
Hello,

Yes, you can retrieve the system service indexes from a mapped view of the already existing KnownDlls\ntdll.dll section. You have to open the section first with SECTION_MAP_READ then map the view into kernel space with PAGE_READONLY, locate the export directory (RtlImageDirectoryEntryToData) and once you've located the exported API address of interest add your architecture-specific offset to this pointer (+1 for x86, +4 for x64) and dereference it. You'll have your service index then. Don't forget to unmap the section view and close the view handle when done.

P.S: Your code doesn't work because you initialized the object attributes with the section name correctly but then immediately below this you assign the object name to NULL which cancels the above assignment of your section name out resulting in a bad syntax NTSTATUS error. I am not sure if this works on 8/8.1 or 10 but it does on Windows 7 and below. You'll have to see for yourself
 #29963  by evelyette
 Mon Feb 13, 2017 6:50 pm
Brock wrote:Hello,

Yes, you can retrieve the system service indexes from a mapped view of the already existing KnownDlls\ntdll.dll section.

You have to open the section first with SECTION_MAP_READ then map the view into kernel space with PAGE_READONLY, locate the export directory (RtlImageDirectoryEntryToData) and once you've located the exported API address of interest add your architecture-specific offset to this pointer (+1 for x86, +4 for x64) and dereference it. You'll have your service index then. Don't forget to unmap the section view and close the view handle when done.
Yeah, I got that.
Brock wrote:P.S: Your code doesn't work because you initialized the object attributes with the section name correctly but then immediately below this you assign the object name to NULL which cancels the above assignment of your section name out resulting in a bad syntax NTSTATUS error. I am not sure if this works on 8/8.1 or 10 but it does on Windows 7 and below. You'll have to see for yourself
You're right, after removing that line, the code starts to work as it should. I've put this line in there when loading the "\\SystemRoot\\system32\\ntdll.dll", since otherwise I was getting the STATUS_OBJECT_TYPE_MISMATCH status error code.