The principle of Windows CE cross-process memory injection

  
Recently, due to the design needs, I have studied the memory layout of WincowsCE. Since I found that there are few documents in this area in China, I formed this example when the research came to an end. Documents, in hopes of throwing bricks to attract jade, get the correction of other masters.

First, the prerequisites for program implementation

Because the Windows system form messages are always delivered to the specified form message function of a specific process. So in the local process (the own application) to get the form of the process belonging to other processes must implement the following two parts:

1, the code that needs to mount the form into the address space of the target process Go in.

2. Execute this code and get the message of the target process form.

These two steps seem simple, but they are more difficult to implement. Because Windows CE is an embedded mobile device operating system, it is very different from the desktop operating system such as Windows 98/2000/XP in terms of kernel design concept and API support. This directly leads to the conventional desktop system using global mouse hook injection /remote thread injection and other methods in the CE is completely unworkable. But the good news is that the remote debugging programs such as remotexxx provided by Microsoft in the development tools make it clear that this goal is not an impossible task. Since Microsoft can do this, it means that there must be a complete set of cross-process memory inside CE. Access/code injection mechanism.

Second, the basic principle of program implementation

After two days of google search, I found an interesting API function not declared in the Microsoft documentation: PerformCallBack4, the legendary function You can execute a function in the specified process in your own application, So Cool! This seems to be exactly what I need. Although online this rumor is not supported in wm5, in fact, this rumor is only a rumor!

Performance of PerformCallBack4 function:
[DllImport("coredll.dll")] public static extern uint PerformCallBack4(ref CallBackInfo CallBackInfo, IntPtr ni_pVoid1, IntPtr ni_pVoid2, IntPtr ni_pVoid3);


where the function's parameter CallBackInfo structure definition:
[StructLayout(LayoutKind.Sequential)] public struct CallBackInfo { public IntPtr hProc; //remote target process public IntPtr pfn; //pointer to the function address of the remote target process public IntPtr pvArg0; //the first parameter required by the function } //end struct


PerformCallback4's ni_pVoid1, ni_pVoid2, and ni_pVoid3 are the other three parameters that are passed to the remote target process execution function.

As for putting the code into the memory space of the target process, we can take advantage of a feature in the CE design:

1. In order to save memory usage, CE will call the dynamic link library of all programs ( DLLs are all mapped to the same memory address.

2, CE memory layout is divided into a slot0 memory location, this memory location is occupied by the process being executed, each specific time slice, only one process can occupy this memory space. When the process requires execution, the system does not directly execute the code of the memory location where the process is located, but copies the execution code of the process to the memory location of slot0 to generate a copy execution. That is to say, when the process is executed, the memory will have two identical versions of the process execution code: the process code that is executing in slot0 and the in-memory code in which the process itself is located.

Under this feature, you can get the conclusion: If process A loads Test.dll through the LoadLibrary function, and process B also loads the same Test.dll through the LoadLibrary function, all functions of this Test.dll are in process A. When executed in process B, the same address is obtained relative to the process execution code in slot0.

3, in CE, the system divides 33 slots in memory, slot0 is reserved for the process being executed, and then put all the code in a slot other than slot0 when the process starts (this In the notorious CE system, memory can only have a maximum of 32 program execution restrictions. When the process is executed, each application's memory access can only access the address in the slot0 memory space and the address of the slot memory space where the process is located. But in order for device drivers to have access to other application data they need, CE provides two functions to break this limitation. SetKmode and SetProcPermission, the SetKmode function tells the system whether the currently running process needs to be executed in kernel mode. The SetProcPermission function can accept a bit mask, each bit of code has a slot access control, and 1 represents the memory content that can access the slot. 0 means that the memory contents of the slot cannot be accessed. These two functions are helpful in msdn, see the documentation for msdn.



Copyright © Windows knowledge All Rights Reserved