日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

模块隐藏(LDR_MODULE链 与 PE特征)

發(fā)布時(shí)間:2025/3/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 模块隐藏(LDR_MODULE链 与 PE特征) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

比較常見的模塊隱藏方法有抹去模塊的PE頭,斷開進(jìn)程的LDR_MODULE鏈,Hook模塊枚舉函數(shù)等。后面?zhèn)渥AD隱藏。

//測(cè)試EXE,加載WaiGua.dll,再隱藏。 #include <Windows.h> #include <stdio.h> #include <TLHELP32.H> typedef struct _LSA_UNICODE_STRING {USHORT Length;USHORT MaximumLength;PWSTR Buffer; } LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;typedef struct _LDR_MODULE{LIST_ENTRY InLoadOrderModuleList;LIST_ENTRY InMemoryOrderModuleList;LIST_ENTRY InInitializationOrderModuleList;PVOID BaseAddress;PVOID EntryPoint;ULONG SizeOfImage;UNICODE_STRING FullDllName;UNICODE_STRING BaseDllName;ULONG Flags;USHORT LoadCount;USHORT TlsIndex;LIST_ENTRY HashTableEntry;ULONG TimeDateStamp;} LDR_MODULE, *PLDR_MODULE, *PLML;// typedef struct _LE{ // DWORD Flink; // DWORD Blink; // }LE, LIST_ENTRY;BOOL BreakLdrModuleLink(DWORD dwBaseAddr) {PLDR_MODULE pLMFNode = NULL, pLNode = NULL ;PLDR_MODULE pLMHNode = NULL, pLMPNode = NULL;PLDR_MODULE pLMTNode = NULL;BOOL bSuccess = FALSE;//獲取LDR_MODULE鏈的頭指針__asm{pushadpushfdxor edx, edxmov ebx, fs:[edx + 0x30] mov ecx, [ebx + 0x0C] lea edx, [ecx + 0x0C]mov ecx, [ecx + 0x0C] mov pLMHNode, edx mov pLMFNode, ecxpopfdpopad}//查找目標(biāo)PLDR_MODULE pLMNode = pLMFNode;pLMPNode = pLMHNode;do{//比較是否是目標(biāo)模塊if( (DWORD)pLMNode->BaseAddress == dwBaseAddr){bSuccess = TRUE;break;}pLMPNode = pLMNode;pLMNode = (PLDR_MODULE)pLMNode->InLoadOrderModuleList.Flink;}while(pLMNode != pLMHNode);if( !bSuccess ){OutputDebugString("cannot find the dest module!");return bSuccess; //未找到目標(biāo)模塊}//斷開InLoadOrderModuleList鏈//重建FlinkpLMTNode = (PLDR_MODULE)pLMNode->InLoadOrderModuleList.Flink;pLMPNode->InLoadOrderModuleList.Flink = (PLIST_ENTRY)pLMTNode;//重建Blink((PLDR_MODULE)(pLMNode->InLoadOrderModuleList.Flink))->InLoadOrderModuleList.Blink = pLMNode->InLoadOrderModuleList.Blink;//斷開InMemoryOrderModuleList鏈//重建FlinkpLMPNode->InMemoryOrderModuleList.Flink = pLMNode->InMemoryOrderModuleList.Flink;//重建BlinkpLMTNode = (PLML)(pLMNode->InMemoryOrderModuleList.Flink - sizeof(LIST_ENTRY));pLMTNode->InMemoryOrderModuleList.Blink = pLMNode->InMemoryOrderModuleList.Blink;//斷開InInitializationOrderModuleList鏈//重建FlinkpLMPNode->InInitializationOrderModuleList.Flink = pLMNode->InInitializationOrderModuleList.Flink;//重建BlinkpLMTNode = (PLML)(pLMNode->InInitializationOrderModuleList.Flink - 2*sizeof(LIST_ENTRY));pLMTNode->InInitializationOrderModuleList.Blink = pLMNode->InInitializationOrderModuleList.Blink; }void ModuleHide(HMODULE hInjectDll) {DWORD dwOldProtect;VirtualProtect((LPVOID)hInjectDll,1024,PAGE_READWRITE, &dwOldProtect);PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER) hInjectDll;//抹去MZ標(biāo)志pDosHeader->e_magic = 0;//DOS頭后面就是PE頭//PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pDosHeader+1);PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((CHAR*)hInjectDll + pDosHeader->e_lfanew);//抹去PE標(biāo)志pNtHeader->Signature = 0;VirtualProtect((LPVOID)hInjectDll,1024,dwOldProtect, &dwOldProtect);//斷開LDR_MODULEBreakLdrModuleLink((DWORD)hInjectDll); }void EnumModule(void) {// TODO: Add your control notification handler code herechar szBuffer[256*100] = "";char szModuFile[240] = "";char szTmpBuffer[256] = "";MODULEENTRY32 moudle;HANDLE handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);if (handle == INVALID_HANDLE_VALUE){printf("枚舉模塊失敗!");return;}int i = 1;if ( Module32First(handle,&moudle)){ do{sprintf(szModuFile,"[%d]Address: 0x%x, Name: %s \r\n", i, moudle.modBaseAddr, moudle.szModule);strcat(szBuffer,szModuFile);i++;}while(Module32Next(handle,&moudle));}CloseHandle(handle);printf(szBuffer);} void main() {HMODULE hDll = LoadLibrary("WaiGua.dll");printf("this waigua.dll load at:0x%x\n",hDll);ModuleHide(hDll);EnumModule();getchar(); }


?

//WaiGua.dll BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) {switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:MessageBoxA(NULL, "the simple inject success", "Dll Inject", MB_OKCANCEL);break;case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE; }


?

備注:

摘要(轉(zhuǎn)自網(wǎng)絡(luò)):
一、從PEB的Ldr鏈中消失

????????????????????????????? 引用內(nèi)容

lkd> dt _PEB 7ffdc000 //當(dāng)前PEB的地址
nt!_PEB
????...
????+0x00cLdr??????????????: 0x001a1e90 _PEB_LDR_DATA?? //這里指向Ldr結(jié)構(gòu)
lkd> dt _PEB_LDR_DATA 0x001a1e90 //這個(gè)結(jié)構(gòu)里有三個(gè)鏈表的表頭
nt!_PEB_LDR_DATA
????+0x000Length????????????:0x28
????+0x004 Initialized??????: 0x1 ''
????+0x008SsHandle??????????: (null)
????+0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x1a1ec0 -0x1a34f8 ]
????+0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x1a1ec8- 0x1a3500 ]
????+0x01c InInitializationOrderModuleList : _LIST_ENTRY [0x1a1f28 - 0x1a3508 ]
????+0x024 EntryInProgress?? : (null)


這里看到有三個(gè)鏈表,其實(shí)三個(gè)鏈表的內(nèi)容是一樣的,但是鏈表的順序不一樣,分別按加載順序、內(nèi)存順序、初始化順序排列。
每一個(gè)DLL由一個(gè)LDR_DATA_TABLE_ENTRY結(jié)構(gòu)描述,但是第一個(gè)結(jié)構(gòu)被鏈入了三個(gè)鏈表。取一個(gè)來看看:

引用內(nèi)容

lkd> dt _LDR_DATA_TABLE_ENTRY 0x1a34f8
nt!_LDR_DATA_TABLE_ENTRY
????+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x1a1e9c -0x1a3450 ]
????+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x1a1ea4 -0x1a3458 ]
????+0x010 InInitializationOrderLinks : _LIST_ENTRY [0x1a1eac - 0x1a3460 ]
????+0x018DllBase?????????? :0x20000000
????+0x01cEntryPoint????????: (null)
????+0x020 SizeOfImage??????: 0x549000
????+0x024 FullDllName??????: _UNICODE_STRING "C:\WINDOWS\system32\xpsp2res.dll"
????+0x02c BaseDllName??????: _UNICODE_STRING "xpsp2res.dll"
?? ......//省略部分內(nèi)容


隨便取一個(gè)鏈表進(jìn)行遍歷,根據(jù)DllBase找到自己的DLL之后,從三個(gè)鏈中RemoveEntryList就可以了,這樣所有使用PEB->Ldr結(jié)構(gòu)來枚舉DLL鏈表的就無法找到了。
由于大部分ARK對(duì)隱藏DLL的查找并不是很重視(比如RKU,Gmer,XueTr,Atool,NIAP),因此該方法就可以bypass很多ARK了,還是有一定市場(chǎng)的~
但對(duì)IceSword是個(gè)例外

二、從VAD樹中消失
IceSword 在枚舉進(jìn)程模塊時(shí)使用的是ZwQueryVirtualMemory,查詢的InfoClass是MemorySectionName(或者叫 MemoryMappedFilenameInformation,值為2)。NtQueryVirtualMemory首先判斷Vad->ControlArea->FilePointer是否有效,若有效則調(diào)用ObQueryNameString查詢此文件對(duì)象的名 稱,最終由文件系統(tǒng)完成此次查詢工作。
關(guān)于VAD的詳細(xì)知識(shí),可以參考《JIURL玩玩Win2k內(nèi)存篇 VAD》,這里不作為重點(diǎn),知道是平衡二叉樹就可以了,樹的根結(jié)點(diǎn)在EPROCESS中。

引用內(nèi)容

lkd> dt _EPROCESS 83f915b8??
nt!_EPROCESS
????...
????+0x11cVadRoot?????????? :0x84079c08


該成員是一個(gè)MMVAD類型的結(jié)構(gòu),而成員LeftChild和RightChild分別是該結(jié)點(diǎn)的左子結(jié)點(diǎn)和右子結(jié)點(diǎn)。

引用內(nèi)容

lkd> dt _MMVAD 0x84079c08
nt!_MMVAD
????+0x000 StartingVpn??????: 0x8e0
????+0x004EndingVpn???????? : 0x8e0
????+0x008Parent????????????:(null)
????+0x00cLeftChild???????? : 0x843b1128 _MMVAD//左孩子
????+0x010RightChild????????: 0x840bf4a0 _MMVAD//右孩子
????+0x014u????????????????: __unnamed //標(biāo)志位
????+0x018 ControlArea??????: (null)
????+0x01c FirstPrototypePte : (null)
????+0x020 LastContiguousPte : (null)
????+0x024u2????????????????:__unnamed


要 對(duì)目標(biāo)DLL實(shí)施隱藏時(shí),先獲取該DLL基址,然后遍歷VAD樹,根據(jù)MMVAD->StartingVpn做匹配(StartingVpn實(shí)際上 是內(nèi)存地址的高20位,比如0x7c800000在這里將只顯示為0x7c800)找到目標(biāo)DLL的VAD結(jié)構(gòu)(這里以kernel32.dll為例,其 加載地址正為0x7c800000):

引用內(nèi)容

lkd> dt _MMVAD 84174a18
nt!_MMVAD
????+0x000 StartingVpn??????: 0x7c800
????+0x004EndingVpn???????? : 0x7c91b
????+0x008Parent????????????:0x841223a0 _MMVAD
????+0x00cLeftChild???????? : 0x84120470 _MMVAD
????+0x010RightChild????????: 0x841a4790 _MMVAD
????+0x014u????????????????: __unnamed
????+0x018 ControlArea??????: 0x876d0b88 _CONTROL_AREA //關(guān)鍵域
????+0x01c FirstPrototypePte : 0xe177d6f0 _MMPTE
????+0x020 LastContiguousPte : 0xfffffffc _MMPTE
????+0x024u2????????????????:__unnamed
lkd> dt _CONTROL_AREA 0x876d0b88
nt!_CONTROL_AREA
????...
????+0x024 FilePointer??????: 0x876d0b10 _FILE_OBJECT外//目標(biāo)在這里


好 了,看到FILE_OBJECT了,這時(shí)你應(yīng)該會(huì)想到系統(tǒng)是從這里取到的文件名吧,沒錯(cuò),這兒就是我們要?jiǎng)邮帜_的地方。根據(jù)小偉、Sysnap等人的測(cè) 試,只要把ControlArea->FilePointer->FileName.Buffer填0就可以實(shí)現(xiàn)該DLL的隱藏(根據(jù)字符串 的特性,實(shí)際上只需要把第一個(gè)字符填0就可以了),此時(shí)ZwQueryVirtualMemory將返回0xC0000039錯(cuò)誤,即“指定的路徑無 效”,自然也就枚舉不到了。而且對(duì)于那些共享的dll,如系統(tǒng)的ntdll.dll,kernel32.dll或在不同進(jìn)程中被加載2次或以上的dll, 雖然是在不同進(jìn)程中,但是使用的是同一個(gè)共享的ControlArea結(jié)構(gòu),因此只需要改一個(gè),那么在所有進(jìn)程中都將實(shí)現(xiàn)隱藏,這對(duì)于隱藏全局鉤子類型的dll顯然是非常方便的。
IS是在ZwQueryVirtualMemory查完全無法枚舉到DLL時(shí)才采用枚舉PEB的方法,因此結(jié)合前面的Ldr斷鏈法,足以搞定N多ARK了。
我所說的“從VAD樹中消失”只是使該VAD的信息從IS的查詢結(jié)果中消失,而并不是真的摘掉該VAD~~
值得一說的是,Sysnap的Yas Kit在檢測(cè)隱藏DLL方面也是比較強(qiáng)的,但是對(duì)于動(dòng)了VAD的,似乎也無能為力~

三、抹掉PE特征
有的工具可以直接枚舉所有有效內(nèi)存并檢查PE標(biāo)記來確定是否有隱藏DLL,因此需要把PE特征抹掉來對(duì)抗之,方法很簡(jiǎn)單,把PE頭整個(gè)填零就可以了。
這種方法主要是作為前兩種方法的補(bǔ)充,單獨(dú)搞是沒有意義的。

再來說說非正規(guī)方式加載的DLL,怎么個(gè)非正規(guī)呢?其實(shí)就是不用LoadLibrary,自已實(shí)現(xiàn)Loader的功能.
實(shí) 現(xiàn)Loader功能之后,不管你是Load別的DLL,或者DLL自已Load自己(老V的ReloadAndRun同樣適用于DLL),在Load完成 后,不會(huì)出現(xiàn)在PEB->Ldr鏈中,它的VAD也不會(huì)與FILE_OBJECT發(fā)生任何關(guān)系,然后再抹掉PE特征,隱藏效果與上面的正規(guī)隱藏法相 當(dāng),甚至要更隱蔽一些~~
再極端一點(diǎn),DLL也可以完全不要,注入具有相同功能的shellcode然后開線程執(zhí)行就可以了,只是shellcode寫起來麻煩一點(diǎn)而已,寫Loader也麻煩啊~~

?

?

http://bbs.pediy.com/archive/index.php?t-125571.html

http://lwglucky.blog.51cto.com/1228348/282331

?

總結(jié)

以上是生活随笔為你收集整理的模块隐藏(LDR_MODULE链 与 PE特征)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。