5.内核空间与内核模块

0x5内核空间与内核模块

1.内核空间

在这里插入图片描述
对于低2G,每个进程是独立的,而高2G是共享的

如果在一个驱动中定义一个变量,然后能够在另一个驱动中进行读取,那就说明高2G确实是所有程序共用的!

#include <ntddk.h>

//卸载函数
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动程序停止运行了.\r\n");
}

ULONG x = 0x12345678;
//入口函数,相当于main

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
	DbgPrint("%X\n",&x);
	//设置一个卸载函数,便于退出

	driver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

dbgview得到x地址
在这里插入图片描述
编写一个驱动读取

#include <ntddk.h>

//卸载函数
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动程序停止运行了.\r\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
	PUINT32 y = (PUINT32)0xF89C5018;
	DbgPrint("%X\n",*y);
	//设置一个卸载函数,便于退出
	driver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

2.内核模块

在这里插入图片描述
<1> 硬件种类繁多,不可能做一个兼容所有硬件的内核,所以,微软提供规定的接口格式,让硬件驱动人员安装规定的格式编写“驱动程序” 。
<2> 这些驱动程序每一个都是一个模块,称为“内核模块”,都可以加载到内核中,都遵守PE结构。但本质上讲,任意一个.sys文件与内核文件没有区别。exe dll sys都是PE结构,唯一区别就是入口不同

3._DRIVER_OBJECT

kd> dt _DRIVER_OBJECT
ntdll!_DRIVER_OBJECT
   +0x000 Type             : Int2B
   +0x002 Size             : Int2B
   +0x004 DeviceObject     : Ptr32 _DEVICE_OBJECT
   +0x008 Flags            : Uint4B
   +0x00c DriverStart      : Ptr32 Void					//基址
   +0x010 DriverSize       : Uint4B
   +0x014 DriverSection    : Ptr32 Void
   +0x018 DriverExtension  : Ptr32 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING			//驱动名	
   +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING
   +0x028 FastIoDispatch   : Ptr32 _FAST_IO_DISPATCH
   +0x02c DriverInit       : Ptr32     long 
   +0x030 DriverStartIo    : Ptr32     void 
   +0x034 DriverUnload     : Ptr32     void 
   +0x038 MajorFunction    : [28] Ptr32     long 

DriverSection指向_LDR_DATA_TABLE_ENTRY结构,是一张链表,跟上一节的PEB断链是一样的结构,唯一的区别就是DriverSection指向ring0驱动的模块(地址都是从0x8xxxxxxx开始的),而_PEB_LDR_DATA指向的是该程序的模块
简单来说DriverSection在高2G,而_PEB_LDR_DATA指向的在低2G

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
	driver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

入口DriverEntry的第一个参数就是_DRIVER_OBJECT结构体指针,第二个参数是注册表路径

4.遍历内核模块

#include <ntddk.h>

typedef struct _LDR_DATA_TABLE_ENTRY
{
   LIST_ENTRY InLoadOrderLinks;
   LIST_ENTRY InMemoryOrderLinks;
   LIST_ENTRY InInitializationOrderLinks;
   PVOID DllBase;
   PVOID EntryPoint;
   UINT32 SizeOfImage;
   UNICODE_STRING FullDllName;
   UNICODE_STRING BaseDllName;
   UINT32 Flags;
   UINT16 LoadCount;
   UINT16 TlsIndex;
   LIST_ENTRY HashLinks;
   PVOID SectionPointer;
   UINT32 CheckSum;
   UINT32 TimeDateStamp;
   PVOID LoadedImports;
   PVOID EntryPointActivationContext;
   PVOID PatchInformation;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;


//卸载函数
VOID DriverUnload(PDRIVER_OBJECT driver)
{
   DbgPrint("驱动程序停止运行了.\r\n");
}

//入口函数,相当于main
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
   DbgPrint("%X \n",driver);
   
   PLIST_ENTRY  Head = (PLIST_ENTRY)driver->DriverSection;
   PLIST_ENTRY  Temp = (PLIST_ENTRY)driver->DriverSection;
   PLDR_DATA_TABLE_ENTRY pDriverSection = (PLDR_DATA_TABLE_ENTRY)Temp;
   do 
   {
   	DbgPrint("模块名称:%ls   基址地址:%X   大小:%X\n",pDriverSection->BaseDllName.Buffer,pDriverSection->DllBase,pDriverSection->SizeOfImage);	
   	Temp = Temp->Flink;
   	pDriverSection = (PLDR_DATA_TABLE_ENTRY)Temp;
   } while (Head != Temp);

   //设置一个卸载函数,便于退出
   driver->DriverUnload = DriverUnload;
   return STATUS_SUCCESS;
}

在这里插入图片描述

5.寻找PspTerminateProcess(未公开函数)

①若A调用B,并且A是已导出函数,则可以在A里找B

②获取函数在模块中的偏移+DllBase即可定位该函数的地址(用windbg很容易)

③特征码搜索

首先必须知道该函数在哪个模块,找到模块开始的地方,利用特征码进行内存遍历

如何寻找特征码?

找比较有特征的,全局变量不行(重定位之后会变),自己经验慢慢总结

nt!PspTerminateProcess:
805c9da4 8bff            mov     edi,edi
805c9da6 55              push    ebp
805c9da7 8bec            mov     ebp,esp
805c9da9 56              push    esi
805c9daa 64a124010000    mov     eax,dword ptr fs:[00000124h]
805c9db0 8b7508          mov     esi,dword ptr [ebp+8]
805c9db3 3b7044          cmp     esi,dword ptr [eax+44h]
805c9db6 7507            jne     nt!PspTerminateProcess+0x1b (805c9dbf)
805c9db8 b80d0000c0      mov     eax,0C000000Dh
805c9dbd eb5a            jmp     nt!PspTerminateProcess+0x75 (805c9e19)
805c9dbf 57              push    edi
805c9dc0 8dbe48020000    lea     edi,[esi+248h]
805c9dc6 f6470120        test    byte ptr [edi+1],20h
805c9dca 7412            je      nt!PspTerminateProcess+0x3a (805c9dde)
805c9dcc 8d8674010000    lea     eax,[esi+174h]
805c9dd2 50              push    eax
805c9dd3 56              push    esi
805c9dd4 68769d5c80      push    offset nt!NtTerminateProcess+0x14c (805c9d76)
805c9dd9 e896eeffff      call    nt!PspCatchCriticalBreak (805c8c74)
805c9dde 6a08            push    8
805c9de0 58              pop     eax
805c9de1 f00907          lock or dword ptr [edi],eax
805c9de4 6a00            push    0
805c9de6 56              push    esi
805c9de7 e88a4f0000      call    nt!PsGetNextProcessThread (805ced76)
805c9dec 8bf8            mov     edi,eax
805c9dee 85ff            test    edi,edi
805c9df0 741e            je      nt!PspTerminateProcess+0x6c (805c9e10)
805c9df2 ff750c          push    dword ptr [ebp+0Ch]
805c9df5 57              push    edi
805c9df6 e807fdffff      call    nt!PspTerminateThreadByPointer (805c9b02)
805c9dfb 57              push    edi
805c9dfc 56              push    esi
805c9dfd e8744f0000      call    nt!PsGetNextProcessThread (805ced76)
805c9e02 8bf8            mov     edi,eax
805c9e04 85ff            test    edi,edi
805c9e06 75ea            jne     nt!PspTerminateProcess+0x4e (805c9df2)
805c9e08 3986bc000000    cmp     dword ptr [esi+0BCh],eax
805c9e0e 7406            je      nt!PspTerminateProcess+0x72 (805c9e16)
805c9e10 56              push    esi
805c9e11 e8baf5feff      call    nt!ObClearProcessHandleTable (805b93d0)
805c9e16 33c0            xor     eax,eax
805c9e18 5f              pop     edi
805c9e19 5e              pop     esi
805c9e1a 5d              pop     ebp
805c9e1b c20800          ret     8

在这里插入图片描述
我从这里开始(函数偏移0xC的位置),隔4个字节提取一个特征码,提取4个

#include <ntifs.h>
#include <ntddk.h>

typedef struct _LDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks;
	LIST_ENTRY InMemoryOrderLinks;
	LIST_ENTRY InInitializationOrderLinks;
	PVOID DllBase;
	PVOID EntryPoint;
	UINT32 SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	UINT32 Flags;
	UINT16 LoadCount;
	UINT16 TlsIndex;
	LIST_ENTRY HashLinks;
	PVOID SectionPointer;
	UINT32 CheckSum;
	UINT32 TimeDateStamp;
	PVOID LoadedImports;
	PVOID EntryPointActivationContext;
	PVOID PatchInformation;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;


NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path);				//入口
VOID GetsysBase(PDRIVER_OBJECT driver, PVOID *pKrnlBase, PUINT32 uKrnlImageSize);	//获取该函数所在模块基址和大小
PVOID MemorySearch(PVOID bytecode,PVOID pBeginAddress, PVOID pEndAddress);			//内存搜索
VOID DriverUnload(PDRIVER_OBJECT driver);											//卸载驱动
typedef NTSTATUS (*_PspTerminateProcess)(PEPROCESS pEprocess, NTSTATUS ExitCode);	//终止进程函数指针

_PspTerminateProcess PspTerminateProcess;

ULONG GetSysBase(PDRIVER_OBJECT driver, PVOID* pKrnlBase, PUINT32 uKrnlImageSize,UNICODE_STRING SysName)
{
	PLDR_DATA_TABLE_ENTRY  Head = (PLDR_DATA_TABLE_ENTRY)driver->DriverSection;
	PLDR_DATA_TABLE_ENTRY  Temp = (PLDR_DATA_TABLE_ENTRY)driver->DriverSection;
	do 
	{
		if (RtlCompareUnicodeString(&Temp->BaseDllName,&SysName, TRUE) == 0)
		{
			*pKrnlBase = Temp->DllBase;
			*uKrnlImageSize = Temp->SizeOfImage;
			return 1;
		}
		Temp = (PLDR_DATA_TABLE_ENTRY)Temp->InLoadOrderLinks.Flink;
	} while (Head != Temp);
	return 0;
}

// 特征码搜索
PVOID MemorySearch(PVOID bytecode,PVOID pBeginAddress,PVOID pEndAddress)
{
	PUINT32 pCur = (PUINT32)pBeginAddress;
	while (pCur != pEndAddress)
	{
		if (RtlCompareMemory(bytecode,pCur,4) == 4 \
			&& RtlCompareMemory((PVOID)((ULONG)bytecode+4),pCur+2,4) == 4 \
			&& RtlCompareMemory((PVOID)((ULONG)bytecode+8),pCur+4,4) == 4 \
			&& RtlCompareMemory((PVOID)((ULONG)bytecode+0xC),pCur+6,4) == 4)
		{
			return pCur;
		}
		pCur = (PUINT32)((ULONG)pCur + 1);		//+1,一个一个搜
	}
	return 0;						//找不到返回0
}


//入口函数,相当于main
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
	UINT32 bytecode[] = {0x3b08758b,0x00000db8,0x0248be8d,0x12742001};	//特征码
	UNICODE_STRING SysName;
	RtlInitUnicodeString(&SysName,L"ntoskrnl.exe");		//函数所在模块名称
	
	PVOID pKrnlBase; // 内核基址
	UINT32 uKrnlImageSize; // 内核大小
	PEPROCESS pEprocess; // 要关闭的进程的EPROCESS

	//获取内核模块基址和大小
	//判断是否成功
	if (!GetSysBase(driver, &pKrnlBase, &uKrnlImageSize,SysName))
	{
		DbgPrint("未找到这个模块,可能被隐藏或不存在");
		driver->DriverUnload = DriverUnload;			//退出
		return STATUS_SUCCESS;			
	}

	DbgPrint("内核地址:%08X,大小: %X\n", pKrnlBase, uKrnlImageSize);

	// 获取PspTerminateProcess函数地址
	PspTerminateProcess = (_PspTerminateProcess)((UINT32)MemorySearch(bytecode,pKrnlBase,(PVOID)((UINT32)pKrnlBase+uKrnlImageSize)) -0xC);
	//确认是否匹配到
	if (!(ULONG)PspTerminateProcess)
	{
		DbgPrint("未在%ls匹配到函数",SysName.Buffer);
		driver->DriverUnload = DriverUnload;		//退出
		return STATUS_SUCCESS;
	}

	DbgPrint("PspTerminateProcess:%X\n",PspTerminateProcess);
	//根据PID获取EPROCESS
	PsLookupProcessByProcessId((HANDLE)1316,&pEprocess); // 记事本PID
	// 调用 PspTerminateProcess 关闭进程
	PspTerminateProcess(pEprocess, 0);
	DbgPrint("记事本进程被PspTerminateProcess函数关闭了\n");
	
	driver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}


//卸载函数
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动程序停止运行了.\r\n");
}

运行前:
在这里插入图片描述
运行后:
在这里插入图片描述

问题:
在这里插入图片描述
如果遇到图上问题,将#include <ntifs.h>放到#include <ntddk.h>上面即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值