QQ登录

只需要一步,快速开始

APP扫码登录

只需要一步,快速开始

手机号码,快捷登录

手机号码,快捷登录

查看: 2577|回复: 0

[C/C++/Qt] 反射式DLL注入实现

[复制链接]

等级头衔

积分成就    金币 : 2841
   泡泡 : 1516
   精华 : 6
   在线时间 : 1295 小时
   最后登录 : 2024-11-23

丰功伟绩

优秀达人突出贡献荣誉管理论坛元老

联系方式
发表于 2022-5-15 22:24:21 | 显示全部楼层 |阅读模式
       一般而言要注入DLL到一个目标进程最简单的方法 就是先获取DLL文件路径,然后在目标进程分配内存空间将路径写入到目标进程,写入到目标进程后再调用CreateRemoteThread()/NtCreateThread()/RtlCreateUserThread()函数来运行LoadLibraryA/W函数调用自己的DLL,这种方法的缺陷也很明显那就是容易被游戏检测到,很容易被游戏拦截,比如CSGO最新版就已经有这个限制了。
( l3 D/ z, N2 J" _; d' W        想要突破CSGO的限制注入DLL进去,我们可以采用反射式注入的方法(也可以先恢复CSGOhook的api进行远程线程注入),那么什么是反射式注入呢?又有什么有点呢?8 J; k5 c& @3 z4 O
       反射式dll注入与常规dll注入类似,而不同的地方在于反射式dll注入技术自己实现了一个reflective loader()函数来代替LoadLibaryA()函数去加载dll,示意图如下图所示。蓝色的线表示与用常规dll注入相同的步骤,红框中的是reflective loader()函数行为,也是下面重点描述的地方。4 H$ d8 h7 _3 z% j; G& m. S
Reflective loader实现思路如下:
3 S9 P, r. C# \  m. l
  • 获得被注入进程未解析的dll的基地址。
  • 获得必要的dll句柄和函数为修复导入表做准备。
  • 分配一块新内存去取解析dll,并把pe头复制到新内存中和将各节复制到新内存中。
  • 修复导入表和重定向表。
  • 执行DllMain()函数。: H6 j/ F. Y& c' A9 j
1.jpg
2 n" P& y' _6 W, N. _# w8 r
8 R! e4 `( y. l; w- O& ~7 F; _3 m2 p. r8 ?6 C
核心代码如下:
/ o+ R1 K- J( f: yManualMapInject.h" h0 ?9 d% U4 P' r& z+ a
  1. #pragma once
  2. #include "Injector.h"
  3. using f_LoadLibraryA = HINSTANCE(WINAPI*)(const char* lpLibFilename);
  4. using f_GetProcAddress = FARPROC(WINAPI*)(HMODULE hModule, LPCSTR lpProcName);
  5. using f_DLL_ENTRY_POINT = BOOL(WINAPI*)(void* hDll, DWORD dwReason, void* pReserved);
  6. #ifdef _WIN64
  7. using f_RtlAddFunctionTable = BOOL(WINAPIV*)(PRUNTIME_FUNCTION FunctionTable, DWORD EntryCount, DWORD64 BaseAddress);
  8. #endif
  9. struct MANUAL_MAPPING_DATA
  10. {
  11.     f_LoadLibraryA pLoadLibraryA;
  12.     f_GetProcAddress pGetProcAddress;
  13. #ifdef _WIN64
  14.     f_RtlAddFunctionTable pRtlAddFunctionTable;
  15. #endif
  16.     BYTE* pbase;
  17.     HINSTANCE hMod;
  18.     DWORD fdwReasonParam;
  19.     LPVOID reservedParam;
  20.     BOOL SEHSupport;
  21. };
  22. //Note: Exception support only x64 with build params /EHa or /EHc
  23. 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);
  24. void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData);
  25. class CManualMapInject :public CInjector
  26. {
  27. public:
  28.     CManualMapInject();
  29.     virtual ~CManualMapInject();
  30.     virtual bool InjectorDLL(TCHAR* szPath,DWORD dwPid);
  31. };
ManualMapInject.cpp
! x+ ^; F, T0 A2 Q/ T
  1. #include "pch.h"
  2. #include "ManualMapInject.h"
  3. #ifdef _WIN64
  4. #define CURRENT_ARCH IMAGE_FILE_MACHINE_AMD64
  5. #else
  6. #define CURRENT_ARCH IMAGE_FILE_MACHINE_I386
  7. #endif
  8. #define RELOC_FLAG32(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_HIGHLOW)
  9. #define RELOC_FLAG64(RelInfo) ((RelInfo >> 0x0C) == IMAGE_REL_BASED_DIR64)
  10. #ifdef _WIN64
  11. #define RELOC_FLAG RELOC_FLAG64
  12. #else
  13. #define RELOC_FLAG RELOC_FLAG32
  14. #endif
  15. CManualMapInject::CManualMapInject()
  16. {
  17. }
  18. CManualMapInject::~CManualMapInject()
  19. {
  20. }
  21. bool CManualMapInject::InjectorDLL(TCHAR* szPath, DWORD dwPid)
  22. {
  23.     HANDLE hProc = GetProcessHandle(dwPid);
  24.     if (!hProc || !IsCorrectTargetArchitecture(hProc) || GetFileAttributes(szPath) == INVALID_FILE_ATTRIBUTES)
  25.     {
  26.         return false;
  27.     }
  28. //     std::ifstream File(szPath, std::ios::binary | std::ios::ate);
  29. //
  30. //     if (File.fail())
  31. //     {
  32. //         printf("Opening the file failed: %X\n", (DWORD)File.rdstate());
  33. //         File.close();
  34. //         CloseHandle(hProc);
  35. //         system("PAUSE");
  36. //         return -5;
  37. //     }
  38. //
  39. //     auto FileSize = File.tellg();
  40. //     if (FileSize < 0x1000)
  41. //     {
  42. //         printf("Filesize invalid.\n");
  43. //         File.close();
  44. //         CloseHandle(hProc);
  45. //         system("PAUSE");
  46. //         return -6;
  47. //     }
  48. //
  49. //     BYTE* pSrcData = new BYTE[(UINT_PTR)FileSize];
  50. //     if (!pSrcData)
  51. //     {
  52. //         printf("Can't allocate dll file.\n");
  53. //         File.close();
  54. //         CloseHandle(hProc);
  55. //         system("PAUSE");
  56. //         return -7;
  57. //     }
  58. //
  59. //     File.seekg(0, std::ios::beg);
  60. //     File.read((char*)(pSrcData), FileSize);
  61. //     File.close();
  62.     CFile file;
  63.     file.Open(szPath, CFile::modeRead);
  64.     ULONGLONG nFileSize = file.GetLength();
  65.     BYTE* pSrcData = new BYTE[nFileSize];
  66.     ZeroMemory(pSrcData,nFileSize);
  67.     file.SeekToBegin();
  68.     file.Read(pSrcData,nFileSize);
  69.     file.Close();
  70.     if (!ManualMapDll(hProc, pSrcData, nFileSize))
  71.     {
  72.         delete[] pSrcData;
  73.         CloseHandle(hProc);
  74.         return false;
  75.     }
  76.     delete[] pSrcData;
  77.     CloseHandle(hProc);
  78.     return false;
  79. }
  80. bool ManualMapDll(HANDLE hProc, BYTE* pSrcData, SIZE_T FileSize, bool ClearHeader,
  81.     bool ClearNonNeededSections, bool AdjustProtections,
  82.     bool SEHExceptionSupport, DWORD fdwReason, LPVOID lpReserved)
  83. {
  84.     IMAGE_NT_HEADERS* pOldNtHeader = nullptr;
  85.     IMAGE_OPTIONAL_HEADER* pOldOptHeader = nullptr;
  86.     IMAGE_FILE_HEADER* pOldFileHeader = nullptr;
  87.     BYTE* pTargetBase = nullptr;
  88.     if (reinterpret_cast<IMAGE_DOS_HEADER*>(pSrcData)->e_magic != 0x5A4D)//"MZ"
  89.     {
  90.         return false;
  91.     }
  92.     pOldNtHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(pSrcData + reinterpret_cast<IMAGE_DOS_HEADER*>(pSrcData)->e_lfanew);
  93.     pOldOptHeader = &pOldNtHeader->OptionalHeader;
  94.     pOldFileHeader = &pOldNtHeader->FileHeader;
  95.     if (pOldFileHeader->Machine != CURRENT_ARCH)
  96.     {
  97.         return false;
  98.     }
  99.     pTargetBase = reinterpret_cast<BYTE*>(VirtualAllocEx(hProc, nullptr, pOldOptHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
  100.     if (!pTargetBase)
  101.     {
  102.         return false;
  103.     }
  104.     DWORD oldp = 0;
  105.     VirtualProtectEx(hProc, pTargetBase, pOldOptHeader->SizeOfImage, PAGE_EXECUTE_READWRITE, &oldp);
  106.     MANUAL_MAPPING_DATA data{ 0 };
  107.     data.pLoadLibraryA = LoadLibraryA;
  108.     data.pGetProcAddress = GetProcAddress;
  109. #ifdef _WIN64
  110.     data.pRtlAddFunctionTable = (f_RtlAddFunctionTable)RtlAddFunctionTable;
  111. #else
  112.     SEHExceptionSupport = false;
  113. #endif
  114.     data.pbase = pTargetBase;
  115.     data.fdwReasonParam = fdwReason;
  116.     data.reservedParam = lpReserved;
  117.     data.SEHSupport = SEHExceptionSupport;
  118.     //PE header
  119.     if (!WriteProcessMemory(hProc, pTargetBase, pSrcData, 0x1000, nullptr)) //only first 0x1000 bytes for the header
  120.     {
  121.         VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
  122.         return false;
  123.     }
  124.     IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader);
  125.     for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader)
  126.     {
  127.         if (pSectionHeader->SizeOfRawData)
  128.         {
  129.             if (!WriteProcessMemory(hProc, pTargetBase + pSectionHeader->VirtualAddress, pSrcData + pSectionHeader->PointerToRawData, pSectionHeader->SizeOfRawData, nullptr))
  130.             {
  131.                 VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
  132.                 return false;
  133.             }
  134.         }
  135.     }
  136.     //Mapping params
  137.     BYTE* MappingDataAlloc = reinterpret_cast<BYTE*>(VirtualAllocEx(hProc, nullptr, sizeof(MANUAL_MAPPING_DATA), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
  138.     if (!MappingDataAlloc)
  139.     {
  140.         VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
  141.         return false;
  142.     }
  143.     if (!WriteProcessMemory(hProc, MappingDataAlloc, &data, sizeof(MANUAL_MAPPING_DATA), nullptr))
  144.     {
  145.         VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
  146.         VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
  147.         return false;
  148.     }
  149.     //Shell code
  150.     void* pShellcode = VirtualAllocEx(hProc, nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  151.     if (!pShellcode)
  152.     {
  153.         VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
  154.         VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
  155.         return false;
  156.     }
  157.     if (!WriteProcessMemory(hProc, pShellcode, Shellcode, 0x1000, nullptr))
  158.     {
  159.         VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
  160.         VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
  161.         VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE);
  162.         return false;
  163.     }
  164.     HANDLE hThread = CreateRemoteThread(hProc, nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(pShellcode), MappingDataAlloc, 0, nullptr);
  165.     if (!hThread)
  166.     {
  167.         VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
  168.         VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
  169.         VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE);
  170.         return false;
  171.     }
  172.     WaitForSingleObject(hThread, INFINITE);
  173.     CloseHandle(hThread);
  174.     HINSTANCE hCheck = NULL;
  175.     while (!hCheck)
  176.     {
  177.         DWORD exitcode = 0;
  178.         GetExitCodeProcess(hProc, &exitcode);
  179.         if (exitcode != STILL_ACTIVE)
  180.         {
  181.             return false;
  182.         }
  183.         MANUAL_MAPPING_DATA data_checked{ 0 };
  184.         ReadProcessMemory(hProc, MappingDataAlloc, &data_checked, sizeof(data_checked), nullptr);
  185.         hCheck = data_checked.hMod;
  186.         if (hCheck == (HINSTANCE)0x404040)
  187.         {
  188.             VirtualFreeEx(hProc, pTargetBase, 0, MEM_RELEASE);
  189.             VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
  190.             VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE);
  191.             return false;
  192.         }
  193.         else if (hCheck == (HINSTANCE)0x505050)
  194.         {
  195.             //Exception support failed!
  196.         }
  197.         Sleep(10);
  198.     }
  199.     BYTE* emptyBuffer = (BYTE*)malloc(1024 * 1024 * 20);
  200.     if (emptyBuffer == nullptr)
  201.     {
  202.         return false;
  203.     }
  204.     memset(emptyBuffer, 0, 1024 * 1024 * 20);
  205.     //CLEAR PE HEAD
  206.     if (ClearHeader)
  207.     {
  208.         WriteProcessMemory(hProc, pTargetBase, emptyBuffer, 0x1000, nullptr);
  209.     }
  210.     //END CLEAR PE HEAD
  211.     if (ClearNonNeededSections)
  212.     {
  213.         pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader);
  214.         for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader)
  215.         {
  216.             if (pSectionHeader->Misc.VirtualSize)
  217.             {
  218.                 if ((SEHExceptionSupport ? 0 : strcmp((char*)pSectionHeader->Name, ".pdata") == 0) ||
  219.                     strcmp((char*)pSectionHeader->Name, ".rsrc") == 0 ||
  220.                     strcmp((char*)pSectionHeader->Name, ".reloc") == 0)
  221.                 {
  222.                     WriteProcessMemory(hProc, pTargetBase + pSectionHeader->VirtualAddress, emptyBuffer, pSectionHeader->Misc.VirtualSize, nullptr);
  223.                 }
  224.             }
  225.         }
  226.     }
  227.     if (AdjustProtections)
  228.     {
  229.         pSectionHeader = IMAGE_FIRST_SECTION(pOldNtHeader);
  230.         for (UINT i = 0; i != pOldFileHeader->NumberOfSections; ++i, ++pSectionHeader)
  231.         {
  232.             if (pSectionHeader->Misc.VirtualSize)
  233.             {
  234.                 DWORD old = 0;
  235.                 DWORD newP = PAGE_READONLY;
  236.                 if ((pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE) > 0)
  237.                 {
  238.                     newP = PAGE_READWRITE;
  239.                 }
  240.                 else if ((pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) > 0)
  241.                 {
  242.                     newP = PAGE_EXECUTE_READ;
  243.                 }
  244.                 VirtualProtectEx(hProc, pTargetBase + pSectionHeader->VirtualAddress, pSectionHeader->Misc.VirtualSize, newP, &old);
  245.             }
  246.         }
  247.         DWORD old = 0;
  248.         VirtualProtectEx(hProc, pTargetBase, IMAGE_FIRST_SECTION(pOldNtHeader)->VirtualAddress, PAGE_READONLY, &old);
  249.     }
  250.     WriteProcessMemory(hProc, pShellcode, emptyBuffer, 0x1000, nullptr);
  251.     VirtualFreeEx(hProc, pShellcode, 0, MEM_RELEASE);
  252.     VirtualFreeEx(hProc, MappingDataAlloc, 0, MEM_RELEASE);
  253.     return true;
  254. }
  255. //#pragma runtime_checks( "", off )
  256. //#pragma optimize( "", off )
  257. void __stdcall Shellcode(MANUAL_MAPPING_DATA* pData)
  258. {
  259.     if (!pData)
  260.     {
  261.         pData->hMod = (HINSTANCE)0x404040;
  262.         return;
  263.     }
  264.     BYTE* pBase = pData->pbase;
  265.     auto* pOpt = &reinterpret_cast<IMAGE_NT_HEADERS*>(pBase + reinterpret_cast<IMAGE_DOS_HEADER*>((uintptr_t)pBase)->e_lfanew)->OptionalHeader;
  266.     auto _LoadLibraryA = pData->pLoadLibraryA;
  267.     auto _GetProcAddress = pData->pGetProcAddress;
  268. #ifdef _WIN64
  269.     auto _RtlAddFunctionTable = pData->pRtlAddFunctionTable;
  270. #endif
  271.     auto _DllMain = reinterpret_cast<f_DLL_ENTRY_POINT>(pBase + pOpt->AddressOfEntryPoint);
  272.     BYTE* LocationDelta = pBase - pOpt->ImageBase;
  273.     if (LocationDelta) {
  274.         if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
  275.         {
  276.             auto* pRelocData = reinterpret_cast<IMAGE_BASE_RELOCATION*>(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
  277.             const auto* pRelocEnd = reinterpret_cast<IMAGE_BASE_RELOCATION*>(reinterpret_cast<uintptr_t>(pRelocData) + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
  278.             while (pRelocData < pRelocEnd && pRelocData->SizeOfBlock)
  279.             {
  280.                 UINT AmountOfEntries = (pRelocData->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
  281.                 WORD* pRelativeInfo = reinterpret_cast<WORD*>(pRelocData + 1);
  282.                 for (UINT i = 0; i != AmountOfEntries; ++i, ++pRelativeInfo)
  283.                 {
  284.                     if (RELOC_FLAG(*pRelativeInfo))
  285.                     {
  286.                         UINT_PTR* pPatch = reinterpret_cast<UINT_PTR*>(pBase + pRelocData->VirtualAddress + ((*pRelativeInfo) & 0xFFF));
  287.                         *pPatch += reinterpret_cast<UINT_PTR>(LocationDelta);
  288.                     }
  289.                 }
  290.                 pRelocData = reinterpret_cast<IMAGE_BASE_RELOCATION*>(reinterpret_cast<BYTE*>(pRelocData) + pRelocData->SizeOfBlock);
  291.             }
  292.         }
  293.     }
  294.     if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
  295.     {
  296.         auto* pImportDescr = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*>(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  297.         while (pImportDescr->Name)
  298.         {
  299.             char* szMod = reinterpret_cast<char*>(pBase + pImportDescr->Name);
  300.             HINSTANCE hDll = _LoadLibraryA(szMod);
  301.             ULONG_PTR* pThunkRef = reinterpret_cast<ULONG_PTR*>(pBase + pImportDescr->OriginalFirstThunk);
  302.             ULONG_PTR* pFuncRef = reinterpret_cast<ULONG_PTR*>(pBase + pImportDescr->FirstThunk);
  303.             if (!pThunkRef)
  304.                 pThunkRef = pFuncRef;
  305.             for (; *pThunkRef; ++pThunkRef, ++pFuncRef)
  306.             {
  307.                 if (IMAGE_SNAP_BY_ORDINAL(*pThunkRef))
  308.                 {
  309.                     *pFuncRef = (ULONG_PTR)_GetProcAddress(hDll, reinterpret_cast<char*>(*pThunkRef & 0xFFFF));
  310.                 }
  311.                 else
  312.                 {
  313.                     auto* pImport = reinterpret_cast<IMAGE_IMPORT_BY_NAME*>(pBase + (*pThunkRef));
  314.                     *pFuncRef = (ULONG_PTR)_GetProcAddress(hDll, pImport->Name);
  315.                 }
  316.             }
  317.             ++pImportDescr;
  318.         }
  319.     }
  320.     if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
  321.     {
  322.         auto* pTLS = reinterpret_cast<IMAGE_TLS_DIRECTORY*>(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
  323.         auto* pCallback = reinterpret_cast<PIMAGE_TLS_CALLBACK*>(pTLS->AddressOfCallBacks);
  324.         for (; pCallback && *pCallback; ++pCallback)
  325.             (*pCallback)(pBase, DLL_PROCESS_ATTACH, nullptr);
  326.     }
  327.     bool ExceptionSupportFailed = false;
  328. #ifdef _WIN64
  329.     if (pData->SEHSupport)
  330.     {
  331.         auto excep = pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
  332.         if (excep.Size) {
  333.             if (!_RtlAddFunctionTable(
  334.                 reinterpret_cast<IMAGE_RUNTIME_FUNCTION_ENTRY*>(pBase + excep.VirtualAddress),
  335.                 excep.Size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY), (DWORD64)pBase))
  336.             {
  337.                 ExceptionSupportFailed = true;
  338.             }
  339.         }
  340.     }
  341. #endif
  342.     _DllMain(pBase, pData->fdwReasonParam, pData->reservedParam);
  343.     if (ExceptionSupportFailed)
  344.         pData->hMod = reinterpret_cast<HINSTANCE>(0x505050);
  345.     else
  346.         pData->hMod = reinterpret_cast<HINSTANCE>(pBase);
  347. }
运行效果如下:: K4 c  R3 G4 n: g' G5 k2 Q  I
2.jpg
1 L# L) _* d' `5 D1 h 3.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|paopaomj.COM ( 渝ICP备18007172号|渝公网安备50010502503914号 )

GMT+8, 2024-11-23 20:24

Powered by paopaomj X3.5 © 2016-2025 sitemap

快速回复 返回顶部 返回列表