Reserves or commits a region of memory within the virtual address space of a specified process. The function initializes the memory it allocates to zero, unless MEM_RESET is used.
[in] The pointer that specifies a desired starting address for the region of pages that you want to allocate.
If you are reserving memory, the function rounds this address down to the nearest multiple of the allocation granularity.
If you are committing memory that is already reserved, the function rounds this address down to the nearest page boundary. To determine the size of a page and the allocation granularity on the host computer, use the GetSystemInfo function.
If lpAddress is NULL, the function determines where to allocate the region.
dwSize
[in] The size of the region of memory to allocate, in bytes.
If lpAddress is NULL, the function rounds dwSize up to the next page boundary.
If lpAddress is not NULL, the function allocates all pages that contain one or more bytes in the range from lpAddress to lpAddress+dwSize. This means, for example, that a 2-byte range that straddles a page boundary causes the function to allocate both pages.
flAllocationType
[in] The type of memory allocation. This parameter must contain one of the following values.
Value
Meaning
MEM_COMMIT 0x1000
Allocates physical storage in memory or in the paging file on disk for the specified reserved memory pages. The function initializes the memory to zero.
To reserve and commit pages in one step, call VirtualAllocEx with MEM_COMMIT | MEM_RESERVE.
The function fails if you attempt to commit a page that has not been reserved. The resulting error code is ERROR_INVALID_ADDRESS.
An attempt to commit a page that is already committed does not cause the function to fail. This means that you can commit pages without first determining the current commitment state of each page.
MEM_RESERVE 0x2000
Reserves a range of the process's virtual address space without allocating any actual physical storage in memory or in the paging file on disk.
You commit reserved pages by calling VirtualAllocEx again with MEM_COMMIT. To reserve and commit pages in one step, call VirtualAllocEx with MEM_COMMIT |MEM_RESERVE.
Other memory allocation functions, such as malloc and LocalAlloc, cannot use reserved memory until it has been released.
MEM_RESET 0x80000
Indicates that data in the memory range specified by lpAddress and dwSize is no longer of interest. The pages should not be read from or written to the paging file. However, the memory block will be used again later, so it should not be decommitted. This value cannot be used with any other value.
Using this value does not guarantee that the range operated on with MEM_RESET will contain zeroes. If you want the range to contain zeroes, decommit the memory and then recommit it.
When you use MEM_RESET, the VirtualAllocEx function ignores the value of fProtect. However, you must still set fProtect to a valid protection value, such as PAGE_NOACCESS.
VirtualAllocEx returns an error if you use MEM_RESET and the range of memory is mapped to a file. A shared view is only acceptable if it is mapped to a paging file.
This parameter can also specify the following values as indicated.
The size and alignment must be a multiple of the large-page minimum. To obtain this value, use the GetLargePageMinimum function.
Windows XP/2000/NT: This flag is not supported.
MEM_PHYSICAL 0x400000
Allocates physical memory with read-write access. This value is solely for use with Address Windowing Extensions (AWE) memory.
This value must be used with MEM_RESERVE and no other values.
MEM_TOP_DOWN 0x100000
Allocates memory at the highest possible address.
flProtect
[in] The memory protection for the region of pages to be allocated. If the pages are being committed, you can specify any one of the memory protection constants.
Protection attributes specified when protecting a page cannot conflict with those specified when allocating a page.
Return Value
If the function succeeds, the return value is the base address of the allocated region of pages.
If the function fails, the return value is NULL. To get extended error information, call GetLastError.
WriteProcessMemory
Writes data to an area of memory in a specified process. The entire area to be written to must be accessible or the operation fails.
[in] A handle to the process memory to be modified. The handle must have PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process.
lpBaseAddress
[in] A pointer to the base address in the specified process to which data is written. Before data transfer occurs, the system verifies that all data in the base address and memory of the specified size is accessible for write access, and if it is not accessible, the function fails.
lpBuffer
[in] A pointer to the buffer that contains data to be written in the address space of the specified process.
nSize
[in] The number of bytes to be written to the specified process.
lpNumberOfBytesWritten
[out] A pointer to a variable that receives the number of bytes transferred into the specified process. This parameter is optional. If lpNumberOfBytesWritten is NULL, the parameter is ignored.
Return Value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is 0 (zero). To get extended error information, call GetLastError. The function fails if the requested write operation crosses into an area of the process that is inaccessible.
Remarks
WriteProcessMemory copies the data from the specified buffer in the current process to the address range of the specified process. Any process that has a handle with PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process to be written to can call the function. Typically but not always, the process with address space that is being written to is being debugged.
The entire area to be written to must be accessible, and if it is not accessible, the function fails.
There are two ways to 'Inject' a series of bytes into an already running process. VirtualAllocEx() - which isn't supported in Win9x/ME - will allow a process to reserve or commit a region of memory within the virtual address space of a separate specified process. Use WriteProcessMemory() to write the data in the reserved/committed area of the target process' memory.
The other way is to directly use ReadProcessMemory()and WriteProcessMemory() - which is supported in all versions of Windows - to search for some accessible area of the target process' memory and replace the bytes within the area size equal to the size of the code. Of course, you will be saving a backup of the replaced bytes in order to put them all back later on.
(Of course, you can use CreateRemoteThread() instead of all this, but it's not supported in all versions of Windows.)
One good yet slow method of injecting the code is using Windows' debugging functions. Suspend the threads of the running process (using the debugging functions) and use GetThreadContext() and SetThreadContext() to save a backup of all the registers and then modify the EIP register, which is the register that contains the offset of the current to-be-executed code, to point it to the 'Injected' code. The injected code block will have a breakpoint set at the end of it (Interrupt 3h -int 3h-). Again, use the debugging functions to resume the threads, which will then continue executing till the first breakpoint is reached. Once your application receives the notification, all you have to do is restore the modified bytes and/or un-allocate any allocated space in memory, and finally restore the registers (SetThreadContext()). That's all there is to it. The application has no idea of what has happened! The code was executed, and probably loaded a DLL. As you know, loaded DLLs are in an application's address space, therefore, the DLLs can access all memory and control the whole application. Very interesting.
----
DLL을 다른 프로세스에 주입한다는 것은 다른 프로세스의 메모리 공간에 내가 만든 DLL을 매핑한다는 뜻이다. 하지만 단순이 메모리에 DLL을 매핑하는 것이 다는 아니다. DLL이 로드될 때 자동으로 실행되는 DllMain 에서 내가 원하는 코드를 '다른 프로세스 내에서' 실행시킬 수도 있다.