01 驱动编写基础案列

WinDbg为什么可以轻松分析结构体?本质原因就是它有符号文件并且能够解析它,也就是PDB文件 上一篇中为什么需要把项目目录加到symbol下的原因

应用层编程使用 <windows.h> 提供的各种API函数 MSDN文档
内核编程使用<ntddk.h>提供的各种API函数 (已安装了WDK) WDK文档

未导出函数

WDK说明文档中只包含了内核模块导出的函数,对于未导出的函数,则不能直接使用

如果要使用未导出的函数,自己定义一个函数指针,并且为函数指针提供正确的函数地址就可以使用了。2种办法可以获取导出的函数地址

1.特征码搜索 (硬编码)
2.解析内核PDB文件

驱动基本类型

unsigned long length 不建议这样写

使用WDK自己的类型

ULONG(unsigned long)	PULONG(unsigned long*)
UINT(unsigned int)		PUINT(unsigned int*)
UCHAR(unsigned char)	PUCHAR(unsigned char*)
UVOID(void)				PUVOID(void*)


typedef signed char         INT8, *PINT8;
typedef signed short        INT16, *PINT16;
typedef signed int          INT32, *PINT32;
typedef signed __int64      INT64, *PINT64;
typedef unsigned char       UINT8, *PUINT8;
typedef unsigned short      UINT16, *PUINT16;
typedef unsigned int        UINT32, *PUINT32;
typedef unsigned __int64    UINT64, *PUINT64;

返回值

大部分内核函数的返回值都是NTSTATUS类型

//函数举例
NTSTATUS PsCreateSystemThread()
NTSTATUS ZwOpenProcess()
NTSTATUS ZwOpenEvent()
//返回值结果
STATUS_SUCCESS			 	0x00000000 成功
STATUS_INVALID_PARAMETER 	0xC000000D 参数无效
STATUS_BUFFER_OVERFLOW 		0x80000005 缓冲区长度不够
其它返回说明 : 参考 ntstatus.h

异常处理

__try {
//可能出错的代码
} __except(filter_value) {
//出错的时候要执行的代码
}

filter_value:
EXCEPTION_EXECUTE_HANDLER(1),代码进入except块
EXCEPTION_CONTINUE_SEARCH(0),不处理异常,由上一层调用函数处理
EXCEPTION_CONTINUE_EXECUTION(-1),回去继续执行错误处的代码

内核内存函数

C语言		内核
malloc		ExAllocatePool //非分页内存是常驻内存的,分页内存会被放到文件上
memset		RtFillMemory
memcpy		RtlMoveMemory
free		ExFreePool

内核字符串种类

CHAR(char)/WCHAR(wchar_t)/ANSI_STRING/UNICODE_STRING

ANSI_STRING :
typedef struct _STRING 
{
	USHORT Length;
	USHORT MaximumLength;
	PCHAR Buffer;
} STRING;

UNICODE_STRING :
typedef struct _UNICODE_STRING
{
	USHORT Length;
	USHORT MaximumLength;
	PCHAR Buffer;
} UNICODE_STRING;

内核字符串操作

创建、复制、比较、转换

ANSI_STRING 字符串		UNICODE_STRING 字符串
RtllnitAnsiString		RtllnitUnicodeString
RtlCopyString			RtlCopyUnicodeString
RtlCompareString		RtlCompareUnicodeString
RtlAnsiStringToUnicodeString RtlUnicodeStringToAnsiString

驱动代码详解

#include <ntddk.h>

NTSTATUS UnloadDriver(PDRIVER_OBJECT DriverObject)
{
    DbgPrint("Chapter Driver By WingSummer,Unloaded Successfully!");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    DbgPrint("Chapter Driver By WingSummer,Loaded Successfully!");
    DriverObject->DriverUnload = UnloadDriver;

    return STATUS_SUCCESS;
}

DriverEntry
DriverEntry是驱动程序的入口,如果驱动加载成功后,就像Dll加载成功调用DllMain函数一样,调用该函数。

PDRIVER_OBJECT
PDRIVER_OBJECT是驱动对象的指针

typedef struct _DRIVER_OBJECT {
    CSHORT Type;
    CSHORT Size;

    PDEVICE_OBJECT DeviceObject;
    ULONG Flags;

    PVOID DriverStart;
    ULONG DriverSize;
    PVOID DriverSection;
    PDRIVER_EXTENSION DriverExtension;

    UNICODE_STRING DriverName;
    PUNICODE_STRING HardwareDatabase;
    PFAST_IO_DISPATCH FastIoDispatch;

    PDRIVER_INITIALIZE DriverInit;
    PDRIVER_STARTIO DriverStartIo;
    PDRIVER_UNLOAD DriverUnload;
    PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];

} DRIVER_OBJECT;

我们看看这个结构 :

kd> dt _DRIVER_OBJECT 89B7FA20
ntdll!_DRIVER_OBJECT
   +0x000 Type             : 0n4
   +0x002 Size             : 0n168
   +0x004 DeviceObject     : (null)
   +0x008 Flags            : 0x12
   +0x00c DriverStart      : 0xbab50000 Void
   +0x010 DriverSize       : 0x6000
   +0x014 DriverSection    : 0x89936678 Void
   +0x018 DriverExtension  : 0x89b7fac8 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING "\Driver\HelloDriver"
   +0x024 HardwareDatabase : 0x80671ae0 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
   +0x028 FastIoDispatch   : (null)
   +0x02c DriverInit       : 0xbab54000     long  HelloDriver!GsDriverEntry+0
   +0x030 DriverStartIo    : (null)
   +0x034 DriverUnload     : 0xbab51040     void  HelloDriver!UnloadDriver+0
   +0x038 MajorFunction    : [28] 0x804f454a     long  nt!IopInvalidDeviceRequest+0

DriverStart :驱动对象加载后的起始地址

DriverSize : 驱动对象加载后的内存大小

DriverName : 驱动对象的名字

DriverUnload : 驱动对象的卸载地址

DriverSection : 存储目前所有已加载的驱动程序信息相关的LDR_DATA_TABLE_ENTRY结构体的双向循环链表。通过这个东西来实现把它们全部串起来,通过这个我们也可以进行遍历

kd> dt _LDR_DATA_TABLE_ENTRY 0x89936678
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x80554fc0 - 0x89b80d58 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0xffffffff - 0xffffffff ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x630069 - 0x0 ]
   +0x018 DllBase          : 0xbab50000 Void
   +0x01c EntryPoint       : 0xbab54000 Void
   +0x020 SizeOfImage      : 0x6000
   +0x024 FullDllName      : _UNICODE_STRING "\??\C:\Documents and Settings\wingsummer\桌面\HelloDriver.sys"
   +0x02c BaseDllName      : _UNICODE_STRING "HelloDriver.sys"
   +0x034 Flags            : 0x9104000
   +0x038 LoadCount        : 1
   +0x03a TlsIndex         : 0x49
   +0x03c HashLinks        : _LIST_ENTRY [ 0xffffffff - 0x1055c ]
   +0x03c SectionPointer   : 0xffffffff Void
   +0x040 CheckSum         : 0x1055c
   +0x044 TimeDateStamp    : 0xfffffffe
   +0x044 LoadedImports    : 0xfffffffe Void
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : 0x00650048 Void

我们可以看下一个成员

kd> dt _LDR_DATA_TABLE_ENTRY 0x89b80d58
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x89936678 - 0x89b45e98 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0xb8183850 - 0x1 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0xe - 0x0 ]
   +0x018 DllBase          : 0xb817e000 Void
   +0x01c EntryPoint       : 0xb81a6105 Void
   +0x020 SizeOfImage      : 0x2b000
   +0x024 FullDllName      : _UNICODE_STRING "\SystemRoot\system32\drivers\kmixer.sys"
   +0x02c BaseDllName      : _UNICODE_STRING "kmixer.sys"
   +0x034 Flags            : 0x9104000
   +0x038 LoadCount        : 1
   +0x03a TlsIndex         : 0x74
   +0x03c HashLinks        : _LIST_ENTRY [ 0xffffffff - 0x2f580 ]
   +0x03c SectionPointer   : 0xffffffff Void
   +0x040 CheckSum         : 0x2f580
   +0x044 TimeDateStamp    : 0xe1786190
   +0x044 LoadedImports    : 0xe1786190 Void
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : 0x006d006b Void

IRQL

IRQL全称Interrupt Request Level,即中断执行的优先级。它是Windows自己定义的一套优先级方案,与CPU无关,数值越大权限越高。中断包括了硬中断和软中断,硬中断是由硬件产生,而软中断则是完全虚拟出来的。

CPU任何时刻必须处于某一个等级
在同一处理器上,等级高的程序可以打断等级低的程序

在这里插入图片描述
HOOK的时候使用的程序等级是 2
缺页异常的 分页处理程序 等级是 2
所以HOOK必须使用非分页内存 分页内存可能遇到缺页异常的情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值