1937特种兵下载-qq管理器

进程隐藏
2023年3月31日发(作者:宝宝取名软件 破解)

再谈隐藏进程中的DLL模块

再谈隐藏进程中的DLL模块

学习各种⾼级外挂制作技术,马上去百度搜索"魔⿁作坊",点击第⼀个站进⼊,快速成为做挂达⼈。

相当⽼的话题,⼤约⼀年前就写过这个东西了,不过那时候知识⽐较有限,也不了解内核,因此实现得很粗浅,现在再写⼀

下,权当是对这个⽼问题的总结吧。

先谈谈正规DLL的隐藏⽅法,这⾥说的正规DLL,是指⽤LoadLibrary以正常⽅式加载的DLL。

⼀、从PEB的Ldr链中消失

这个很简单,看雪上NetRoc有⼀篇关于这个的⽂章,从分析原理到编程实现,虽然技术不算⾼深,但是思路⾮常精彩。来复

习⼀下吧~~

lkd>dt_PEB7ffdc000//当前PEB的地址

nt!_PEB

...

+0x00cLdr:0x001a1e90_PEB_LDR_DATA//这⾥指向Ldr结构lkd>dt_PEB_LDR_DATA0x001a1e90//这个结构⾥有三个链表

的表头

nt!_PEB_LDR_DATA

+0x000Length:0x28

+0x004Initialized:0x1''

+0x008SsHandle:(null)

+0x00cInLoadOrderModuleList:_LIST_ENTRY[0x1a1ec0-0x1a34f8]

+0x014InMemoryOrderModuleList:_LIST_ENTRY[0x1a1ec8-0x1a3500]

+0x01cInInitializationOrderModuleList:_LIST_ENTRY[0x1a1f28-0x1a3508]

+0x024EntryInProgress:(null)

这⾥看到有三个链表,其实三个链表的内容是⼀样的,但是链表的顺序不⼀样,分别按加载顺序、内存顺序、初始化顺序排列

也就是说每⼀个DLL由⼀个LDR_DATA_TABLE_ENTRY结构描述,但是第⼀个结构被链⼊了三个链表。取⼀个来看看:

lkd>dt_LDR_DATA_TABLE_ENTRY0x1a34f8

nt!_LDR_DATA_TABLE_ENTRY

+0x000InLoadOrderLinks:_LIST_ENTRY[0x1a1e9c-0x1a3450]

+0x008InMemoryOrderLinks:_LIST_ENTRY[0x1a1ea4-0x1a3458]

+0x010InInitializationOrderLinks:_LIST_ENTRY[0x1a1eac-0x1a3460]

+0x018DllBase:0x20000000

+0x01cEntryPoint:(null)

+0x020SizeOfImage:0x549000

+0x024FullDllName:_UNICODE_STRING"C:"

+0x02cBaseDllName:_UNICODE_STRING""

......//省略部分内容

随便取⼀个链表进⾏遍历,根据DllBase找到⾃⼰的DLL之后,从三个链中RemoveEntryList就可以了,这样所有使⽤PEB-

>Ldr结构来枚举DLL链表的就⽆法找到了。

由于⼤部分ARK对隐藏DLL的查找并不是很重视(⽐如RKU,Gmer,XueTr,Atool,NIAP),因此该⽅法就可以bypass很多ARK了,

还是有⼀定市场的~

但对IceSword是个例外,下⾯就来说说如何bypassIceSword

⼆、从VAD树中消失

IceSword在枚举进程模块时使⽤的是ZwQueryVirtualMemory,查询的InfoClass是MemorySectionName(或者叫

MemoryMappedFilenameInformation,值为2)。NtQueryVirtualMemory⾸先判断Vad->ControlArea->FilePointer是否有效,

若有效则调⽤ObQueryNameString查询此⽂件对象的名称,最终由⽂件系统完成此次查询⼯作。

关于VAD的详细知识,可以参考《JIURL玩玩Win2k内存篇VAD》,这⾥不作为重点,知道是平衡⼆叉树就可以了,树的根结

点在EPROCESS中。

lkd>dt_EPROCESS83f915b8

nt!_EPROCESS

...

+0x11cVadRoot:0x84079c08

该成员是⼀个MMVAD类型的结构,⽽成员LeftChild和RightChild分别是该结点的左⼦结点和右⼦结点。

lkd>dt_MMVAD0x84079c08

nt!_MMVAD

+0x000StartingVpn:0x8e0

+0x004EndingVpn:0x8e0

+0x008Parent:(null)

+0x00cLeftChild:0x843b1128_MMVAD//左孩⼦

+0x010RightChild:0x840bf4a0_MMVAD//右孩⼦

+0x014u:__unnamed//标志位

+0x018ControlArea:(null)

+0x01cFirstPrototypePte:(null)

+0x020LastContiguousPte:(null)

+0x024u2:__unnamed

要对⽬标DLL实施隐藏时,先获取该DLL基址,然后遍历VAD树,根据MMVAD->Starti

ngVpn做匹配(StartingVpn实际上是内存地址的⾼20位,⽐如0x7c800000在这⾥将只显⽰为0x7c800)找到⽬标DLL的VAD结

构(这⾥以为例,其加载地址正为0x7c800000):

lkd>dt_MMVAD84174a18

nt!_MMVAD

+0x000StartingVpn:0x7c800

+0x004EndingVpn:0x7c91b

+0x008Parent:0x841223a0_MMVAD

+0x00cLeftChild:0x84120470_MMVAD

+0x010RightChild:0x841a4790_MMVAD

+0x014u:__unnamed

+0x018ControlArea:0x876d0b88_CONTROL_AREA//关键域

+0x01cFirstPrototypePte:0xe177d6f0_MMPTE

+0x020LastContiguousPte:0xfffffffc_MMPTE

+0x024u2:__unnamed

lkd>dt_CONTROL_AREA0x876d0b88

nt!_CONTROL_AREA

...

+0x024FilePointer:0x876d0b10_FILE_OBJECT外//⽬标在这⾥

好了,看到FILE_OBJECT了,这时你应该会想到系统是从这⾥取到的⽂件名吧,没错,这⼉就是我们要动⼿脚的地⽅。根据

⼩伟、Sysnap等⼈的测试,只要把ControlArea->FilePointer->填0就可以实现该DLL的隐藏(根据字符串的特

性,实际上只需要把第⼀个字符填0就可以了),此时ZwQueryVirtualMemory将返回0xC0000039错误,即“指定的路径⽆效”,

⾃然也就枚举不到了。⽽且对于那些共享的dll,如系统的,或在不同进程中被加载2次或以上的dll,虽然是在

不同进程中,但是使⽤的是同⼀个共享的ControlArea结构,因此只需要改⼀个,那么在所有进程中都将实现隐藏,这对于隐藏

全局钩⼦类型的dll显然是⾮常⽅便的。

IS是在ZwQueryVirtualMemory查完全⽆法枚举到DLL时才采⽤枚举PEB的⽅法,因此结合前⾯的Ldr断链法,⾜以搞定N多

ARK了。

我所说的“从VAD树中消失”只是使该VAD的信息从IS的查询结果中消失,⽽并不是真的摘掉该VAD~~

值得⼀说的是,Sysnap的YasKit在检测隐藏DLL⽅⾯也是⽐较强的,但是对于动了VAD的,似乎也⽆能为⼒~

三、抹掉PE特征

有的⼯具可以直接枚举所有有效内存并检查PE标记来确定是否有隐藏DLL,因此需要把PE特征抹掉来对抗之,⽅法很简单,

把PE头整个填零就可以了。

这种⽅法主要是作为前两种⽅法的补充,单独搞是没有意义的。

再来说说⾮正规⽅式加载的DLL,怎么个⾮正规呢?其实就是不⽤LoadLibrary,⾃已实现Loader的功能.

实现Loader功能之后,不管你是Load别的DLL,或者DLL⾃已Load⾃⼰(⽼V的ReloadAndRun同样适⽤于DLL),在Load完成

后,不会出现在PEB->Ldr链中,它的VAD也不会与FILE_OBJECT发⽣任何关系,然后再抹掉PE特征,隐藏效果与上⾯的正

规隐藏法相当,甚⾄要更隐蔽⼀些~~

再极端⼀点,DLL也可以完全不要,注⼊具有相同功能的shellcode然后开线程执⾏就可以了,只是shellcode写起来⿇烦⼀点

⽽已,写Loader也⿇烦啊~~

总之只要能把我们的代码跑起来就OK,DLL隐藏就写到这⼉~~

更多推荐

进程隐藏