反射式DLL注入实现
2022-5-13 17:59:0 Author: mp.weixin.qq.com(查看原文) 阅读量:15 收藏


本文为看雪论坛优秀文章
看雪论坛作者ID:_DriverEntry

一般而言要注入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
#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 _WIN64using 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 /EHcbool 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);};
ManualMapInject.cpp
#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);}
运行效果如下:

看雪ID:_DriverEntry

https://bbs.pediy.com/user-home-944747.htm

*本文由看雪论坛 _DriverEntry 原创,转载请注明来自看雪社区

# 往期推荐

1.angr符号变量转LLVM IR

2.记录一次对某CMS漏洞挖掘

3.Android APP漏洞之战—验证码漏洞挖掘详解

4.CTF 中 glibc堆利用及 IO_FILE 总结

5.记一次新型变种QakBot木马分析

6.[VNCTF2022]gocalc0复现

球分享

球点赞

球在看

点击“阅读原文”,了解更多!


文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458444006&idx=1&sn=f18d9a9dd09f0b5f89314ce4ccfe465f&chksm=b18fd06c86f8597a7cfe4917df1f2979148a24ffc1284fa9c52fb690b0457b3175e1ecd9eaea#rd
如有侵权请联系:admin#unsafe.sh