Jump to content
MSFN is made available via donations, subscriptions and advertising revenue. The use of ad-blocking software hurts the site. Please disable ad-blocking software or set an exception for MSFN. ×

[Info] How to find code for Windows 2000 Native API Functions


Ximonite
 Share

Recommended Posts

This information is specific to Windows 2000, but how the Native API Functions work and how to find the code for them is similar on other versions of Windows.

Table with every Native API function: https://j00ru.vexillium.org/syscalls/nt/32/

Summary of what Native API Functions are and how they work:

Native API Functions are functions stored in kernel-space but can be called by user-space applications. User-space applications will usually call forwarded exports in kernel32 that point to exports in ntdll. The code an export will eventually reach in ntdll will look like this:

mov     eax, ##h
lea     edx, [esp+4]
int     2Eh
retn    2Ch

A software interrupt is used to transfer code execution to one of the addresses in the System Service Descriptor Table (also known as the KiServiceTable). The KiServiceTable is contained in ntoskrnl and the address of the KiServiceTable is copied to an exported value called KeServiceDescriptorTable. This is the relevant code:

INIT:005535EE        mov     ds:KeServiceDescriptorTable, offset off_472228

This is the most reliable way to find the address of the KiServiceTable. The address may not be 472228, but the beginning of the KiServiceTable will always have this comment at the end of the first line:

; DATA XREF: sub_55351A+D4↓o

Finding the code for a certain Native API Function:

If the name of the Native API Function starts with "Nt", then the export in ntoskrnl probably points to the actual function code. Finding the function code may be as simple as that, but most of the time, it isn't. There are a few Nt exports that do not point to the actual function code. In this case, it will point to the same code execution transfer code found in ntdll, but inside of ntoskrnl. These functions will also have a matching function with the same name except for "Zw" instead of "Nt" at the beginning. The export with Zw at the beginning will point to the code that transfers code execution to an address in the KiServiceTable. If the function is one of the few Nt functions which have exports that don't point to the actual function code, or is only a Zw function, then finding the KiServiceTable will be required. To find the KiServiceTable, find the line of code above that copies the KiServiceTable to KeServiceDescriptorTable in ntoskrnl. The address 5535EE will most likely be where this code is. In the example code above, the KiServiceTable is located at address 472228. The KiServiceTable will look like this (only the first 16 lines shown here):

off_472228      dd offset sub_4C5C12    ; DATA XREF: sub_55351A+D4↓o
                dd offset sub_4FA4EE
                dd offset sub_4FD362
                dd offset sub_4FA518
                dd offset sub_4FD398
                dd offset sub_45BE3E
                dd offset sub_4FD3D8
                dd offset sub_4FD418
                dd offset NtAddAtom
                dd offset sub_4F63E6
                dd offset NtAdjustPrivilegesToken
                dd offset sub_4E5660
                dd offset sub_4E5616
                dd offset NtAllocateLocallyUniqueId
                dd offset sub_44AB84
                dd offset NtAllocateUuids

The first address will correspond with value 00h in this code:

mov     eax, ##h
lea     edx, [esp+4]
int     2Eh
retn    2Ch

The next will correspond with 01h, then 02h, etc.

Edited by Ximonite
Added table with all Native API functions
  • Like 2
Link to comment
Share on other sites


This still holds true for x64 Windows, where x86 and x64 versions of an ntdll function lead to one ntoskrnl function. So now I need to determine why the NtQueryInformationProcess implementation was good enough for x64 but not x86 K32* functions on Vista.

So much to learn!

And also user32/win32k should have a similar relationship for many of the former's functions, but what I've seen so far in win32k is ambiguous. There are offsets leading to tables like that, but they're scattered all over the place and not all of them lead to a function.

Link to comment
Share on other sites

17 hours ago, win32 said:

And also user32/win32k should have a similar relationship for many of the former's functions, but what I've seen so far in win32k is ambiguous. There are offsets leading to tables like that, but they're scattered all over the place and not all of them lead to a function.

win32k declare own ring3->ring0 service table for user32 and gdi32

see KeAddSystemServiceTable() inside win32k

  • Upvote 1
Link to comment
Share on other sites

OK, on Windows Vista x64 it is w32pServiceTable. I was looking at the 8.1 x64 version earlier and checked w32pServiceTable but it seemed all odd to me there.

Windows 2000 has no w32pServiceTable, though there is also a call to ntoskrnl.KeAddSystemServiceTable somewhere in its win32k. Right above this is

push    offset off_A0170400   ;the offset in 5.0.2195.7399 anyway.

The user32/gdi32 stubs seem to follow a similar pattern to ntdll ones, but the values being copied to eax seem to start at 1000h instead of 0. On Windows 2000 it seems that gdi32 takes some priority over user32 in the table.

Edited by win32
Link to comment
Share on other sites

Something I want to do is port some Windows XP Native API functions to Windows 2000.

Since every entry in the KiServiceTable corresponds to a function, I wonder if the KiServiceTable can be expanded or if there's a different way to add these functions to ntdll, since the functions could call ntoskrnl functions (NtModifyBootEntry does).

Link to comment
Share on other sites

On 11/2/2020 at 2:29 PM, Ximonite said:

I wonder if the KiServiceTable can be expanded or if there's a different way to add these functions to ntdll, since the functions could call ntoskrnl functions (NtModifyBootEntry does).

How important/easily refactorable is the code immediately below the current end to the KiServiceTable? IDA spazzes out on my copies of win2k's ntoskrnl, but right below it on my win2k3 version is a snippet that does get lots of calls to it though.

win32k in Vista seems to have a function that declares the end of its service table. But there isn't one on 2000 ntoskrnl so I think you can just move code around and add stuff to the table without harm (actually that link shows there is a ServiceLimit, but I think it would be easy to change and is not its own function seemingly).

Alternatively, you could change the offset that is used by KiServiceTable and recreate it somewhere else where it isn't bound by code. But it would be a painstaking process. If you can simply move (in the assembly sense of the term, since it's a copy as opposed to a proper move - why is it mov and not cpy?) around an export table while leaving it intact, perhaps someone could write a program that can move a service/dispatch table.

this is what I'll probably read at next breakfast:

https://resources.infosecinstitute.com/topic/hooking-system-service-dispatch-table-ssdt/

Edited by win32
Link to comment
Share on other sites

On 11/5/2020 at 12:16 AM, win32 said:

How important/easily refactorable is the code immediately below the current end to the KiServiceTable? IDA spazzes out on my copies of win2k's ntoskrnl, but right below it on my win2k3 version is a snippet that does get lots of calls to it though.

Here is what I found right after the KiServiceTable:

dword_472614    dd 0FBh                 ; DATA XREF: sub_55351A+FD↓r
unk_472618      db  18h                 ; DATA XREF: sub_55351A+102↓o
                db  20h
                db  2Ch
                db  2Ch
                db  40h
                db  2Ch
                db  40h
                db  44h
                db  0Ch
                db  18h
                db  18h
                db  08h
                db  04h
                db  04h
                db  0Ch
                db  10h

The dword value is the amount of entries in the KiServiceTable.

The other values below (only the first 16 shown) are the amount of bytes popped from the stack at the end of each function.

Edited by Ximonite
Removed "+ 4" because it's not accurate.
Link to comment
Share on other sites

On Server 2003, they were moved to somewhere else in .text, decoupled from KiServiceTable, so I'd think those would be movable in 2000 as well. Also doesn't seem like a pain to refactor either, so you're lucky.

Link to comment
Share on other sites

  • 1 month later...

I found this article very interesting to the subject of implementing system services, even if it's about the WRK:

http://web.archive.org/web/20090707233000/http://www.dcl.hpi.uni-potsdam.de/research/WRK/?p=28

And also check these out:

https://j00ru.vexillium.org/syscalls/nt/64/

https://j00ru.vexillium.org/syscalls/win32k/32/

https://j00ru.vexillium.org/syscalls/win32k/64/

Edited by win32
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    No registered users viewing this page.


×
×
  • Create New...