in src/creatwth.cpp [1022:1126]
PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess,
_In_ REFGUID rguid,
_In_reads_bytes_(cbData) LPCVOID pvData,
_In_ DWORD cbData)
{
if (hProcess == NULL) {
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
DWORD cbTotal = (sizeof(IMAGE_DOS_HEADER) +
sizeof(IMAGE_NT_HEADERS) +
sizeof(IMAGE_SECTION_HEADER) +
sizeof(DETOUR_SECTION_HEADER) +
sizeof(DETOUR_SECTION_RECORD) +
cbData);
PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal,
MEM_COMMIT, PAGE_READWRITE);
if (pbBase == NULL) {
DETOUR_TRACE(("VirtualAllocEx(%lu) failed: %lu\n", cbTotal, GetLastError()));
return NULL;
}
// As you can see in the following code,
// the memory layout of the payload range "[pbBase, pbBase+cbTotal]" is a PE executable file,
// so DetourFreePayload can use "DetourGetContainingModule(Payload pointer)" to get the above "pbBase" pointer,
// pbBase: the memory block allocated by VirtualAllocEx will be released in DetourFreePayload by VirtualFree.
PBYTE pbTarget = pbBase;
IMAGE_DOS_HEADER idh;
IMAGE_NT_HEADERS inh;
IMAGE_SECTION_HEADER ish;
DETOUR_SECTION_HEADER dsh;
DETOUR_SECTION_RECORD dsr;
SIZE_T cbWrote = 0;
ZeroMemory(&idh, sizeof(idh));
idh.e_magic = IMAGE_DOS_SIGNATURE;
idh.e_lfanew = sizeof(idh);
if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) ||
cbWrote != sizeof(idh)) {
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError()));
return NULL;
}
pbTarget += sizeof(idh);
ZeroMemory(&inh, sizeof(inh));
inh.Signature = IMAGE_NT_SIGNATURE;
inh.FileHeader.SizeOfOptionalHeader = sizeof(inh.OptionalHeader);
inh.FileHeader.Characteristics = IMAGE_FILE_DLL;
inh.FileHeader.NumberOfSections = 1;
inh.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) ||
cbWrote != sizeof(inh)) {
return NULL;
}
pbTarget += sizeof(inh);
ZeroMemory(&ish, sizeof(ish));
memcpy(ish.Name, ".detour", sizeof(ish.Name));
ish.VirtualAddress = (DWORD)((pbTarget + sizeof(ish)) - pbBase);
ish.SizeOfRawData = (sizeof(DETOUR_SECTION_HEADER) +
sizeof(DETOUR_SECTION_RECORD) +
cbData);
if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) ||
cbWrote != sizeof(ish)) {
return NULL;
}
pbTarget += sizeof(ish);
ZeroMemory(&dsh, sizeof(dsh));
dsh.cbHeaderSize = sizeof(dsh);
dsh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE;
dsh.nDataOffset = sizeof(DETOUR_SECTION_HEADER);
dsh.cbDataSize = (sizeof(DETOUR_SECTION_HEADER) +
sizeof(DETOUR_SECTION_RECORD) +
cbData);
if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) ||
cbWrote != sizeof(dsh)) {
return NULL;
}
pbTarget += sizeof(dsh);
ZeroMemory(&dsr, sizeof(dsr));
dsr.cbBytes = cbData + sizeof(DETOUR_SECTION_RECORD);
dsr.nReserved = 0;
dsr.guid = rguid;
if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) ||
cbWrote != sizeof(dsr)) {
return NULL;
}
pbTarget += sizeof(dsr);
if (!WriteProcessMemory(hProcess, pbTarget, pvData, cbData, &cbWrote) ||
cbWrote != cbData) {
return NULL;
}
DETOUR_TRACE(("Copied %lu byte payload into target process at %p\n",
cbData, pbTarget));
SetLastError(NO_ERROR);
return pbTarget;
}