快速恢复Safengine Protector的Shadow DLL
本文以Safengine Protector v2.3.x.0為例, 提供了一種C++代碼快速恢復Safengine的Shadow DLL的方法, 沒啥技術含量, 僅希望能給各位一點參考.
Shadow DLL是一種加密殼常見的反Hook/反下斷方案, 工作原理簡言之就是自行加載系統DLL, 并重定向受保護程序的API調用到相應處理過的Shadow DLL, 由此繞開了對原有系統DLL的調用, 阻止對系統DLL的下斷和攔截. 詳細請參閱半斤八兩前輩的文章【原創】Kill Safengine Shadow Dll(附源碼)
那如何恢復呢?上面那篇文章已經講得非常清楚了, 本文只是補充了一點, 即快速恢復.
有時候我們只對特定的API感興趣, 那么我們大可通過PE結構直接確定該API在物理文件中的位置(File Offset), HOOK NtReadFile攔截殼對系統DLL文件的讀取, 接著在特定位置使用0xFF25 jmp到系統DLL, 完成恢復.
攔截部分, 我的做法是HOOK NtCreateFile, NtReadFile, NtClose以確定殼正在加載那個DLL, 這種方法感覺最為簡單高效, 無須額外的API調用(僅僅HOOK NtReadFile你無法直接判斷打開的是什么文件), 然后可能你還要記錄讀取的位置, 因為SE殼會分多次, 而不是一次性讀入, 如果特定位置恰好在分塊位置, 你就需要特殊處理.
下面附上由Export Name確定對應File Offset的方法, 可算是本文的核心代碼:
static DWORD KiGetFileOffset(LPVOID lpBaseOfImage, LPCSTR lpTargetFuncName) {auto lpNtHeader = RtlImageNtHeader(lpBaseOfImage);auto sizeOfExpDir = 0UL; auto lpExportDir = static_cast<PIMAGE_EXPORT_DIRECTORY>(RtlImageDirectoryEntryToData(lpBaseOfImage, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &sizeOfExpDir));/*PIMAGE_DATA_DIRECTORY lpExportDirEntry = &lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];assert(lpExportDirEntry->Size != 0 && "no export table found!");auto lpExportDir = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(lpNtHeader->OptionalHeader.ImageBase + lpExportDirEntry->VirtualAddress);*/DWORD dwVirtualAddress = NULL;auto AddressOfNames = reinterpret_cast<PDWORD>(lpNtHeader->OptionalHeader.ImageBase + lpExportDir->AddressOfNames);auto AddressOfFunctions = reinterpret_cast<PDWORD>(lpNtHeader->OptionalHeader.ImageBase + lpExportDir->AddressOfFunctions);auto AddressOfNameOrdinals = reinterpret_cast<PUSHORT>(lpNtHeader->OptionalHeader.ImageBase + lpExportDir->AddressOfNameOrdinals);if (reinterpret_cast<DWORD>(lpTargetFuncName) & 0xFFFF0000) {long high = lpExportDir->NumberOfNames - 1;long low = 0;while (low <= high){auto mid = (high + low) >> 1;auto name = reinterpret_cast<PCHAR>(lpNtHeader->OptionalHeader.ImageBase) + AddressOfNames[mid];auto Idx = 0;while (name[Idx] && name[Idx] == lpTargetFuncName[Idx]) {++Idx;}auto ret = name[Idx] - lpTargetFuncName[Idx];if (ret == 0) {dwVirtualAddress = AddressOfFunctions[AddressOfNameOrdinals[mid]];break;} else if (ret > 0) {high = mid - 1;} else {low = mid + 1;} //if}} else {dwVirtualAddress = AddressOfFunctions[reinterpret_cast<DWORD>(lpTargetFuncName) & 0x0FFFF];} //ifif (!dwVirtualAddress) {return NULL;} //ifDWORD VRk = 0xffffffffUL;auto lpSection = IMAGE_FIRST_SECTION(lpNtHeader);for (register int i = 0; i < lpNtHeader->FileHeader.NumberOfSections; ++i, ++lpSection) {if (dwVirtualAddress > lpSection->VirtualAddress && dwVirtualAddress < (lpSection->VirtualAddress + lpSection->Misc.VirtualSize)){VRk = lpSection->VirtualAddress - lpSection->PointerToRawData;break;} //if} //forreturn VRk != 0xffffffffUL ? (dwVirtualAddress - VRk) : NULL; }
總結
以上是生活随笔為你收集整理的快速恢复Safengine Protector的Shadow DLL的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HMAC 算法原理
- 下一篇: 读书笔记《一个App的诞生》