dbgView在 win10 32位和win7 64上无法显示驱动中DbgPrint输出的日志

dbgView在 win10 32位和win7 64上无法显示驱动中DbgPrint输出的日志,第1张

各种调试工具都可以看,例如WinDbg、SoftICE。

SoftICE可以本地调试,但现在开发商已经不再更新了,没法调试新的系统环境;WinDbg不能本地调试,现在流行用虚拟机来双机调试;dbgview我不了解。

用管理员启动driver Monitor ,如果不行看一下vs编译的时候driver setting->general ->target os version 是不是windows7,stampinfo和inf2cat禁用没禁用

网上说的比较常见的4种方法:

1、通过DriverEntry传入的DriverObject参数的DriverSection成员指向LDR_DATA_TABLE_ENTRY结构,通过遍历这张表得到ntoskrnl的基址和大小

2、ZwQuerySystemInformation大法

3、搜索内存

4、利用KPCR结构

存在的问题:

1、第1种方法和第4种方法得到的结果比ZwQuerySystemInformation少一个

2、第1种方法如果输出BaseDllName是ntoskrnl.exe,如果输出FullDllName则是:\WINDOWS\system32\ntkrnlpa.exe,地址都是:804d8000,不明白为何

环境:虚拟机VMWare:WIN XP SP3 + WDK ---- WINXP Check方式编译

#include <ntddk.h>

//---------------------------------//

//下面的结构包含了一些重要信息。如:PsLoadedModuleList ,它是Windows加载的所有内核模块构成的链表的表头。

//PsLoadedModuleList就是如下这个结构体中InLoadOrderLinks。即为LDR_DATA_TABLE_ENTRY结构的第一项。

#pragma pack(push)//结构定义

#pragma pack(1)

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

ULONG Flags

USHORT LoadCount

USHORT TlsIndex

union

{

LIST_ENTRY HashLinks

struct

{

PVOID SectionPointer

ULONG CheckSum

}

}

union

{

ULONG TimeDateStamp

PVOID LoadedImports

}

PVOID EntryPointActivationContext

PVOID PatchInformation

} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY

#pragma pack(pop)

//---------------------------------------------------------------------------------------------------//函数声明

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)

NTSTATUS DriverUnload()

//Method3用到,指定当前线程运行在那个处理器

NTKERNELAPI VOID KeSetSystemAffinityThread ( KAFFINITY Affinity )

NTKERNELAPI VOID KeRevertToUserAffinityThread ( VOID )

NTKERNELAPI NTSTATUS ZwQuerySystemInformation(

IN ULONG SystemInformationClass,

IN OUT PVOID SystemInformation,

IN ULONG SystemInformationLength,

IN PULONG ReturnLength OPTIONAL

)

#pragma alloc_text(INIT, DriverEntry)

#pragma alloc_text(PAGE, DriverUnload)

//---------------------------------------------------------------------------------------------------//变量、常量、结构定义

UNICODE_STRING BaseName

#define SystemModuleInformation 11 //Method2要用到11功能号

typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY

{

ULONG Unknow1

ULONG Unknow2

#ifdef _WIN64

ULONG Unknow3

ULONG Unknow4:

#endif

PVOID Base

ULONG Size

ULONG Flags

USHORT Index

USHORT NameLength

USHORT LoadCount

USHORT ModuleNameOffset

char ImageName[256]

}SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY

typedef struct _SYSTEM_MODULE_INFORMATION

{

ULONG Count//内核中以加载的模块的个数

SYSTEM_MODULE_INFORMATION_ENTRY Module[1]

}SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION

//---------------------------------------------------------------------------------------------------//

/*

用到了DriverObject域的InLoadOrderLinks链表

注意:

下面的代码会用到一个宏:

---------------------------------------------------------------------------------------------------------------------

CONTAINING_RECORD 这样的一个宏,它的定义如下:

#define CONTAINING_RECORD(address, type, field) ((type *)( (PCHAR)(address) - (ULONG_PTR)(&((type*)0)->field)))

根据网上资料:就是address -(field在type中的偏移)

----------------------------------------------------------------------------------------------------------------------

*/

VOID Method1(IN PDRIVER_OBJECT DriverObject)//遍历链表

{

ULONG Base=0//模块基地址

LDR_DATA_TABLE_ENTRY* SectionBase=NULL

LIST_ENTRY* Entry=NULL

LIST_ENTRY InLoadOrderLinks

ULONG num=0

Entry=((LIST_ENTRY*)DriverObject->DriverSection)->Flink

do

{

SectionBase=CONTAINING_RECORD(Entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks)//得到这个Entry所属的Section的地址,此方法经过验证可行

if (SectionBase->EntryPoint &&

SectionBase->BaseDllName.Buffer &&

SectionBase->FullDllName.Buffer &&

SectionBase->LoadCount

)

{

DbgPrint("方法一遍历模块名称:%wZ,地址:%x\n",&(SectionBase->FullDllName),SectionBase->DllBase)

//DbgPrint("方法一遍历模块名称:%wZ,地址:%8X\n",&(SectionBase->BaseDllName),SectionBase->DllBase)

num++

/*if(!RtlCompareUnicodeString(&(SectionBase->BaseDllName),&BaseName,FALSE))

{

DbgPrint("方法一模块名称:%wZ,地址:%x\n",&(SectionBase->BaseDllName),SectionBase->DllBase)

}*/

}

Entry=Entry->Flink

}while(Entry!=((LIST_ENTRY*)DriverObject->DriverSection)->Flink)//直到遍历回来

DbgPrint("方法一得到模块总数:%d\n",num)

}

void Method2()//ZwQuerySystemInformation大法

{

PVOID pBuffer=0//缓冲区

NTSTATUS Result//查询结果

ULONG NeedSize

PSYSTEM_MODULE_INFORMATION pSystemModuleInformation//将结果强制转换为该类型

ULONG BufferSize = 0x5000//初始分配内存大小,没有采用查询再分配的循环方法

ULONG ModuleCount//模块总数

ULONG i

do

{

pBuffer=ExAllocatePool(NonPagedPool,BufferSize)

if(pBuffer==NULL)

{

DbgPrint("分配内存失败!\n")

return FALSE

}

Result=ZwQuerySystemInformation(SystemModuleInformation,pBuffer,BufferSize,&NeedSize)

if(Result==STATUS_INFO_LENGTH_MISMATCH )//分配不够

{

ExFreePool(pBuffer)

//大小乘以2,重新分配

BufferSize*=2

}

else if(!NT_SUCCESS(Result))//失败,放弃吧

{

DbgPrint( "查询失败,错误码:%8X\n", Result )

ExFreePool(pBuffer)

return FALSE

}

}while( Result == STATUS_INFO_LENGTH_MISMATCH )

pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)pBuffer//类型转换

ModuleCount=pSystemModuleInformation->Count//模块总数

for(i=0i<ModuleCounti++)

{

DbgPrint( "方法二遍历模块名称:%s,地址:%8X\n", pSystemModuleInformation->Module[i].ImageName, pSystemModuleInformation->Module[i].Base )

}

DbgPrint("方法二得到模块总数:%d\n",ModuleCount)

ExFreePool(pBuffer)

return TRUE

}

VOID Method3(ULONG Base)//搜索内存,从0x80000000-----0xa0000000

{

}

//内核中FS寄存器指向KPCR结构,每个处理器都有一个,使用第一个处理器即可其中比较重要的是KdVersionBlock这个指针, 它指向一个DBGKD_GET_VERSION64这个结构.

//这个结构体里面包含了一些重要信息。如:PsLoadedModuleList ,它是Windows加载的所有内核模块构成的链表的表头

//两个处理器对应的KPCR结构是有区别的, 只有第一个处理器的KPCR域KdVersionBlock才指向DBGKD_GET_VERSION64这个结构.

//-------------------------------------仔细观察定义会发现,这个跟使用DriverObject方法达到的链表示一样的!

void Method4()

{

ULONG Addr//内核地址

LIST_ENTRY* Entry=NULL

LIST_ENTRY InLoadOrderLinks

LDR_DATA_TABLE_ENTRY* SectionBase=NULL//LdrData->DllBase,LdrData->FullDllNme

ULONG num=0

//-----------------------------------------------------------------------------//在莫灰灰基础上修改一小部分

KeSetSystemAffinityThread(1)//使当前线程运行在第一个处理器上

_asm

{

push eax

mov eax,FS:[0x34] 指向KdVersionBlock的指针

add eax,18h 得到指向PsLoadedModuleList的地址,即该指针的地址,指针里存有PsLoadedModuleList的地址

mov eax,[eax] 得到PsLoadedModuleList的地址

mov eax,[eax] 得到PsLoadedModuleList的内容

//mov eax,[eax+18h] 取出DllBase, 即ntoskrnl.exe的基地址

mov Addr,eax

pop eax

}

KeRevertToUserAffinityThread()//恢复线程运行的处理器

//----------------------------------------------------------------------// 以下跟方法一重复

Entry=(LIST_ENTRY*)Addr

do

{

SectionBase=CONTAINING_RECORD(Entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks)//得到这个Entry所属的Section的地址,此方法经过验证可行

if (SectionBase->EntryPoint &&

SectionBase->BaseDllName.Buffer &&

SectionBase->FullDllName.Buffer &&

SectionBase->LoadCount

)

{

DbgPrint("方法四遍历模块名称:%wZ,地址:%8X\n",&(SectionBase->FullDllName),SectionBase->DllBase)

num++

}

Entry=Entry->Flink

}while(Entry!=(LIST_ENTRY*)Addr)//直到遍历回来

DbgPrint("方法四得到模块总数:%d\n",num)

}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)

{

ULONG EntryAddr

_asm

{

push ecx

lea ecx,[ebp][4]//得到DriverEntry返回地址

mov EntryAddr,ecx

pop ecx

}

EntryAddr=*(ULONG*)EntryAddr

DbgPrint("驱动返回地址:%8X\n",EntryAddr)

RtlInitUnicodeString(&BaseName,L"ntoskrnl.exe")

DbgPrint("驱动加载成功!\n")

//-------------------------------//

Method1(pDriverObject)

//-------------------------------//

Method2()

//-------------------------------//

Method3()

//-------------------------------//

Method4()

//-------------------------------//

pDriverObject->DriverUnload=DriverUnload

return STATUS_SUCCESS

}

NTSTATUS DriverUnload()

{

DbgPrint("驱动卸载成功\n")


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/tougao/9913075.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-03
下一篇 2023-05-03

发表评论

登录后才能评论

评论列表(0条)

保存