反射式DLL注入实现
https://mp.weixin.qq.com/s/SmHT6NswqsmZDKKKTjUHgw
反射式DLL注入实现
收录于合集#“雪花”创作激励计划63个本文为看雪论坛优秀文章
看雪论坛作者ID:_DriverEntry
反射式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.cppusing 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);using f_RtlAddFunctionTable = BOOL(WINAPIV*)(PRUNTIME_FUNCTION FunctionTable, DWORD EntryCount, DWORD64 BaseAddress);struct MANUAL_MAPPING_DATA{f_LoadLibraryA pLoadLibraryA;f_GetProcAddress pGetProcAddress;f_RtlAddFunctionTable pRtlAddFunctionTable;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);};
运行效果如下: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(pSrcData)->e_magic != 0x5A4D)//"MZ" {return false;}pOldNtHeader = reinterpret_cast(pSrcData + reinterpret_cast (pSrcData)->e_lfanew); pOldOptHeader = &pOldNtHeader->OptionalHeader;pOldFileHeader = &pOldNtHeader->FileHeader;if (pOldFileHeader->Machine != CURRENT_ARCH){return false;}pTargetBase = reinterpret_cast(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;data.pRtlAddFunctionTable = (f_RtlAddFunctionTable)RtlAddFunctionTable;SEHExceptionSupport = false;data.pbase = pTargetBase;data.fdwReasonParam = fdwReason;data.reservedParam = lpReserved;data.SEHSupport = SEHExceptionSupport;//PE headerif (!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 paramsBYTE* MappingDataAlloc = reinterpret_cast(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 codevoid* 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(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 HEADif (ClearHeader){WriteProcessMemory(hProc, pTargetBase, emptyBuffer, 0x1000, nullptr);}//END CLEAR PE HEADif (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(pBase + reinterpret_cast ((uintptr_t)pBase)->e_lfanew)->OptionalHeader; auto _LoadLibraryA = pData->pLoadLibraryA;auto _GetProcAddress = pData->pGetProcAddress;auto _RtlAddFunctionTable = pData->pRtlAddFunctionTable;auto _DllMain = reinterpret_cast(pBase + pOpt->AddressOfEntryPoint); BYTE* LocationDelta = pBase - pOpt->ImageBase;if (LocationDelta) {if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size){auto* pRelocData = reinterpret_cast(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); const auto* pRelocEnd = reinterpret_cast(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(pRelocData + 1); for (UINT i = 0; i != AmountOfEntries; ++i, ++pRelativeInfo){if (RELOC_FLAG(*pRelativeInfo)){UINT_PTR* pPatch = reinterpret_cast(pBase + pRelocData->VirtualAddress + ((*pRelativeInfo) & 0xFFF)); *pPatch += reinterpret_cast(LocationDelta); }}pRelocData = reinterpret_cast(reinterpret_cast (pRelocData) + pRelocData->SizeOfBlock); }}}if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size){auto* pImportDescr = reinterpret_cast(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(pBase + pImportDescr->OriginalFirstThunk); ULONG_PTR* pFuncRef = reinterpret_cast(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(pBase + (*pThunkRef)); *pFuncRef = (ULONG_PTR)_GetProcAddress(hDll, pImport->Name);}}++pImportDescr;}}if (pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size){auto* pTLS = reinterpret_cast(pBase + pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); auto* pCallback = reinterpret_cast(pTLS->AddressOfCallBacks); for (; pCallback && *pCallback; ++pCallback)(*pCallback)(pBase, DLL_PROCESS_ATTACH, nullptr);}bool ExceptionSupportFailed = false;if (pData->SEHSupport){auto excep = pOpt->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];if (excep.Size) {if (!_RtlAddFunctionTable(reinterpret_cast(pBase + excep.VirtualAddress), excep.Size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY), (DWORD64)pBase)){ExceptionSupportFailed = true;}}}_DllMain(pBase, pData->fdwReasonParam, pData->reservedParam);if (ExceptionSupportFailed)pData->hMod = reinterpret_cast(0x505050); elsepData->hMod = reinterpret_cast(pBase); }
看雪ID:_DriverEntry
https://bbs.pediy.com/user-home-944747.htm
*本文由看雪论坛 _DriverEntry 原创,转载请注明来自看雪社区