首页
社区
课程
招聘
[原创]反射式DLL注入实现(ManualMap,手动解析PE并映射到目标进程再运行)
发表于: 2022-4-30 21:58 31884

[原创]反射式DLL注入实现(ManualMap,手动解析PE并映射到目标进程再运行)

2022-4-30 21:58
31884

一般而言要注入DLL到一个目标进程最简单的方法 就是先获取DLL文件路径,然后在目标进程分配内存空间将路径写入到目标进程,写入到目标进程后再调用CreateRemoteThread()/NtCreateThread()/RtlCreateUserThread()函数来运行LoadLibraryA/W函数调用自己的DLL,这种方法的缺陷也很明显那就是容易被游戏检测到,很容易被游戏拦截,比如CSGO最新版就已经有这个限制了。

想要突破CSGO的限制注入DLL进去,我们可以采用反射式注入的方法(也可以先恢复CSGOhook的api进行远程线程注入),那么什么是反射式注入呢?又有什么有点呢?
反射式dll注入与常规dll注入类似,而不同的地方在于反射式dll注入技术自己实现了一个reflective loader()函数来代替LoadLibaryA()函数去加载dll,示意图如下图所示。蓝色的线表示与用常规dll注入相同的步骤,红框中的是reflective loader()函数行为,也是下面重点描述的地方。

Reflective loader实现思路如下:

1.获得被注入进程未解析的dll的基地址。
2.获得必要的dll句柄和函数为修复导入表做准备。
3.分配一块新内存去取解析dll,并把pe头复制到新内存中和将各节复制到新内存中。
4.修复导入表和重定向表。
5.执行DllMain()函数。

核心代码如下:
ManualMapInject.h

ManualMapInject.cpp

运行效果如下:

 
 
 
 
#pragma once
#include "Injector.h"
 
using f_LoadLibraryA = HINSTANCE(WINAPI*)(const char* lpLibFilename);
using f_GetProcAddress = FARPROC(WINAPI*)(HMODULE hModule, LPCSTR lpProcName);
using f_DLL_ENTRY_POINT = BOOL(WINAPI*)(void* hDll, DWORD dwReason, void* pReserved);
 
#ifdef _WIN64
using f_RtlAddFunctionTable = BOOL(WINAPIV*)(PRUNTIME_FUNCTION FunctionTable, DWORD EntryCount, DWORD64 BaseAddress);
#endif
 
struct MANUAL_MAPPING_DATA
{
    f_LoadLibraryA pLoadLibraryA;
    f_GetProcAddress pGetProcAddress;
#ifdef _WIN64
    f_RtlAddFunctionTable pRtlAddFunctionTable;
#endif
    BYTE* pbase;
    HINSTANCE hMod;
    DWORD fdwReasonParam;
    LPVOID reservedParam;
    BOOL SEHSupport;
};
 
 
//Note: Exception support only x64 with build params /EHa or /EHc
bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader = true, bool ClearNonNeededSections = true, bool AdjustProtections = true, bool SEHExceptionSupport = true, DWORD fdwReason = DLL_PROCESS_ATTACH, LPVOID lpReserved = 0);
void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData);
 
class CManualMapInject :public CInjector
{
public:
    CManualMapInject();
    virtual ~CManualMapInject();
    virtual bool InjectorDLL(TCHAR* szPath,DWORD dwPid);
};
#pragma once
#include "Injector.h"
 
using f_LoadLibraryA = HINSTANCE(WINAPI*)(const char* lpLibFilename);
using f_GetProcAddress = FARPROC(WINAPI*)(HMODULE hModule, LPCSTR lpProcName);
using f_DLL_ENTRY_POINT = BOOL(WINAPI*)(void* hDll, DWORD dwReason, void* pReserved);
 
#ifdef _WIN64
using f_RtlAddFunctionTable = BOOL(WINAPIV*)(PRUNTIME_FUNCTION FunctionTable, DWORD EntryCount, DWORD64 BaseAddress);
#endif
 
struct MANUAL_MAPPING_DATA
{
    f_LoadLibraryA pLoadLibraryA;
    f_GetProcAddress pGetProcAddress;
#ifdef _WIN64
    f_RtlAddFunctionTable pRtlAddFunctionTable;
#endif
    BYTE* pbase;
    HINSTANCE hMod;
    DWORD fdwReasonParam;
    LPVOID reservedParam;
    BOOL SEHSupport;
};
 
 
//Note: Exception support only x64 with build params /EHa or /EHc
bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader = true, bool ClearNonNeededSections = true, bool AdjustProtections = true, bool SEHExceptionSupport = true, DWORD fdwReason = DLL_PROCESS_ATTACH, LPVOID lpReserved = 0);
void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData);
 
class CManualMapInject :public CInjector
{
public:
    CManualMapInject();
    virtual ~CManualMapInject();
    virtual bool InjectorDLL(TCHAR* szPath,DWORD dwPid);
};
#include "pch.h"
#include "ManualMapInject.h"
 
 
#ifdef _WIN64
#define CURRENT_ARCH IMAGE_FILE_MACHINE_AMD64
#else
#define CURRENT_ARCH IMAGE_FILE_MACHINE_I386
#endif
#define RELOC_FLAG32(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_HIGHLOW)
#define RELOC_FLAG64(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_DIR64)
 
#ifdef _WIN64
#define RELOC_FLAG RELOC_FLAG64
#else
#define RELOC_FLAG RELOC_FLAG32
#endif
 
 
 
CManualMapInject::CManualMapInject()
{
}
 
CManualMapInject::~CManualMapInject()
{
}
 
bool CManualMapInject::InjectorDLL(TCHAR* szPath, DWORD dwPid)
{
    HANDLE hProc = GetProcessHandle(dwPid);
    if (!hProc || !IsCorrectTargetArchitecture(hProc) || GetFileAttributes(szPath) == INVALID_FILE_ATTRIBUTES)
    {
        return false;
    }
 
//     std::ifstream File(szPath, std::ios::binary | std::ios::ate);
//
//     if (File.fail())
//     {
//         printf("Opening the file failed: %X\n", (DWORD)File.rdstate());
//         File.close();
//         CloseHandle(hProc);
//         system("PAUSE");
//         return -5;
//     }
//
//     auto FileSize = File.tellg();
//     if (FileSize < 0x1000)
//     {
//         printf("Filesize invalid.\n");
//         File.close();
//         CloseHandle(hProc);
//         system("PAUSE");
//         return -6;
//     }
//
//     BYTE* pSrcData = new BYTE[(UINT_PTR)FileSize];
//     if (!pSrcData)
//     {
//         printf("Can't allocate dll file.\n");
//         File.close();
//         CloseHandle(hProc);
//         system("PAUSE");
//         return -7;
//     }
//
//     File.seekg(0, std::ios::beg);
//     File.read((char*)(pSrcData), FileSize);
//     File.close();
    CFile file;
    file.Open(szPath, CFile::modeRead);
    ULONGLONG nFileSize = file.GetLength();
    BYTE* pSrcData = new BYTE[nFileSize];
    ZeroMemory(pSrcData,nFileSize);
    file.SeekToBegin();
    file.Read(pSrcData,nFileSize);
    file.Close();
 
    if (!ManualMapDll(hProc, pSrcData, nFileSize))
    {
        delete[] pSrcData;
        CloseHandle(hProc);
        return false;
    }
    delete[] pSrcData;
 
    CloseHandle(hProc);
    return false;
}
 
bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader,
    bool ClearNonNeededSections, bool AdjustProtections,
    bool SEHExceptionSupport, DWORD fdwReason, LPVOID lpReserved)
{
    IMAGE_NT_HEADERS* pOldNtHeader = nullptr;
    IMAGE_OPTIONAL_HEADER* pOldOptHeader = nullptr;
    IMAGE_FILE_HEADER* pOldFileHeader = nullptr;
    BYTE* pTargetBase = nullptr;
 
    if (reinterpret_cast<IMAGE_DOS_HEADER*>(pSrcData)->e_magic != 0x5A4D)//"MZ"
    {
        return false;
    }
 
    pOldNtHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(pSrcData + reinterpret_cast<IMAGE_DOS_HEADER*>(pSrcData)->e_lfanew);
    pOldOptHeader = &pOldNtHeader->OptionalHeader;
    pOldFileHeader = &pOldNtHeader->FileHeader;
 
    if (pOldFileHeader->Machine != CURRENT_ARCH)
    {
        return false;
    }
 
    pTargetBase = reinterpret_cast<BYTE*>(VirtualAllocEx(hProc, nullptr, pOldOptHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
    if (!pTargetBase)
    {
        return false;
    }
 
    DWORD oldp = 0;
    VirtualProtectEx(hProc, pTargetBase, pOldOptHeader->SizeOfImage, PAGE_EXECUTE_READWRITE, &oldp);
 
    MANUAL_MAPPING_DATA data{ 0 };
    data.pLoadLibraryA = LoadLibraryA;
    data.pGetProcAddress = GetProcAddress;
#ifdef _WIN64
    data.pRtlAddFunctionTable = (f_RtlAddFunctionTable)RtlAddFunctionTable;
#else
    SEHExceptionSupport = false;
#endif
    data.pbase = pTargetBase;
    data.fdwReasonParam = fdwReason;
    data.reservedParam = lpReserved;
    data.SEHSupport = SEHExceptionSupport;
 
 
    //PE header
    if (!WriteProcessMemory(hProc, pTargetBase, pSrcData, 0x1000, nullptr)) //only first 0x1000 bytes for the header
    {
        VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
        return false;
    }
 
    IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader);
    for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader)
    {
        if (pSectionHeader->SizeOfRawData)
        {
            if (!WriteProcessMemory(hProc, pTargetBase + pSectionHeader->VirtualAddress, pSrcData + pSectionHeader->PointerToRawData, pSectionHeader->SizeOfRawData, nullptr))
            {
                VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
                return false;
            }
        }
    }
 
    //Mapping params
    BYTE* MappingDataAlloc = reinterpret_cast<BYTE*>(VirtualAllocEx(hProc, nullptr, sizeof(MANUAL_MAPPING_DATA), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
    if (!MappingDataAlloc)
    {
        VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
        return false;
    }
 
    if (!WriteProcessMemory(hProc, MappingDataAlloc, &data, sizeof(MANUAL_MAPPING_DATA), nullptr))
    {
        VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
        VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
        return false;
    }
 
    //Shell code
    void* pShellcode = VirtualAllocEx(hProc, nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!pShellcode)
    {
        VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
        VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
        return false;
    }
 
    if (!WriteProcessMemory(hProc, pShellcode, Shellcode, 0x1000, nullptr))
    {
        VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
        VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
        VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE);
        return false;
    }
 
 
    HANDLE hThread = CreateRemoteThread(hProc, nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(pShellcode), MappingDataAlloc, 0, nullptr);
    if (!hThread)
    {
        VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
        VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
        VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE);
        return false;
    }
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
 
 
    HINSTANCE hCheck = NULL;
    while (!hCheck)
    {
        DWORD exitcode = 0;
        GetExitCodeProcess(hProc, &exitcode);
        if (exitcode != STILL_ACTIVE)
        {
            return false;
        }
 
        MANUAL_MAPPING_DATA data_checked{ 0 };
        ReadProcessMemory(hProc, MappingDataAlloc, &data_checked, sizeof(data_checked), nullptr);
        hCheck = data_checked.hMod;
 
        if (hCheck == (HINSTANCE)0x404040)
        {
            VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
            VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
            VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE);
            return false;
        }
        else if (hCheck == (HINSTANCE)0x505050)
        {
            //Exception support failed!
        }
 
        Sleep(10);
    }
 
    BYTE* emptyBuffer = (BYTE*)malloc(1024 * 1024 * 20);
    if (emptyBuffer == nullptr)
    {
        return false;
    }
    memset(emptyBuffer, 0, 1024 * 1024 * 20);
 
    //CLEAR PE HEAD
    if (ClearHeader)
    {
        WriteProcessMemory(hProc, pTargetBase, emptyBuffer, 0x1000, nullptr);
    }
    //END CLEAR PE HEAD
 
 
    if (ClearNonNeededSections)
    {
        pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader);
        for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader)
        {
            if (pSectionHeader->Misc.VirtualSize)
            {
                if ((SEHExceptionSupport ? 0 : strcmp((char*)pSectionHeader->Name, ".pdata") == 0) ||
                    strcmp((char*)pSectionHeader->Name, ".rsrc") == 0 ||
                    strcmp((char*)pSectionHeader->Name, ".reloc") == 0)
                {
                    WriteProcessMemory(hProc, pTargetBase + pSectionHeader->VirtualAddress, emptyBuffer, pSectionHeader->Misc.VirtualSize, nullptr);
                }
            }
        }
    }
 
    if (AdjustProtections)
    {
        pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader);
        for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader)
        {
            if (pSectionHeader->Misc.VirtualSize)
            {
                DWORD old = 0;
                DWORD newP = PAGE_READONLY;
 
                if ((pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE) > 0)
                {
                    newP = PAGE_READWRITE;
                }
                else if ((pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) > 0)
                {
                    newP = PAGE_EXECUTE_READ;
                }
                VirtualProtectEx(hProc, pTargetBase + pSectionHeader->VirtualAddress, pSectionHeader->Misc.VirtualSize, newP, &old);
            }
        }
        DWORD old = 0;
        VirtualProtectEx(hProc, pTargetBase, IMAGE_FIRST_SECTION(pOldNtHeader)->VirtualAddress, PAGE_READONLY, &old);
    }
 
    WriteProcessMemory(hProc, pShellcode, emptyBuffer, 0x1000, nullptr);
    VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE);
    VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
 
    return true;
}
 
 
 
//#pragma runtime_checks( "", off )
//#pragma optimize( "", off )
void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData)
{
    if (!pData)
    {
        pData->hMod = (HINSTANCE)0x404040;
        return;
    }
 
    BYTE* pBase = pData->pbase;
    auto* pOpt = &reinterpret_cast<IMAGE_NT_HEADERS*>(pBase + reinterpret_cast<IMAGE_DOS_HEADER*>((uintptr_t)pBase)->e_lfanew)->OptionalHeader;
 
    auto _LoadLibraryA = pData->pLoadLibraryA;
    auto _GetProcAddress = pData->pGetProcAddress;
#ifdef _WIN64
    auto _RtlAddFunctionTable = pData->pRtlAddFunctionTable;
#endif
    auto _DllMain = reinterpret_cast<f_DLL_ENTRY_POINT>(pBase + pOpt->AddressOfEntryPoint);
 
    BYTE* LocationDelta = pBase - pOpt->ImageBase;
    if (LocationDelta) {
        if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
        {
            auto* pRelocData = reinterpret_cast<IMAGE_BASE_RELOCATION*>(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
            const auto* pRelocEnd = reinterpret_cast<IMAGE_BASE_RELOCATION*>(reinterpret_cast<uintptr_t>(pRelocData) + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
            while (pRelocData < pRelocEnd && pRelocData->SizeOfBlock)
            {
                UINT AmountOfEntries = (pRelocData->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
                WORD* pRelativeInfo = reinterpret_cast<WORD*>(pRelocData + 1);
 
                for (UINT i = 0; i != AmountOfEntries; ++i, ++pRelativeInfo)
                {
                    if (RELOC_FLAG(*pRelativeInfo))
                    {
                        UINT_PTR* pPatch = reinterpret_cast<UINT_PTR*>(pBase + pRelocData->VirtualAddress + ((*pRelativeInfo) & 0xFFF));
                        *pPatch += reinterpret_cast<UINT_PTR>(LocationDelta);
                    }
                }
                pRelocData = reinterpret_cast<IMAGE_BASE_RELOCATION*>(reinterpret_cast<BYTE*>(pRelocData) + pRelocData->SizeOfBlock);
            }
        }
    }
 
    if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
    {
        auto* pImportDescr = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*>(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
        while (pImportDescr->Name)
        {
            char* szMod = reinterpret_cast<char*>(pBase + pImportDescr->Name);
            HINSTANCE hDll = _LoadLibraryA(szMod);
 
            ULONG_PTR* pThunkRef = reinterpret_cast<ULONG_PTR*>(pBase + pImportDescr->OriginalFirstThunk);
            ULONG_PTR* pFuncRef = reinterpret_cast<ULONG_PTR*>(pBase + pImportDescr->FirstThunk);
 
            if (!pThunkRef)
                pThunkRef = pFuncRef;
 
            for (; *pThunkRef; ++pThunkRef, ++pFuncRef)
            {
                if (IMAGE_SNAP_BY_ORDINAL(*pThunkRef))
                {
                    *pFuncRef = (ULONG_PTR)_GetProcAddress(hDll, reinterpret_cast<char*>(*pThunkRef & 0xFFFF));
                }
                else
                {
                    auto* pImport = reinterpret_cast<IMAGE_IMPORT_BY_NAME*>(pBase + (*pThunkRef));
                    *pFuncRef = (ULONG_PTR)_GetProcAddress(hDll, pImport->Name);
                }
            }
            ++pImportDescr;
        }
    }
 
    if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
    {
        auto* pTLS = reinterpret_cast<IMAGE_TLS_DIRECTORY*>(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
        auto* pCallback = reinterpret_cast<PIMAGE_TLS_CALLBACK*>(pTLS->AddressOfCallBacks);
        for (; pCallback && *pCallback; ++pCallback)
            (*pCallback)(pBase, DLL_PROCESS_ATTACH, nullptr);
    }
 
    bool ExceptionSupportFailed = false;
 
#ifdef _WIN64
 
    if (pData->SEHSupport)
    {
        auto excep = pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
        if (excep.Size) {
            if (!_RtlAddFunctionTable(
                reinterpret_cast<IMAGE_RUNTIME_FUNCTION_ENTRY*>(pBase + excep.VirtualAddress),
                excep.Size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY), (DWORD64)pBase))
            {
                ExceptionSupportFailed = true;
            }
        }
    }
 
#endif
 
    _DllMain(pBase, pData->fdwReasonParam, pData->reservedParam);
 
    if (ExceptionSupportFailed)
        pData->hMod = reinterpret_cast<HINSTANCE>(0x505050);
    else
        pData->hMod = reinterpret_cast<HINSTANCE>(pBase);
}
#include "pch.h"
#include "ManualMapInject.h"
 
 
#ifdef _WIN64
#define CURRENT_ARCH IMAGE_FILE_MACHINE_AMD64
#else
#define CURRENT_ARCH IMAGE_FILE_MACHINE_I386
#endif
#define RELOC_FLAG32(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_HIGHLOW)
#define RELOC_FLAG64(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_DIR64)
 
#ifdef _WIN64
#define RELOC_FLAG RELOC_FLAG64
#else
#define RELOC_FLAG RELOC_FLAG32
#endif
 
 
 
CManualMapInject::CManualMapInject()
{
}
 
CManualMapInject::~CManualMapInject()
{
}
 
bool CManualMapInject::InjectorDLL(TCHAR* szPath, DWORD dwPid)
{
    HANDLE hProc = GetProcessHandle(dwPid);
    if (!hProc || !IsCorrectTargetArchitecture(hProc) || GetFileAttributes(szPath) == INVALID_FILE_ATTRIBUTES)
    {
        return false;
    }
 
//     std::ifstream File(szPath, std::ios::binary | std::ios::ate);
//
//     if (File.fail())
//     {
//         printf("Opening the file failed: %X\n", (DWORD)File.rdstate());
//         File.close();
//         CloseHandle(hProc);
//         system("PAUSE");
//         return -5;
//     }
//
//     auto FileSize = File.tellg();
//     if (FileSize < 0x1000)
//     {
//         printf("Filesize invalid.\n");
//         File.close();
//         CloseHandle(hProc);
//         system("PAUSE");
//         return -6;
//     }
//
//     BYTE* pSrcData = new BYTE[(UINT_PTR)FileSize];
//     if (!pSrcData)
//     {
//         printf("Can't allocate dll file.\n");
//         File.close();
//         CloseHandle(hProc);
//         system("PAUSE");
//         return -7;
//     }
//
//     File.seekg(0, std::ios::beg);
//     File.read((char*)(pSrcData), FileSize);
//     File.close();
    CFile file;
    file.Open(szPath, CFile::modeRead);
    ULONGLONG nFileSize = file.GetLength();
    BYTE* pSrcData = new BYTE[nFileSize];
    ZeroMemory(pSrcData,nFileSize);
    file.SeekToBegin();
    file.Read(pSrcData,nFileSize);
    file.Close();
 
    if (!ManualMapDll(hProc, pSrcData, nFileSize))
    {
        delete[] pSrcData;
        CloseHandle(hProc);
        return false;
    }
    delete[] pSrcData;
 
    CloseHandle(hProc);
    return false;
}
 
bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader,
    bool ClearNonNeededSections, bool AdjustProtections,
    bool SEHExceptionSupport, DWORD fdwReason, LPVOID lpReserved)
{
    IMAGE_NT_HEADERS* pOldNtHeader = nullptr;
    IMAGE_OPTIONAL_HEADER* pOldOptHeader = nullptr;
    IMAGE_FILE_HEADER* pOldFileHeader = nullptr;
    BYTE* pTargetBase = nullptr;
 
    if (reinterpret_cast<IMAGE_DOS_HEADER*>(pSrcData)->e_magic != 0x5A4D)//"MZ"
    {
        return false;
    }
 
    pOldNtHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(pSrcData + reinterpret_cast<IMAGE_DOS_HEADER*>(pSrcData)->e_lfanew);
    pOldOptHeader = &pOldNtHeader->OptionalHeader;
    pOldFileHeader = &pOldNtHeader->FileHeader;
 
    if (pOldFileHeader->Machine != CURRENT_ARCH)
    {
        return false;
    }
 
    pTargetBase = reinterpret_cast<BYTE*>(VirtualAllocEx(hProc, nullptr, pOldOptHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
    if (!pTargetBase)
    {
        return false;
    }
 
    DWORD oldp = 0;
    VirtualProtectEx(hProc, pTargetBase, pOldOptHeader->SizeOfImage, PAGE_EXECUTE_READWRITE, &oldp);
 
    MANUAL_MAPPING_DATA data{ 0 };
    data.pLoadLibraryA = LoadLibraryA;
    data.pGetProcAddress = GetProcAddress;
#ifdef _WIN64
    data.pRtlAddFunctionTable = (f_RtlAddFunctionTable)RtlAddFunctionTable;
#else
    SEHExceptionSupport = false;
#endif
    data.pbase = pTargetBase;
    data.fdwReasonParam = fdwReason;
    data.reservedParam = lpReserved;
    data.SEHSupport = SEHExceptionSupport;
 
 
    //PE header
    if (!WriteProcessMemory(hProc, pTargetBase, pSrcData, 0x1000, nullptr)) //only first 0x1000 bytes for the header
    {
        VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
        return false;
    }
 
    IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader);
    for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader)
    {
        if (pSectionHeader->SizeOfRawData)
        {
            if (!WriteProcessMemory(hProc, pTargetBase + pSectionHeader->VirtualAddress, pSrcData + pSectionHeader->PointerToRawData, pSectionHeader->SizeOfRawData, nullptr))
            {
                VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
                return false;
            }
        }
    }
 
    //Mapping params
    BYTE* MappingDataAlloc = reinterpret_cast<BYTE*>(VirtualAllocEx(hProc, nullptr, sizeof(MANUAL_MAPPING_DATA), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
    if (!MappingDataAlloc)
    {
        VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
        return false;
    }
 
    if (!WriteProcessMemory(hProc, MappingDataAlloc, &data, sizeof(MANUAL_MAPPING_DATA), nullptr))
    {
        VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
        VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
        return false;
    }
 
    //Shell code
    void* pShellcode = VirtualAllocEx(hProc, nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!pShellcode)
    {
        VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
        VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
        return false;

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2022-5-6 22:05 被_DriverEntry编辑 ,原因: 之前图片没显示出来
收藏
免费 15
支持
分享
打赏 + 50.00雪花
打赏次数 1 雪花 + 50.00
 
赞赏  Editor   +50.00 2022/05/13 恭喜您获得“雪花”奖励,安全圈有你而精彩!
最新回复 (21)
雪    币: 6357
活跃值: (3887)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
DLL要做处理吗?我记得好像反射注入的DLL内部也要做处理的……
2022-5-1 09:51
0
雪    币: 2737
活跃值: (5044)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
大鲤鱼 DLL要做处理吗?我记得好像反射注入的DLL内部也要做处理的……
这个不用
2022-5-7 15:22
0
雪    币: 1440
活跃值: (1401)
能力值: ( LV3,RANK:23 )
在线值:
发帖
回帖
粉丝
4

1

最后于 2022-5-7 17:33 被Black貓①呺编辑 ,原因:
2022-5-7 17:31
0
雪    币: 1440
活跃值: (1401)
能力值: ( LV3,RANK:23 )
在线值:
发帖
回帖
粉丝
5
大鲤鱼 DLL要做处理吗?我记得好像反射注入的DLL内部也要做处理的……
DLL可以做处理,可以不做处理。不做处理就是需要先注入一段shellcode或者一个特殊的dll,调用那注入的代码进行加载DLL。
如果不做进程内加载dll工作,调用的第三方dll就有限制,只能利用已加载,其他就需要自己load(也就是改需要注入dll的代码了)
2022-5-7 17:33
0
雪    币: 1440
活跃值: (1401)
能力值: ( LV3,RANK:23 )
在线值:
发帖
回帖
粉丝
6
我不怎么喜欢用shellcode,调试不方便,直接搞个特殊dll进去搞事情: https://github.com/Kerrbty/RemoteLoadDll 
2022-5-7 17:39
0
雪    币: 6221
活跃值: (5660)
能力值: ( LV5,RANK:65 )
在线值:
发帖
回帖
粉丝
7
感谢分享,收藏了!
2022-5-7 17:56
0
雪    币: 2737
活跃值: (5044)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
Black貓①呺 我不怎么喜欢用shellcode,调试不方便,直接搞个特殊dll进去搞事情: https://github.com/Kerrbty/RemoteLoadDll
感谢分享
2022-5-7 18:12
0
雪    币: 1935
活跃值: (4180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
mark
2022-5-9 11:53
0
雪    币: 865
活跃值: (1613)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
10
mark
2022-5-15 15:27
0
雪    币: 99
活跃值: (398)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11


最后于 2023-8-1 16:26 被Uioa编辑 ,原因:
2022-5-18 18:15
0
雪    币: 865
活跃值: (1613)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
Uioa 楼主,站在游戏安全的角度,如何检测这种注入方式?
关键函数喽,CreateRemoteThread这种的
2022-5-18 18:52
0
雪    币: 99
活跃值: (398)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
凌哥 关键函数喽,CreateRemoteThread这种的
最后于 2023-8-1 16:24 被Uioa编辑 ,原因:
2022-5-19 09:57
0
雪    币: 99
活跃值: (398)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14

mark

最后于 2023-8-1 16:26 被Uioa编辑 ,原因:
2022-5-19 09:57
0
雪    币: 865
活跃值: (1613)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
15
大佬,看你的贴子 学到了一个shellcode的编写方式,但是仅限于Release模式,有没有办法让Debug模式下可以使用呢,因为有需求调试别的内容。而此时的函数已经有了 调试信息了,会导致shellcode 在目标进程中崩溃。目前我的解决办法是设置项目属性,但是我更想利用宏来完成
2022-7-12 15:25
0
雪    币: 14
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
感谢大佬分享!
2022-7-12 17:05
0
雪    币: 1025
活跃值: (633)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
详细代码参见 https://github.com/TheCruZ/Simple-Manual-Map-Injector
2022-8-23 16:27
0
雪    币: 127
活跃值: (2868)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
       if (!pData) {
               pData->hMod = (HINSTANCE)0x404040;
               return;
       }
这代码是认真的么
2022-8-24 20:19
0
雪    币: 144
活跃值: (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
data.pLoadLibraryA = LoadLibraryA;
data.pGetProcAddress = GetProcAddress;
data.pRtlAddFunctionTable = (f_RtlAddFunctionTable)RtlAddFunctionTable;

这三行不严谨,应该通过GetProcAddress获取地址,否则注入程序通过IAT进行跳转,和目标地址不一定一样。
2022-8-28 01:49
0
雪    币: 1440
活跃值: (1401)
能力值: ( LV3,RANK:23 )
在线值:
发帖
回帖
粉丝
20
Uioa 驱动创建远程线程估计也就走个形式
攻防这事没有尽头的,线程方式可以使用 DLL_THREAD_ATTACH 互调处理,但是你也可以不开辟线程,使用已有的线程 SetThreadContext 设置Eip指向shellcode(但shellcode要做好返回原地址执行的操作),也可以 用这种方法先用 DisableThreadLibraryCalls 废掉线程回调。检测内存遍历,对应就是抹掉PE头。检测所有线程运行地址是否在自己模块或者系统模块内,使用栈回溯看是否被其他非法模块调用,,,,,《游戏外挂攻防艺术》里面总结比较好了
2022-9-9 17:10
0
雪    币: 3573
活跃值: (31026)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
感谢分享
2023-11-24 10:06
1
雪    币: 20
活跃值: (77)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
感谢分享。。。
2023-12-7 19:50
0
游客
登录 | 注册 方可回帖
返回
//