模块隐藏之断链

上一篇文章讨论了远程线程注入的相关知识,我们通过LoadLibraryA函数在目标进程加重了我们自己编写的dll并成功运行,但是这种方法显然很容易被发现,我们只要比较PE文件中的导入表和运行时加载的dll文件就能知道该进程是否被注入了,因此我们需要隐藏我们加载的dll

1 断链

TEB(Thread Environment Block),它记录的相关线程的信息,每一个线程都有自己的TEB,FS:[0]即是当前线程的TEB

PEB(Process Environment Block),进程环境块存放进程信息,每个进程都有自己的PEB信息,TEB偏移0x30即当前进程的PEB

我们借助windbg查看TEB和PEB的结构如下
在这里插入图片描述
在这里插入图片描述
在peb中有一个结构体为_PEB_LDR_DATA如下:
在这里插入图片描述
红框中的部分为三个双向链表,InLoadOrderModuleList为加载时的模块列表,InMemoryOrderModuleList为在内存中的模块列表,InInitializationOrderModuleList为初始化时的模块列表,链表里面的值为以下结构体
在这里插入图片描述
因此我们需要在这三个双向链表中把远程加载的dll文件删掉就能到达隐藏的目的

2 实验

我们编写断链隐藏dll的代码如下:

#include <iostream>
#include <windows.h>

typedef struct _UNICODE_STRING {
	USHORT Length;
	USHORT MaximumLength;
	PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;

typedef struct _PEB_LDR_DATA {
	ULONG length;
	UCHAR Initialized;
	PVOID SsHandle;
	LIST_ENTRY InLoadOrderModuleList;
	LIST_ENTRY InMemoryOrderModuleList;
	LIST_ENTRY InInitializationOrderModuleList;
	PVOID EntryInProgress;
	UCHAR ShutdownInProgress;
	PVOID ShutdownThreadId;

} PEB_LDR_DATA, * PPEB_LDR_DATA;

typedef struct _LDR_DATA_TABLE_ENTRY {
	LIST_ENTRY InLoadOrderLinks;		//代表按加载顺序构成的模块链表
	LIST_ENTRY InMemoryOrderLinks;		//代表按内存顺序构成的链表
	LIST_ENTRY InInitializationOrderLinks;		//代表按初始化顺序构成的链表
	PVOID BaseAddress;		//该模块基地址
	PVOID EntryPoint;		//该模块的入口
	ULONG SizeOfImage;		//该模块的影像大小
	UNICODE_STRING FullDllName;		//包含路径的模块名
	UNICODE_STRING BaseDllName;		//不包含路径的模块名
	ULONG Flags;
	USHORT LoadCount;		//该模块的引用次数
} LDR_MODULE, * PLDR_MODULE;

void Hide(char* moduleName) {
	HMODULE hMod = GetModuleHandle(moduleName);
	PLIST_ENTRY Head, Cur;
	PPEB_LDR_DATA ldr;
	PLDR_MODULE ldm;
	__asm
	{
		mov eax , fs:[0x30]
		mov ecx , [eax + 0x0c]
		mov ldr , ecx
	}
	Head = &(ldr->InLoadOrderModuleList);
	Cur = Head->Flink;
	do
	{
		//宏CONTAINING_RECORD根据结构体中的某成员的地址来推算结构体的地址
		ldm = CONTAINING_RECORD(Cur, LDR_MODULE, InLoadOrderLinks);
		if (hMod == ldm->BaseAddress)
		{
			ldm->InLoadOrderLinks.Blink->Flink = ldm->InLoadOrderLinks.Flink;
			ldm->InLoadOrderLinks.Flink->Blink = ldm->InLoadOrderLinks.Blink;
			ldm->InMemoryOrderLinks.Blink->Flink = ldm->InMemoryOrderLinks.Flink;
			ldm->InMemoryOrderLinks.Flink->Blink = ldm->InMemoryOrderLinks.Blink;
			ldm->InInitializationOrderLinks.Blink->Flink = ldm->InInitializationOrderLinks.Flink;
			ldm->InInitializationOrderLinks.Flink->Blink = ldm->InInitializationOrderLinks.Blink;
			break;
		}
		Cur = Cur->Flink;
	} while (Cur != Head);
}

int main() {
	printf("---------按任意键断链---------\n");
	getchar();
	Hide("kernel32.dll");
	printf("---------断链成功---------\n");
	getchar();
	return 0;
}

编写完代码后编译运行,借助DTDebug来查看进程加载的模块
在这里插入图片描述
启动模块隐藏后,发现kernel32.dll被隐藏了
在这里插入图片描述
断链之后虽然隐藏了kernel32.dll,但仍然可以通过遍历进程vad树的方式发现该模块

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值