Windows 95 System Programming Secrents Learning Notes - Chapter 5 (4)

xiaoxiao2021-03-06  41

GetProcessheap

Use a Win32 HEAP function, first you have a Heap Handle. Most programs use Kernel32 to give a default heap when the program is generated. You can call GetProcessHeap to get its Heap Handle. This function is very simple, it takes out a global variable of the Kernel32, pointing to the Process Database of the current process. There is a handle (handle) of the default stack in which the process is stored.

Heapalloc and Iheapalloc

HeapAlloc, as indicated by its name, you can use it to allocate a memory from a HEAP. It is actually just the work of parameter inspection, and true allocation of memory is done by Iheapalloc and HPalloc. HeapAlloc Checks if the size of the HHEAP is sufficient to accommodate a Heap header. Although it can also check other members such as Signature and Checksum, but it is very strange that it ignores those members. If HHEAP is tested, Heapalloc calls iHEAPAlloc.

Iheapalloc is actually just HPalloc's outsourcing functions. The latter is the real Heapalloc "subject". Before calling HPalloc, IHEAPAlloc has processed dwflags (flags of the caller). The only thing that may survive is Heap_Zero_Memory and Heap_Generate_Exceptions. The value of the former (if survive) is three digits from its original value.

HPalloc

This is the main body of Heapalloc. It first checks if the required block size is too large. Too much means 0x0fffff98 (close to 256MB). Next, HPalloc calls HPTakeSem, which makes Critical Section in the HEAP header. Since then, there is no hitoc in the process to call HPalloc until the HPALLOC ends. In the debug version, HPTakesem also randomly checks if the HEAP is destroyed. Hptakesem can also traverse the entire HEAP, check Checksum and Signature. You can use HeapSetFlags to switch these capabilities. HeapsetFlags joins Windows 95 Time too late, so that I have no way to put it in this book.

HPalloc Nexts to the block size parameters, adjust the multiple of the 4 (also considering the size of Arena). The minimum is 0x18. After subtracting the size of the Arena, only 8 positions left to the user. After knowing the block size, HPalloc can decide to search for the one in four free linked lists. After finding the correct linked list, HPalloc traverses the entire linked list (using the free block PREV pointer) to identify the first large block.

At this time, let's assume that HPalloc finds a large block. So it calls HPCARVE (I will introduce later). The HPCARVE function checks a block to see if it is just big enough, or can be divided into two. If you need to split, HpCarve processes all work, including generating new Arena, initializing Prev and Next. One of the splits is just large enough to meet the needs of HPalloc. Another piece is placed in a free linked list.

After HPCARVE returns, HPalloc initializes the Arena members of the new block. In addition to "getting the HPalloc caller's EIP", and "Checksum for calculating the first three members", the rest is just some simple settings. Finally, HPalloc releases the critical area of ​​the HEAP, returns a pointer, pointing to the first byte after Arena.

If HPalloc does not find a free block, and HEAP allows automatic growth (when pile is generated, dwmaximumsize is specified as 0), HPalloc needs to generate a new SunHEAP. I said before, a subheap is another independent space that contains some HEAP blocks. KERNEL32 is responsible for tracking all SubHeaps, which is to maintain them in a linked list. If you need to generate subheap, Kernel32 will determine its initial size (usually 4KB), and call VMM to leave some Pages. Next, HPalloc calls hpinit to initialize the new SubHeap header. After initialization, HPalloc places it into the list of SubHeaps. Finally, HPalloc jumps to the beginning of the "Search Free Link". I think this time you should find a block of size. In Windows 95, memory in Win32 pile is initially reserved and for committed. If we have 1MB pluck and do not need this 1MB of memory, it will not submit the actual memory page. When the program hits by reserved, the Page Fault will be thrown when the Page is not already written. Therefore, the heap function must determine that the PAGES involved in all uses is a CommIT action. In Windows 95, the system is not using structural exceptions to do a CommIT action.

Heapsize and Iheapsize

Heapsize gets a pointer, pointing to a previously assigned memory and returns its size (excluding Arena).

HeapFree and Iheapfree

HeapFree is only responsible for parameter testing. Real action happens in Iheapfree and X_HeapFree, in addition to release the specified plurality of memory, which also checks if there is a need for free blocks.

HeapRealloc and IheapRealloc

HeapRealloc reclaims its size for a Win32 heap of the original existing. HeapRealloc is only responsible for parameter testing, which is the same as HeapFree.

In Windows 95, IheapRealloc is a little strange, it will re-press DWFLAGS parameters, and the flags can pass are as follows:

HEAP_GENERATGE_EXCESS

HEAP_NO_SERIALIZE

HEAP_ZERO_MEMORY

HEAP_REALLOC_IN_PLACE_ONLY

When redistribution, HeapRealloc needs to be considered:

l New blocks are smaller than the original block.

l The new block and the original block size are similar.

l The new block is larger than the original block. The next block in the heap is free, and can be combined with the original block to form a new block that meets the requirements.

l The new block is larger than the original block. The next block in the heap is not free, or although it is free, it is still unable to meet the requirements after the original block.

Heapcreate

HeapCreate is the root of all Win32 heap functions. Each Win32 program has a default heap before the start. In addition, the program can also call HeapCreate to generate additional stacks. In addition to being used by the application, Kernel32 also calls HeapCreate to generate a heap in global shared memory, and use these stacks to system data structures (such as threads or processes related information)

The process of generating a Win32 heap can be divided into two parts. The first part is to keep the memory and connect it to the pile of the process, and the other part is the initialization pile head.

Heapdestroy and Iheapdestroy

Similar to the functions described above, Heapdestroy just do parameter inspection work, the actual destruction of Win32 heap is done by Iheapdestroy. Destroying Win32 pile is not as simple as the releasing stack. There are two things that make it complicated. First, all the stacks that are not generated by the HEAP_NO_SERIALIZE property holds a critical area object. Iheapdestroy checks if the heap you want to destroy has this object and release it properly. Another complicated reason is the pile of layers. If IHEAPDESTROY is just unlicensed, the pile table will be destroyed. Iheapdestroy must traverse the entire list and update.

After the chain is updated, IHEAPDESTROY calls the _pagefree, release the pile you owns. Call only once may not be enough to release all pages. why? If the heap user has a lot of configuration, or a very large configuration, HeapAlloc may produce additional subheaps and append to the Subheap Link. Therefore, Iheapdestroy must ensure release Main HEAP and any Subheap.

Finally, please pay attention, the system does not automatically call Heapdestroy before the program exits. I speculate that if the address space of the process disappears, all the stacks are released.

HeapValidate

This is a Windows NT function. It scans a Win32 heap to check its consistency. In fact, I can't see any reason that it should not appear in the Windows 95 API.

HEAPCompact

This is also a Windows NT function. It will try to merge free blocks and drop outlined DECOMMIT in Win32 bile. Windows 95 has completed these things in daily maintenance, so it doesn't exist.

GetProcessHeaps

This function is only in the Windows NT series operating system that returns an array composed of a heap handle.

HEAPLOCK

This is also a Windows NT function that gets the critical area of ​​Win32 heap.

HEAPUNLOCK

It is also a Windows NT function that releases the critical area of ​​Win32 heap.

HEAPWalk

It is also a Windows NT function that traverses all blocks of Win32 piles.

notes:

In Windows XP and Windows Server 2003 series, add two new heap functions:

HeapsetInformation

HeapQueryInformation

Win32 Virtual function

Win32 heap function

Virtualalloc

Heapcreate

VirtualaLalkEx

HEAPSIZE

Virtualfree

HEAPALLOC

VirtualFreeex

HEAPREALLOC

Virtuallock

HEAPLOCK

VirtualUnlock

HEAPUNLOCK

VirtualProtect

Heapfree

VirtualProtectex

HEAPDESTROY

VirtualQuery

HeapValidate

VirtualQueryex

HEAPCompact

HeapsetInformation

HeapQueryInformation

GetProcessheap

GetProcessHeaps

Win32 Local HEAP function

Win32 Local Heap and Global Heap functions are left behind. There is no need in Windows 95. Win16's Local HEAP is generated to let EXE or DLL can find its HEAP content without changing the Selector. The existence of Global HEAP is because there is no way to allocate large blocks without processing Selector. Win32 programs in Windows 95 have no two restrictions, so Win32 API can exempt the two sets of functions. However, we know, Win32 API has made some compromises because of the downward compatibility. There are too many Win16 programs to use the Global Heap and Local Heap functions. If you remove them from the Win32 API, the transplantation of the program will not go out of the laboratory, so Microsoft decides to retain them.

For most, Windows 95's Local HEAP and GLOBAL HEAP functions are completely consistent. That is, although GlobalLoccoC and Localalalk are the same as the output function, they use the same kernel32.dll address. GlobalFree and LocalFree are also the same.

The Global Heap function in Windows 95 has little functionality, most of which is just directly jumping into its corresponding Local HEAP function. If it is like GlobalLococ, you will share the same entry point at all and the corresponding Local HEAP function. Most functions receive a hglobal parameter. GlobalAlloc or Localalloc allocated memory is from HPalloc.

notes:

About Local Heap and Global Heap functions, this is not detailed here. Because in Win32 programs, these two groups of functions are not recommended. Its existence is merely to provide downward compatibility.

The list of functions that have existing in Windows 2000 / XP are listed below:

Win32 Local HEAP function

Win32 Global Heap function

Localaloc

GlobalAlloc

Localdiscard

GlobalDiscard

Localflags

Globalflags

Localfree

Globalfree

LocalHandle

Globalhandle

Locallock

GlobalLock

LocalRealloc

GlobalRealloc

Localsize

GlobalSize

Localunlock

Globalunlock

It can be seen that some Windows 95 supported Local Heap and Global HEAP functions do not appear in the list above, the reason is simple, there is no need to exist. It is possible to purely, in the operating system based on the Windows NT kernel, the details of these functions will definitely differ from Windows 95.

Miscellaneous function:

WriteProcessMemory and ReadProcessMemroy

This is a function that is approved to read the memory data of another process. In order to use them, you must first get the handle of another process. However, Win32 API does not provide any convenient practice, so that you can easily achieve this. These two functions are the key function of the Win32 debugger. The debugger is an alternative software belonging to the "must read other process memory data". J

The bottom layer of these two functions is very similar. So I decided to display only one of the virtual code. The only significant difference is that WriteProcessMemory calls VWIN32 0x002A0017 Service, while ReadProcessMemory calls VWIN32 0x002A0016 Service.

WriteProcessMemory first makes synchronous control. It first determines that it does not hold Win16Mutex and Krn32Mutex, then enter "must complete" status - meaning: cannot be switched during execution. The Source Address is then determined in the ARENA located private in the application (both between the 4MB-2GB said in the VMM file). Next, WriteProcessMemory got a pointer, pointing to the source process, and then get a thread link list from him. For some reasons, the "actual memory replication action" VWIN32 Service hopes to get the RING0 Stack address of the current thread of the target process. Once all things come to hand, it requests KRN32MUTEX and calls VWIN32 Server. After Vwin32 Complete its Memory Context, WriteProcessMemory release KRN32MUTEX and calls LeavemustComplete to exit "must complete" status. If there is something wrong in this program, call SetLastError, let the caller know where it is wrong.

GlobalMemorystauts

GlobalMemoryStatus can easily observe the state of memory. This function fills the MemoryStatus structure, like how much Pages have been mapped to the actual RAM, Swap file, and so on. This function is very similar to Win16 MemmanInfo.

GlobalMemoryStatus is actually just a parameter test layer, which only determines one thing: the pointer to the function points to a memory that is sufficient to store the MemoryStatus structure. Don't say how to say, you don't need to initialize the DWLEngth member of the MemoryStatus structure before calling GlobalMemoryStatus.

notes:

Since Windows 2000, Microsoft adds a GlobalMemoryStatusex function that uses the MemoryStatusex structure, which is different from the GlobalMemoryStatus function. Before calling, you need to initialize the DwLengthStatusex structure. Such as:

MemoryStatusex Statex;

Statex.dwlength = sizeof (statex);

GetthreadSelectorentry

When I saw GetThreadselectorentry, I shocked it and also appeared in the Win32 API team. This function does not have any action on the thread. In fact, the HThread parameter is just to test, but it never used it. GetThreadSelectorentry gives you a read-only chance to process the Local Descriptor Tables (LDTS) of System VM. This is a specific Descriptor Table that records the FLAT program area and data area of ​​the Win32 program. The Win16 program is also obtained by obtaining their code areas and data area, and the GlobalAlloc handle. This function is a very useful tool for any exploration system tool software.

It should be noted that this function can only be used in a system using X86 CPU. The SYSTEM VM mentioned here is the X86 virtual machine environment.

If you pass it to getthreadselectorentry a legitimate Selector, you can retrieve a 8BITS structure, the format is the same as LDT Descriptor. Since the Win32 program has a FLAT pointer, you can reach anywhere, so you can use this function to convert a 16:16 address to a FLAT32 address. Then the Win32 program can read the contents of the site, or the data can be written to the site. You can even build Win16's GetSelectorBase and GetSelectorLimit function to build your own Win32 version. The main fun in the Getthreadselectorentry function is on both of LDT Alias ​​and LDT PTR. This is two global variables of kernel32.dll. The LDT PTR contains the linear address of the LDT of the System VM. LDTalias is a Selector value with read and write power to the SELector Table.

Malloc and New from the C / C compiler

Many times, the programmer will ignore the memory management function provided by the operating system, use the C Runtime Library (especially Malloc, and Free functions) to do memory management. C ? As I know, the New operators provided by the C compiler on all PCs are directly corresponding to Malloc, and the Delete operator is corresponding to free. The problem is how these functions use the ability of the underlying operating system?

In this chapter, I have already told you that the heap function (such as HeapAlloc and HeapFree is near Malloc and Free. Does this mean that Malloc and Free are just another packaging of Heapalloc and HeapFree? At least VIUSAL C 4.0, the answer is negative. The only exception is Crtdll.dll - Microsoft's C Runtime Library. In Crtdll.dll, Malloc and New are just simple calls HeapAlloc, Free, and Delete call HeapFree. Crtdll.dll is used in many standards of Windows NT and Windows 95 EXES and DLLs. This is a great idea that Microsoft does not have to hurt their brains for "different C Runtime Library" on different EXE and DLL.

Unfortunately, the C compiler manufacturer does not cover, they don't let everyone use crtdll.dll. Therefore, each EXE may also have a C Runtime Library. This situation will not change in a short time, so we'd better know what the underlying of these Runtime Library is doing.

I don't want to study Malloc and Free. Instead, I will give you enough information, so that you are enough to make self-judgments, how to design your own memory management system.

So far, I have been able to determine. Borland and Microsoft make Runtime Library's Heaps in a similar approach. In fact, in addition to the size, the entire situation has not changed with the Windows 3.1 era. Each EXE and DLL have its own HEAP. If you use three DLLs, there will be four separate Heaps (EXE has one, and there is one of DLLs). The memory allocated by the DLL will come from the HEAP of the DLL. This is different from Win32's Heapalloc, and the latter must be allocated from the EXE HEAP (assuming you always throw the default pile of the process).

The RTLS (Runtime Library) of the C compiler does not use the HEAP function of the operating system such as Heapalloc, which uses its own data structure and memory manager. Thus, it is difficult to use Malloc's memory and the memory obtained by HeapAlloc. As long as the C / C RTL is deep enough, we can learn how to put Malloc's operating system function. I lurked into the original code of Borland C 4.5 RTL. That is a difficult job, I am very happy that you don't have to do it again. The following Call Stack shows how malloC is implemented on Windows 95:

Malloc (HEAP.C)

_getmem (getMem.c)

_VIRT_RESERVE (VirtMem.c)

Virtualalloc (NULL, SIZE, MEM_RESERVE, PAGE_NOACCESS)

Ah, C RTL uses Virtualalloc to allocate a large amount of memory from the operating system, which is the behavior of HeapAlloc. The assigned memory is originally in the reserved status, and then _virt_reserve "commit" --- before they are used. _Virt_reserve is actually just another outsourcing function of VirtualCommit. Is this process sound familiar? Yes, this is the practice of Windows 95. If you need to review, please look back at the two functions of HPCARVE and HPCommit.

RTL does not call Virtualalloc when you call Malloc. They need to set and maintain internal structures and continue to track what block is assigned, what is not ... .. Also maintain a free linked list in order to be able to distribute quickly.

A potential problem is its lifetime when you use RTL. When a DLL is removed and received a DLL_PROCESS_DETACH message, Runtime Library calls VirtualFree and releases the memory that is occupied. If another DLL has a pointer points to a block in this block, the pointer suddenly invalidates. If the DLL is later removed, these pointers are used during their DLL_PROCESS_DETACH process, and the program will be finished, and this error is not easy to find. This experience is learned from people with painful experience.

Then, answer my initial problem, Malloc is basically the compiler version of the HeapAlloc function of Windows 95. But there are at least two key differences. First, each EXE and DLL have their own stacks, provided by RTL, and the memory allocated by HeapAlloc comes from the process set by the system default heap. Under some operational procedure, the heap to use RTL may cause problems. This is not to say that you should avoid using Malloc or New, just tell you what they are, and let you understand the potential issues.

notes:

These two functions belong to Win32 Debugging Funciton, which lists these functions in MSDN 2002.4:

Win32 Debugging Function

ContinueDebugevent

DebugActiveProcess

DebugActiveProcessStop

Debugbreak

DebugBreakProcess

DebugSetProcesskilloneXITKILLONEXIT

Fatalexit

Flushinstructioncache

GetthreadContext

GetthreadSelectorentry

IsdebuggerPresent

Outputdebugstring

ReadProcessMemory

SetthreadContext

WaitfordebugeventwriteProcessMemory

----------------- Chapter 5- -----------------

转载请注明原文地址:https://www.9cbs.com/read-70677.html

New Post(0)