|
一般而言要注入DLL到一个目标进程最简单的方法 就是先获取DLL文件路径,然后在目标进程分配内存空间将路径写入到目标进程,写入到目标进程后再调用CreateRemoteThread()/NtCreateThread()/RtlCreateUserThread()函数来运行LoadLibraryA/W函数调用自己的DLL,这种方法的缺陷也很明显那就是容易被游戏检测到,很容易被游戏拦截,比如CSGO最新版就已经有这个限制了。% g) m) ^; L1 |
想要突破CSGO的限制注入DLL进去,我们可以采用反射式注入的方法(也可以先恢复CSGOhook的api进行远程线程注入),那么什么是反射式注入呢?又有什么有点呢?
, i# l' H3 ^6 w, V* A+ B6 @" l 反射式dll注入与常规dll注入类似,而不同的地方在于反射式dll注入技术自己实现了一个reflective loader()函数来代替LoadLibaryA()函数去加载dll,示意图如下图所示。蓝色的线表示与用常规dll注入相同的步骤,红框中的是reflective loader()函数行为,也是下面重点描述的地方。2 S( U# h& H T
Reflective loader实现思路如下: 8 T9 ^5 j W, H3 ]7 `& h8 m
- 获得被注入进程未解析的dll的基地址。
- 获得必要的dll句柄和函数为修复导入表做准备。
- 分配一块新内存去取解析dll,并把pe头复制到新内存中和将各节复制到新内存中。
- 修复导入表和重定向表。
- 执行DllMain()函数。# G4 J5 v) T$ B: @8 F5 Q& [4 z {5 f
! X. _5 @7 H2 Y& Y1 a; R& W
% a* x, o* ~9 f! s
- L7 w# a1 H* I核心代码如下:
2 i# o1 i N! n- d+ ~ManualMapInject.h* r0 _) P2 x; f, s* k
- #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);
- };
ManualMapInject.cpp / E( K; C0 y( ?
- #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;
|
|