Thanks!
Nope. They are almost completely undocumented. There are various resources
out on the Internet. The functions accessible from user mode are all found
in ntdll.dll. Some are documented in the Windows DDK. Many aren't. If you
disassemble one, the code will look something like this:
mov eax, <service number>
lea edx, [esp+4]
int 2E
On XP, the setup will look the same but it will use syscall instead of int
2E.
Remember - the service numbers can change for each build of Windows!
-Matt
>Does anyone know where I can find a list of the sevices offered by int 2Eh?
>I assume there has to be an include file somewhere with these defined.
Try (Table 02586) in RBIL. (a little big to include here)
--
Arargh (at arargh dot com) http://www.arargh.com
To reply by email, change the domain name, and remove the garbage.
(Enteract can keep the spam, they are gone anyway)
There are a couple of approaches that can be taken to acquire the service
call.
One attempt is to load the ntdll.dll via LoadLibrary() and obtain the entry
point for a known function. I assume since I know most of the Nt<func>
functions, I can programmatically
create a list of these names and query the dll (via GetProcAddress()) for
each function.
In order to get the service number (which is loaded into EAX), some
assembler code could be used to obtain the variable offset +4 bytes from the
address returned by GetProcAddress().
Here's a snippet from WDM explaining the theory.
---- snippet
I can find the service number for NtUserGetProcessWindowStation() by using
GetProcAddress() to locate the address for GetProcessWindowStation() in
user32.dll. Using the address returned by GetProcAddress(), I retrieve the
service number by reading a DWORD value starting one byte past that address.
Once I have the service number for NtUserGetProcessWindowStation(), I simply
add one to get the service number for NtUserGetStats(). The same trick also
works for NtGdiGetStats() using GetProcAddress() to locate
GdiGetSpoolMessage() in gdi32.dll. GdiGetSpoolMessage() is the user-mode
wrapper for NtGdiGetSpoolMessage() in win32k.sys. I add one to the service
number for NtGdiGetSpoolMessage() to find the service number for
NtGdiGetStats().
------
What do you think?
Mike
"Matt Taylor" <pa...@tampabay.rr.com> wrote in message
news:eVY5a.18774$163.6...@twister.tampabay.rr.com...
If you want more flexibility in finding service routines, you can always
look at the file yourself (without LoadLibrary). The export table has all
the names, and you can match all functions beginning with Nt or Zw.
-Matt
"Mike" <no_...@hvc.rr.com> wrote in message
news:byZ5a.71040$9U3....@twister.nyroc.rr.com...
The ordinal (not service number), name and entry point is visible in quick
view.
Yes I can disassemble the binary to get the service numbers, but I want to
find out the name of the function that's relevant to that service number.
That's my ultimate goal.
Thanks
Mike
"Matt Taylor" <pa...@tampabay.rr.com> wrote in message
news:Ii06a.22705$0n2.4...@twister.tampabay.rr.com...
-Matt
"Mike" <no_...@hvc.rr.com> wrote in message
news:PI56a.11043$%r1....@twister.nyroc.rr.com...
However, I see I can do an ASM dump of the dll also.
Is it logical to...
1) add the entry point address to the base address, this will be the start
of the function? I think this assumption is correct as seeking to this point
resembles stack preservation instructions (push esp, etc.)
Thanks a lot, I really appreciate it.
Mike
"Matt Taylor" <pa...@tampabay.rr.com> wrote in message
news:Hfc6a.31885$0n2.4...@twister.tampabay.rr.com...
-Matt
"Mike" <no_...@hvc.rr.com> wrote in message
news:ugq6a.13379$%r1....@twister.nyroc.rr.com...
The base address of a _loaded_ EXE or DLL + the offset gives the real
address of the entry point.
In the EXE or DLL file on _disk_, you can't safely seek to that address
unless the blocks on disk are the same size as the blocks when loaded into
memory, and they don't have to be. To calculate where in the file image the
entry point is located, you must calculate it. For example (output from
DUMPBIN):
...... cut
OPTIONAL HEADER VALUES
10B magic #
5.12 linker version
4C00 size of code
4E00 size of initialized data
0 size of uninitialized data
28A0 RVA of entry point
1000 base of code
6000 base of data
1000000 image base
1000 section alignment <==== note
200 file alignment <==== note
5.00 operating system version
5.00 image version
4.00 subsystem version
0 Win32 version
C000 size of image
600 size of headers
16CA4 checksum
2 subsystem (Windows GUI)
...... cut
SECTION HEADER #1
.text name
4A84 virtual size
1000 virtual address
4C00 size of raw data
600 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
...... cut
Assume this an EXE file, and we are looking for a function with an RVA of
0x28A0 (the entry point). Then any function with an RVA of 0x1000 to 0x5A84
lives in this section, so our function does too. The file pointer is 0x600:
to seek to the function start, you add 0x600 to 0x28A0 to find it, or (you
do the math).
1. You need to read each PE header to get the section alignment (normally
0x1000 as in this example) and the file alignment (some multiple of 0x200,
0x200 in this example).
2. You need to search through each section to find the virtual address it
covers, and whether the function lives there.
3. You need to offset from the file pointer to the RVA.
A good tutorial on PE headers can be found at msdn.microsoft.com. Search for
"Inside Windows - An In-Depth Look into the Win32 Portable Executable File
Format" by Matt Pietrek.
--
Regards
Alex McDonald
> Assume this an EXE file, and we are looking for a function with an RVA of
> 0x28A0 (the entry point). Then any function with an RVA of 0x1000 to
0x5A84
> lives in this section, so our function does too.
If it's not too much to ask, please show me an example. I started to read
the article from MSDN, however I didn't finish :)
Thanks!
Mike
I assume when dumpbin is run, it's not loaded into memory?
"Alex McDonald" <alex...@btopenworld.com> wrote in message
news:b3e050$pun$1...@sparta.btinternet.com...
Anyway, in answer to your question:
The PE file is laid out with sections. The loader reads the first 512 bytes
or so (all the headers & section data), and then it loads the section data
into memory. Data directories and the headers have "RVAs" (Relative Virtual
Addresses) in them -- these are offsets from the base address field in the
PE "optional" header.
What Alex is pointing out is that when you read the file on disk, it is a
mistake to use the RVA as an offset in the file. The RVA (1000h) of the
section he pointed to is not the same as the offset (200h) in the file. When
you want to get a file offset based on RVA, you have to search the list of
sections. Each section has a virtual base and virtual length. If the RVA
lies within that section, the formula for the offset is this:
virt_addr = rva + pe.imagebase;
if (virt_addr >= section.virtual_offset &&
virt_addr < (section.virtual_offset + section.virtual_len))
{
file_offset = section.file_offset + (virt_addr - section.virtual_offset)
}
It gets a little trickier because the section has a "raw length" (length of
section on disk). If this is less than the virtual length, the section is
padded at load-time to the virtual length with 0's. However, you needn't
worry about all these details -- just load with LoadLibrary and traverse the
PE structures in memory and you will avoid this headache.
-Matt
"Mike" <no_...@hvc.rr.com> wrote in message
news:OHK6a.18195$%r1.1...@twister.nyroc.rr.com...
You right, I got thrown by the reference to "seek" in Mike's post, and
thought he was trying to blat up ntdll.dll on disk.
--
Regards
Alex McDonald
Mike
"Matt Taylor" <pa...@tampabay.rr.com> wrote in message news:<miN6a.39970$Cv4.7...@twister.tampabay.rr.com>...