Analyze Windows NT / 2000 Heap Insection and Virtual Memory Organization
Webcrazy
http://webcrazy.yeah.net/)
When discussing this topic today, I think it should be repeatedly referencing two books:
Matt Pietrek
<< Windows 95 System Programming SECRETS >>
Jeffrey Richter
<< Programming Microsoft Windows, Fourth Edition >>
The two have fully elaborated from the core state and the user state, which is fully elaborated with Windows (although not a Windows NT / 2000) of the heap memory and virtual memory management and organization. Before reading, it is best to browse browsing. I don't explain some basic APIs or concepts.
First talk about the organization of the stack of memory. Some core data structures in Windows NT / 2000 tissue stacks are stored in process PEB. The following member is defined in the PEB structure (I don't confirm the structure of the PEB):
Typedef struct _peb
{
.
.
.
PVOID processheap; // The default pile address of the process is 0x18 after PEB.
.
.
.
Ulong Numberofheaps; // The number of current piles, 0x88 after PEB
Ulong maximumnumnumnumnumberofheaps; // The maximum number of piles can be owned by the process, located at the 0x8c after PEB
PVOID ** processHeaps; // The address list of all piles in the process is located at the 0x90 after PEB.
.
.
.
} PEB, * PPEB;
For the address of PEB and its preliminary analysis, please refer to my
"Treatment of WINDOWS NT / 2000 module". In order to better understand, I will list some of the Softice's partial analysis process:
: AddR cmd // below will only target CMD.exe processes
: Heap 32 cmd // Displays the pile of CMD processes
Base ID CMMT / PSNT / RSVD Segments Flags Process
00130000 01 0025/0024 / 00db 1 00000002 cmd
|
| _ Process default pile addresses (in the Windows platform, it is also used as the handle of the process stack to the user)
00230000 02 0003/0002 / 000D 1 00008000 cmd
007C0000 03 0008/0008/0008 1 00001002 CMD
00800000 04 0004/0004 / 000C 1 00001002 CMD
:? #Dword (@ (7FFDF000 18)) // Displays the address of the default pile of the process
00130000 0001245184 "" "
: DD 7FFDF000 88 L 10 // Displays several members related to HEAP in PEB, see
0010: 7FFDF088 00000004 00000010 77fCE380 00450000 ........... W J.
| | | | |
| | | | ProcessHeaps Value, Windows 2000 Provides API GetProcessHeaps
| | | | List of all piles for enumeration processes
| | _MAXIMUMNUMBEROFHEAPS value
| _ NumberOfheaps value
: DD @ (7FFDF000 90) L DWORD (@ (7ffdf000 88)) * 4
0023: 77fce380 00130000 00230000 007C0000 00800000 ... # ... | .....--------------------------- -----------
|
| _CMD process currently all of the addresses of all piles (one to the HEAP 32 command to Softice)
The above analysis is only for the rough description of the heap, and the Windows NT / 2000 provides the Heapwalk API for debugging purposes, which can traverse the contents of the specified stack. Softice's HEAP 32 command plus -w parameters can also traverse these content. In Windows NT / 2000, the HEAP (RTLHEAP) header is provided for the operation of the plot memory, and the internal Windows NT / 2000 of these functions finally calls VirtualAlloc or the like to implement memory. And this is the part I have to discuss below about virtual memory. Since the operation in Windows NT / 2000 in the heap is very frequent, in order to avoid frequent runoffs, some of the main data structures of HEAP memory store in the PEB structure of the user-state space, not in the kernel space. KPEB. To be familiar with the PE loading routine (LDR "), you have to look at the Microsoft CRT source code. CRT code About establishing CRT uses piles (mainly supplied to new syntax) to understand HEAP applications can have comparison Understand, such as Heapinit.c, HeapHook.c, Heapdump.c, Heapwalk.c, and so on.
Let's talk about the organization of virtual memory. The structure constituting the virtual memory management basis is VAD (Virtual Address Descriptors). Since the Windows NT / 2000 memory subsystem really assigns actual physical storage space when you really use the storage space, the kernel provides VAD software to store some of the data for virtual memory space retention, submission. The VAD structure is located in EPRocess (KPEB):
KD>! Processfields
EPROCESS STRUCTURE OFFSETS:
.
.
.
VADROOT: 0x194
.
.
.
VAD uses a binary tree structure, from the output of the above I386kd / windbg, you can see the location of the VAD in KPEB. Softice's query command can export a very important structure in this system, below I list the function that implements this command:
/ / -------------------------------------------------------------------------------------------- -----------------
//
// QuerySystemProcessvad - Portion Cut from "undocumented windows NT"
// Rewrite by Webcrazy (http://webcray.yeah.net) on 11-20-2000!
@ // only test on Windows 2000 Server Build 2195!
//
/ / -------------------------------------------------------------------------------------------- -----------------
#define max_vad_entries 0x200
#define vadoffset 0x194
Typedef struct vad {
Void * StartingAddress;
Void * endingaddress;
Struct Vad * Parentlink;
Struct Vad * LeftLink;
Struct Vad * RightLink;
Ulong flags;
Ulong mmci;
Ulong Protopte;
VAD, * PVAD;
#pragma pack (1)
Typedef struct vadinfo {
Void * vadlocation;
VAD VAD;
VADINFO, * PVADINFO;
#pragma pack ()
Vadinfo Vadinfoarray [MAX_VAD_ENTRIES]; int VadinfoarrayIndex;
PVAD VADTREEROOT;
Void _stdcall VadtreeWalk (PVAD VADNODE)
{
IF (vadnode == null) {
Return;
}
VADTreeWalk (Vadnode-> LeftLink);
IF (VADINFOARRAYINDEX Vadinfoarray [vadinfoarrayindex] .vadlocation = vadnode; Vadinfoarray [VADINFOARRAYINDEX] .vad.startingaddress = Vadnode-> StartingAddress; Vadinfoarray [VADINFOARRAYINDEX] .vad.endingaddress = VADNODE-> EndingAddress; (Ulong) Vadinfoarray [VADINFOARRAYINDEX] .vad.startingaddress << = 12; (Ulong) Vadinfoarray [VADINFOARRAYINDEX] .vad.EndingAddress = 1; (Ulong) Vadinfoarray [VADINFOARRAYINDEX] .vad.EndingAddress << = 12; (Ulong) Vadinfoarray [VADINFOARRAYINDEX] .vad.EndingAddress- = 1; Vadinfoarray [vadinfoarrayindex] .vad.parentlink = Vadnode-> Parentlink Vadinfoarray [vadinfoarrayindex] .vad.LeftLink = Vadnode-> LeftLink; Vadinfoarray [VADINFOARRAYINDEX] .vad.rightlink = Vadnode-> RightLink; Vadinfoarray [VADINFOARRAYINDEX] .vad.flags = Vadnode-> Flags; IF (vadnode-> mmci> 0x80000000) Vadinfoarray [VADINFOARRAYINDEX] .vad.mmci = vadnode-> mmci; Else Vadinfoarray [VADINFOARRAYINDEX] .vad.mmci = 0; IF (Vadnode-> Protopte> 0x80000000) Vadinfoarray [vadinfoarrayindex] .vad.protopte = Vadnode-> Protopte; Else Vadinfoarray [VADINFOARRAYINDEX] .vad.protopte = 0; VadinfoarrayIndex ; } VADTreeWalk (Vadnode-> RightLink); } void vadtreedisplay () { INT I; DBGPRINT ("/ nvadroot is located @% 08x / n", VADTREEROOT; DBGPRINT ("VAD @ Starting Ending Parent LeftLink RRIGHTLINK FLAGS MMCI PTE / N "); For (i = 0; i DBGPRINT ("% 08X% 08X% 08X% 08X% 08X% 08X% 08X% 08X% 08X / N", VADINFOARRAY [i] .vadLocation, Vadinfoarray [i] .vad.startingaddress, Vadinfoarray [i] .vad.EndingAddress, Vadinfoarray [i] .vad.parentlink, Vadinfoarray [i] .vad.Leftlink, Vadinfoarray [i] .vad.rightlink, Vadinfoarray [i] .vad.flags, Vadinfoarray [i] .vad.mmci, Vadinfoarray [i] .vad.protopte; } } void querysySystemProcessvad () { IF ((USHORT) NTBUILDNUMBER! = 2195) { DBGPRINT ("Only Test On Windows 2000 Server Build 2195! / N"); Return; } // Query System Process Vad VADTREEROOT = (PVAD) * (ULONG *) ((char *) psinitialsystemprocess vadoffset); VadinfoarrayIndex = 0; VadtreeWalk (VADTREEROOT); VADTREEDISPLAY (); } Take a look at the output results of the QuerySystemProcessvad routine: VADROOT IS LOCATED @ fe4DDF28 VAD @ Starting Ending Parent Leftlink Rrightlink Flags MMCI PTE Fe4DDF28 00010000 00042FFF 00000000 00000000 Fe354DC8 04000000 Fe4DD0E8 E1008A40 FF874348 00060000 000000FFF FE354DC8 00000000 FF8389A8 C4000001 0000000000000000 FF8389A8 00070000 00070FFF FF874348 00000000 FF7B72C8 04000000 FF8345A8 E2747880 FF7B72C8 00080000 0017FFFFF8389A8 00000000 00000000 04000000 Fe33DB48 E2936040 Fe354DC8 77F80000 77FF8FFFFFFFF FE4DDF28 FF874348 00000000 07100003 Fe354B68 E1630040 Compare the output of the Query command of the following Softice, compare with the above output: : query system Address Range Flags MMCI PTE Name 00010000-00042000 04000000 Fe4DD0E8 E1008A40 00060000-00060000 C4000001 00070000-00070000 04000000 FF8345A8 E2747880 00080000-0017f000 04000000 Fe33DB48 E2936040 HEAP 77F80000-77FF8000 07100003 Fe354B68 E1630040 NTDLL.DLL Ok, I have already used the two main mechanisms of Windows NT / 2000 user code to use memory (another way may be FilemApping objects) presented in front of you, of course, the internal use methods also involve many content, only Can rely on yourself. Reference: 1.jeffrey richter << Programming Applications for Microsoft Windows, Fourth Edition >> 2.matt Pietrek << Windows 95 System Programming Secrets >> 3. << undocumented windows NT >> supplied source code