首页 > 编程知识 正文

易语言断链隐藏dll,断链

时间:2023-05-05 21:47:30 阅读:263140 作者:306

0x4 PEB断链隐藏模块 1.如何找到_PEB_LDR_DATA

由_TEB找到_PEB,_PEB偏移0xC找到_PEB_LDR_DATA

2.基础知识

_LDR_DATA_TABLE_ENTRY结构

ntdll!_LDR_DATA_TABLE_ENTRY +0x000 InLoadOrderLinks : _LIST_ENTRY//_PEB_LDR_DATA的第一个_LIST_ENTRY结构指向这里 +0x008 InMemoryOrderLinks : _LIST_ENTRY//_PEB_LDR_DATA的第二个_LIST_ENTRY结构指向这里 +0x010 InInitializationOrderLinks : _LIST_ENTRY//_PEB_LDR_DATA的第三个_LIST_ENTRY结构指向这里 +0x018 DllBase : Ptr32 Void//DLL基址 +0x01c EntryPoint : Ptr32 Void +0x020 SizeOfImage : Uint4B +0x024 FullDllName : _UNICODE_STRING//带路径的dll的名称 +0x02c BaseDllName : _UNICODE_STRING//dll的名称 +0x034 Flags : Uint4B +0x038 LoadCount : Uint2B +0x03a TlsIndex : Uint2B +0x03c HashLinks : _LIST_ENTRY +0x03c SectionPointer : Ptr32 Void +0x040 CheckSum : Uint4B +0x044 TimeDateStamp : Uint4B +0x044 LoadedImports : Ptr32 Void +0x048 EntryPointActivationContext : Ptr32 _ACTIVATION_CONTEXT +0x04c PatchInformation : Ptr32 Void +0x050 ForwarderLinks : _LIST_ENTRY +0x058 ServiceTagLinks : _LIST_ENTRY +0x060 StaticLinks : _LIST_ENTRY +0x068 ContextInformation : Ptr32 Void +0x06c OriginalBase : Uint4B +0x070 LoadTime : _LARGE_INTEGER

_PEB_LDR_DATA结构

typedef struct _PEB_LDR_DATA{ULONG Length; // +0x00BOOLEAN Initialized; // +0x04PVOID SsHandle; // +0x08LIST_ENTRY InLoadOrderModuleList; // +0x0c 加载顺序LIST_ENTRY InMemoryOrderModuleList; // +0x14 在内存中的顺序LIST_ENTRY InInitializationOrderModuleList;// +0x1c 初始化装载顺序PVOID EntryInProgress;// +0x24} PEB_LDR_DATA,*PPEB_LDR_DATA;

_LIST_ENTRY结构

typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink;} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY; 3.实现原理

_PEB_LDR_DATA后三个成员存储的是该程序所有模块的信息(用链表存储)
因此只要将这些信息抹除,就可以欺骗那些调用API扫描模块的程序了。
由于存储信息的是个链表,所以只要修改一下指针即可,并不复杂。

4.调试找模块



_PEB_LDR_DATA的第一个_LDR_DATA_TABLE_ENTRY是该程序的exe,windbg里显示不出来(3环程序!)

5.实现代码(不是驱动!在ring3执行就好)

隐藏所有模块

#include "stdafx.h"#include "windows.h"typedef struct _PEB_LDR_DATA{ULONG Length; // +0x00BOOLEAN Initialized; // +0x04PVOID SsHandle; // +0x08LIST_ENTRY InLoadOrderModuleList; // +0x0cLIST_ENTRY InMemoryOrderModuleList; // +0x14LIST_ENTRY InInitializationOrderModuleList;// +0x1cPVOID EntryInProgress;// +0x24} PEB_LDR_DATA,*PPEB_LDR_DATA; void HideModule(){PPEB_LDR_DATA ldr;PLIST_ENTRY Head;__asm{mov eax,fs:[0x30] //只有在ring3_TEB的值为fs[0],偏移0x30到_PEBmov ecx,[eax+0xC]//_PEB偏移0xC到PEB_LDRmov ldr,ecx}// 分别将三个链表断链处理Head = &(ldr->InLoadOrderModuleList);Head->Flink = Head->Blink = Head;//处理成空的双向循环链表Head = &(ldr->InMemoryOrderModuleList);Head->Flink = Head->Blink = Head;//处理成空的双向循环链表Head = &(ldr->InInitializationOrderModuleList);Head->Flink = Head->Blink = Head;//处理成空的双向循环链表}int main(){printf("未断链n");getchar();HideModule();printf("断链后n");getchar();return 0;}

效果如下:

隐藏某个模块

#include "stdafx.h"#include "windows.h"typedef struct _UNICODE_STRING {USHORT Length;USHORT MaximumLength;PWSTR Buffer;}UNICODE_STRING, *PUNICODE_STRING;typedef struct _PEB_LDR_DATA{ULONG Length; // +0x00BOOLEAN Initialized; // +0x04PVOID SsHandle; // +0x08LIST_ENTRY InLoadOrderModuleList; // +0x0cLIST_ENTRY InMemoryOrderModuleList; // +0x14LIST_ENTRY InInitializationOrderModuleList;// +0x1cPVOID EntryInProgress;// +0x24} PEB_LDR_DATA,*PPEB_LDR_DATA; typedef struct _LDR_DATA_TABLE_ENTRY{LIST_ENTRY InLoadOrderLinks;LIST_ENTRY InMemoryOrderLinks;LIST_ENTRY InInitializationOrderLinks;PVOID DllBase;PVOID EntryPoint;ULONG SizeOfImage;UNICODE_STRING FullDllName;UNICODE_STRING BaseDllName;//后面不写了,用不到} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;int STRCMP(unsigned short *str1,unsigned short *str2)//自己实现一个UNICODE字符串比较{int flag = 0;while (*str1){if (*str1 != *str2){flag = 1;break;}str1++;str2++;}return flag;}void HideModule(UNICODE_STRING DllName){PPEB_LDR_DATA ldr;PLDR_DATA_TABLE_ENTRY Node;PLIST_ENTRY Head,Temp;__asm{mov eax,fs:[0x30] //只有在ring3_TEB的值为fs[0],偏移0x30到_PEBmov ecx,[eax+0xC]//_PEB偏移0xC到PEB_LDRmov ldr,ecx}// 分别将三个链表断链处理//1Head = &(ldr->InLoadOrderModuleList);//第一项是自己的exe,windbg显示不出来Temp = Head->Flink;printf("以下为所有模块名:n");do{//CONTAINING_RECORD宏的作用就是根据结构体类型和结构体中成员变量地址和名称,则可求出该变量所在结构体的指针Node = (PLDR_DATA_TABLE_ENTRY)Temp;//InLoadOrderLinks就是结构体第一个成员,不必CONTAINING_RECORDprintf("%lsn",Node->BaseDllName.Buffer);//打印所有模块名if (!STRCMP(Node->BaseDllName.Buffer,DllName.Buffer)){Node->InLoadOrderLinks.Blink->Flink = Node->InLoadOrderLinks.Flink; Node->InLoadOrderLinks.Flink->Blink = Node->InLoadOrderLinks.Blink; }Temp = Temp->Flink;} while(Head != Temp);//2Head = &(ldr->InMemoryOrderModuleList);Temp = Head->Flink;do{//CONTAINING_RECORD宏的作用就是根据结构体类型和结构体中成员变量地址和名称,则可求出该变量所在结构体的指针Node = CONTAINING_RECORD(Temp, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); if (!STRCMP(Node->BaseDllName.Buffer,DllName.Buffer)){Node->InMemoryOrderLinks.Blink->Flink = Node->InMemoryOrderLinks.Flink; Node->InMemoryOrderLinks.Flink->Blink = Node->InMemoryOrderLinks.Blink; }Temp = Temp->Flink;} while(Head != Temp);//3Head = &(ldr->InInitializationOrderModuleList);Temp = Head->Flink;do{//CONTAINING_RECORD宏的作用就是根据结构体类型和结构体中成员变量地址和名称,则可求出该变量所在结构体的指针Node = CONTAINING_RECORD(Temp, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);if (!STRCMP(Node->BaseDllName.Buffer,DllName.Buffer)){Node->InInitializationOrderLinks.Blink->Flink = Node->InInitializationOrderLinks.Flink; Node->InInitializationOrderLinks.Flink->Blink = Node->InInitializationOrderLinks.Blink; }Temp = Temp->Flink;} while(Head != Temp);}int main(){printf("未断链n");getchar();WCHAR MoudleName[] = L"ntdll.dll";//要隐藏的dll名称UNICODE_STRING YourMoudle;YourMoudle.MaximumLength = strlen((char*)MoudleName) + 1;YourMoudle.Length = strlen((char*)MoudleName);YourMoudle.Buffer = MoudleName;HideModule(YourMoudle);printf("断链后n");printf("隐藏的模块名为:%ls",YourMoudle.Buffer);getchar();return 0;}

效果如图:

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。