Hey guys! I was looking at y0da's kernel32.dll image base discovery example and have a question. How did he come up with 0x70000000 as the starting point in memory to begin looking for kernel32's PE header. Is there something special about this address in memory?
Posted on 2003-02-01 17:34:39 by rdaneel
MSDN Platform SDK
A well-behaved application has its DLLs rebased so they each fall within a unique range of the virtual address space. The system DLLs are currently based in memory from 0x70000000 to 0x78000000 (0x68000000 to 0x78000000 on MIPS).
Posted on 2003-02-01 20:55:49 by BubbaFate
Thanks BubbaFate.

That leads me to my real point in researching this topic. I am trying to patch the export table of NDIS.SYS using a kernel mode driver. Where do I start from in memory to search for the PE header of ndis.sys so that I can patch the export table. I can handle the KMD and the PE search logic. I just don't know where to start to avoid a catastrophe in ring0. Maybe there is a better way than searching through contiguous memory registers. Any suggestions are appreciated. My point for this project is to make a GRE bridge driver that tunnels GRE packets over UDP. I think this is the right forum to post in because it isn't really a network question at this point.
Posted on 2003-02-01 22:24:59 by rdaneel

This is sounding very much like a subject that should not be addressed here, the US Digital Millenium Copyright Act legislation makes it an offence in the US to do what you are after.


See next post.


Posted on 2003-02-02 02:16:50 by hutch--
rdaneel has PM'd me about the direction he is working in and it is a fully legitimate programming posting about a driver for the internet.

I have re-opened the thread for this reason.

If anyone wants to post question that can be seen as working in the cracking area, PLEASE make a point of describing what the question is about because it will be censured and removed if it even looks like illegal content.


Posted on 2003-02-02 17:30:00 by hutch--
Good stuff hutch ;)

I was interested in following the logic behind searching a memory space for a PE header, as opposed to using GetModuleHandle() to find the start address.....
Posted on 2003-02-02 19:54:07 by sluggy
y0da's example on icz's site is what originally prompted the question about searching memory for the PE. His example is designed to show how to do it without using any API calls. I don't care either way about that. I am just trying to find the header for ndis.sys using a KMD. This will allow me to interface with all incoming and outgoing packets on a machine by redirecting some of ndis.sys's functions to my own functions. You can read about it here:


From what I understand, this is the technique used by Zone Alarm.
Posted on 2003-02-02 20:21:45 by rdaneel

I have no idea how the Ring0 api's differ in a KMD vs a vxd, I haven't got Win2K yet to try coding one unfortunately, but I think you could use a similar strategy to how you might do it in Win98 by using VxDCall VXDLDR_GetDeviceList to access the VxD_Desc_Block structure of NDIS.SYS and the pointer to its Service_Table_Ptr which should be contained therein. This should give you direct access to all its exported functions without having to do any PE header walking.

You'll have to check your VxD_Desc_Block structure on your own OS, there seems to be a discrepancy between the 98DDK definition of it and the one in VMM.INC, and even how it might look on your system. The new DDK might have a corrected structure. It should be easy to find which DWORD offset to the Service_Table_Ptr in the structure is the one you want though by examining the address in a debugger, this should be a pointer to an array of addresses to each of the exported functions.

This is a partial structure from Vmm.inc, some of the members may be different in Win2K, but you should be able to find the Service_Table_Ptr as an offset from the DDB_Name.

VxD_Desc_Block STRUC
DDB_Next DD ?
DDB_Dev_Major_Version DB 0
DDB_Dev_Minor_Version DB 0
DDB_Flags DW 0
DDB_Name DB " "
DDB_Service_Table_Ptr DD 0
DDB_Service_Table_Size DD 0
DDB_Win32_Service_Table DD 0
DDB_Prev DD 'Prev'
DDB_Size DD SIZE(VxD_Desc_Block)
DDB_Reserved1 DD 'Rsv1'
DDB_Reserved2 DD 'Rsv2'
DDB_Reserved3 DD 'Rsv3'
VxD_Desc_Block ENDS

To find the VxD_Desc_Block you can use VxDCall VXDLDR_GetDeviceList for dynamic drivers, and VMM_GetVxDLocationList for static ones. This code should find the DDB_ Structure for ndis.sys, then you can access the Service_Table_Ptr of exports from there.

VMMCall VMM_GetVxDLocationList
or eax, eax
jz EHandler
;mov [TableAddress], eax
;mov [VxDCount], edx
;mov [TableSize], ecx

; Returns the address of the VxD location list in EAX,
; returns the count of VxDs in EDX, and
; returns the list size (in bytes) in ECX.
; Uses EAX, ECX, and EDX.

; Returns the address of the VxD if the function
; succeeds; otherwise, sets the zero flag.
; The VxD location list is a packed array of variable
; length Device_Location_List structures.

; The Device_Location_List structure will give you
; a linked DDB list for statically loaded vxds:

; Device_Location_List STRUC
; DLL_NumObjects DB ?
; DLL_ObjLocation DB SIZE ObjectLocation * 1 DUP (?)
; Device_Location_List ENDS

.while edx !=0
mov eax, [eax]
or eax, eax
jz @F
lea ecx, dword ptr [eax+0Ch] ; DDB_Name

.if dword ptr [ecx] == 'SIDN' ; "NDIS"
; FOUND DDB_Name field of VxD_Desc_Block
jmp @F

dec edx

Things might be different in Win2K, but if you can find the VxD_Desc_Block and Service_Table_Ptr directly it should be straightforward.

Hope this helps,

PS sluggy, there's more than a few examples around on how to search for the PE header of system dlls and walk the import or export directories, I'm fairly sure y0da's site has something like that. ;)

EDIT: ...thinking about it... I may be totally off base here and into left field in how a Win2K sys driver differs from the Win98 vxd version, I'm basing all this on my ndis driver, if so I apologize.

This will only give you a pointer to the array of export addresses, unless you know for sure the offset to the particular function(s) you want to modify it might not be foolproof. If you're sure of the ndis.sys version you'll be dealing with you could probably hardcode in the proper offset (a quick disassembly should confirm the proper value), but if not you'll still need to find another table confirming the name and order of the functions.

I'm not even 100% sure if the Service_Table_Ptr is "THE" Export table that the system uses and which addresses you need to modify to point to your own function, or whether this is just included to access the addresses for direct calling. Unless you're willing to patch the beginning of the functions themselves to point to your new code, rather than changing the original export table pointers to them, it might boil down to a header search and walk after all...

In a regular memory scan for a PE header you can use the fact that all system dll offsets are aligned to 1000h and check for a MZ header with something like

mov edx, _Address
; Address of API function (i.e. BFF7xxxx in Kernel32.dll)
xor dx, dx ; Align to 1000h

.if word ptr [edx] != 'ZM'

sub edx, 1000h ; search previous page
cmp word ptr [edx], 'ZM' ; MZ header?
jne previous_page ; If not, then keep searching

Posted on 2003-02-02 23:31:40 by Kayaker

Is there another place i can get those doc's. I tried that link but i will not go through on my machine...
I always wanted to do a firewall but never had a clue where to start.

Thanks for starting this thread
Posted on 2003-02-03 04:14:10 by cmax
In a regular memory scan for a PE header you can use the fact that all system dll offsets are aligned to 1000h and check for a MZ header with something like

Yeah it is true...

Posted on 2003-02-03 06:13:26 by roticv

Any Progress? I wanted to know before I went down this path. :)
Posted on 2003-02-10 07:22:48 by packetvb
I have kind of switched gears on this matter. I intend to take it up later but for now I am getting what I needed out of the winpcap library. I am in the middle of playing with packet32.dll and it has lots of potential. Sorry I didn't respond sooner.:rolleyes:
Posted on 2003-04-12 12:59:32 by rdaneel

I know this is a month old, but i was curious, are you trying to make a firewall?

I looked in to this a while back, after first looking at making a layered service provider i realized that I had to go lower than the winsock. That when I found the winpcap. However last I checked the winpcap could only look at the packet data and really couldnt drop or redirect them. So Its on the back burner for now. :(

Id be really interested in what direction your moving now?

Posted on 2003-04-20 23:27:35 by packetvb

You may not have to fuss arround at driver level. Under 2k+ you can open a raw socket and monitor the trafic :)
Posted on 2003-04-21 04:14:01 by Axial
monitor... but not intercept+modify/block.
Posted on 2003-04-22 01:50:28 by f0dder