WIN64内核编程基础班(作者:胡文亮) https://www.dbgpro.com/x64driver
我们先从一份“简历”说起:
姓名:X86或80x86
性别:?
出生年月:1978
出生地点:美国
所属公司:主要是INTEL和AMD
主要历史(摘自维基百科):x86架构于1978年推出的Intel 8086中央处理器中首度出
现,它是从Intel 8008处理器中发展而来的,而8008则是发展自Intel 4004的。8086
在三年后为IBM PC所选用,之后x86便成为了个人电脑的标准平台,成为了历来最成功
的CPU架构。其他公司也有制造x86架构的处理器,计有Cyrix(现为威盛电子所收购)、
恩益禧集团、IBM、IDT以及Transmeta。Intel以外最成功的制造商为AMD,其早先产品
Athlon系列处理器的市场份额仅次于Intel Pentium。8086是16位处理器;直到1985
年32位的80386的开发,这个架构都维持是16位。接着一系列的处理器表示了32位架
构的细微改进,推出了数种的扩充,直到2003年AMD对于这个架构发展了64位的扩充,
并命名为AMD64。后来英特尔也推出了与之兼容的处理器,并命名为Intel 64。两者一般
被统称为x86-64或x64,开创了x86的64位时代。
在X86的“简历”里,我们摘出一段重要的话:2003年AMD对于这个架构发展了64位
的扩充,并命名为AMD64。后来英特尔也推出了与之兼容的处理器,并命名为Intel 64。两
者一般被统称为x86-64或x64,开创了x86的64位时代。也就是说,如果要学习WIN64内
核编程,就必须拥有2003年以后的CPU!不像学习WIN32内核编程一样,随便一台运行XP
的奔腾3笔记本也行!但实际情况是,基本上只有2005年以后的CPU才支持X64指令集;
到2008年之后,CPU才普遍含有X64指令集;到2010年之后,CPU才普遍含有X64指令集
和支持VT-X技术(没有VT-X技术就无法运行WIN64虚拟机)。
鉴于中国的实际情况,应该很多人手里还有酷睿2的笔记本。一般来说,T5XXX以下的
CPU是没有X64指令集的;T7XXX以下的CPU是不支持VT-X的。只有T7XXX以上的CPU,才
有X64指令集和支持VT-X。而2010年之后的Core i系列的CPU,都有X64指令集和支持
VT-X了。台式机方面也差不多,CORE 2似乎只有比较高端的E8000或者Q8000以上才有X64
指令集和支持VT-X技术。AMD则比较厚道,Athlon X2 245之类的低端CPU都有X64指令
集和支持AMD-V技术(等于是AMD的VT-X技术)。
总结来说,如果你用的CPU是CORE I系列的,就可以了,如果不是的话,可以用CPUZ检测一下,看看是否支持X64和VT-X。如果发现不支持VT-X的话,看看是不是BIOS里没
有打开,一般主板的默认设置里,VT-X都是关闭的。
说完CPU,说说内存。内存经历过两次大跌大涨,现在(2013年11月)又在价格的顶
峰,真是让人心碎。不过再让人心碎的价格,为了学习技术,大家也只能忍受了。一句话,
学习WIN64内核编程至少需要8GB的内存,如果要多开虚拟机,推荐16GB。否则在双机调
试时卡死(鼠标移动变成了“飘动”的),会让人非常愤怒。
配置好驱动测试环境后,就可以正式编写驱动了。市面上讲解驱动开发的书籍汗牛充栋,
但讲得较为太复杂,让初学者不好理解。本文从一个简单的hello,world驱动(驱动模板)
讲起,力求讲解得简单明了,让大家好理解。
本文主角:
1.DbgView。DbgView是查看程序调试输出的工具,由美国高富帅Mark Russinovich编写
(不得不说,此人长得帅,编程技术又牛,让多少男人羡慕妒忌,让多少女人一见倾心)。
下载地址:http://technet.microsoft.com/en-us/sysinternals/bb.aspx
2.KmdMgr。KmdMgr是一个由俄国人编写的驱动加载工具。比起国内那些乱七八糟的驱动加
载工具,它的特点是可以与驱动进行通信(虽然无法设置I/O缓冲区)。下载地址:
https://www.assembla.com/code/L2h/subversion/nodes/LowLevel/KmdManager.exe?_for
mat=raw&rev=1
3.WIN64AST。作者自行开发的64位ARK类工具。在本章中用来查看驱动是否加载成功。在
后续章节还有其他的用途。下载地址:www.win64ast.com。
4.WIN64UDL。作者自行开发的驱动加载工具,能在正常模式下加载没有签名的驱动。因为这
个工具,被人举报滥用签名,最终导致价值15000人民币的数字签名被吊销。下载地址:
http://www.m5home.com/bbs/thread-7845-1-1.html
编写驱动:
以下是一个我写的WIN64驱动模板(代码中已经加了详细的注释,完整工程文件可以在
论坛上下载):
//【0】包含的头文件,可以加入系统或自己定义的头文件 #include<ntddk.h> #include<windef.h> #include<stdlib.h> //【1】定义符号链接,一般来说修改为驱动的名字即可 #define DEVICE_NAME L"\\Device\\KrnlHW64" #define LINK_NAME L"\\DosDevices\\KrnlHW64" #define LINK_GLOBAL_NAME L"\\DosDevices\\Global\\KrnlHW64" //【2】定义驱动功能号和名字,提供接口给应用程序调用 #define IOCTL_IO_TEST CTL_CODE(FILE_DEVICE_UNKNOWN,0x800, METHOD_BUFFERED,FILE_ANY_ACCESS) #define IOCTL_SAY_HELLO CTL_CODE(FILE_DEVICE_UNKNOWN,0x801, METHOD_BUFFERED,FILE_ANY_ACCESS) //【3】驱动卸载的处理例程 VOID DriverUnload(PDRIVER_OBJECT pDriverObj) { UNICODE_STRING strLink; DbgPrint("[KrnlHW64]DriverUnload\n"); RtlInitUnicodeString(&strLink,LINK_NAME); IoDeleteSymbolicLink(&strLink); WIN64内核编程基础班(作者:胡文亮;:) IoDeleteDevice(pDriverObj->DeviceObject); } //【4】IRP_MJ_CREATE对应的处理例程,一般不用管它 NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj,PIRP pIrp) { DbgPrint("[KrnlHW64]DispatchCreate\n"); pIrp->IoStatus.Status=STATUS_SUCCESS; pIrp->IoStatus.Information=0; IoCompleteRequest(pIrp,IO_NO_INCREMENT); return STATUS_SUCCESS; } //【5】IRP_MJ_CLOSE对应的处理例程,一般不用管它 NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj,PIRP pIrp) { DbgPrint("[KrnlHW64]DispatchClose\n"); pIrp->IoStatus.Status=STATUS_SUCCESS; pIrp->IoStatus.Information=0; IoCompleteRequest(pIrp,IO_NO_INCREMENT); return STATUS_SUCCESS; } //【6】IRP_MJ_DEVICE_CONTROL对应的处理例程,驱动最重要的函数之一,一般走正常途径调 用驱动功能的程序,都会经过这个函数 NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj,PIRP pIrp) { NTSTATUS status=STATUS_INVALID_DEVICE_REQUEST; PIO_STACK_LOCATION pIrpStack; ULONG uIoControlCode; PVOID pIoBuffer; ULONG uInSize; ULONG uOutSize; DbgPrint("[KrnlHW64]DispatchIoctl\n"); pIrpStack=IoGetCurrentIrpStackLocation(pIrp); //控制码 uIoControlCode=pIrpStack->Parameters.DeviceIoControl.IoControlCode; //输入输出缓冲区 pIoBuffer=pIrp->AssociatedIrp.SystemBuffer; //输入区域大小 uInSize=pIrpStack->Parameters.DeviceIoControl.InputBufferLength; //输出区域大小 uOutSize=pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch(uIoControlCode) WIN64内核编程基础班(作者:胡文亮;:) { //在这里加入接口 case IOCTL_IO_TEST: { DWORD dw=0; //获得输入的内容 memcpy(&dw,pIoBuffer,sizeof(DWORD)); //使用输入的内容 dw++; //输出处理的结果 memcpy(pIoBuffer,&dw,sizeof(DWORD)); //处理成功,返回非STATUS_SUCCESS会让DeviveIoControl返回失败 status=STATUS_SUCCESS; break; } case IOCTL_SAY_HELLO: { DbgPrint("[KrnlHW64]IOCTL_SAY_HELLO\n"); status=STATUS_SUCCESS; break; } } if(status==STATUS_SUCCESS) pIrp->IoStatus.Information=uOutSize; else pIrp->IoStatus.Information=0; pIrp->IoStatus.Status=status; IoCompleteRequest(pIrp,IO_NO_INCREMENT); return status; } //【7】驱动加载的处理例程,里面进行了驱动的初始化工作 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegistryString) { NTSTATUS status=STATUS_SUCCESS; UNICODE_STRING ustrLinkName; UNICODE_STRING ustrDevName; PDEVICE_OBJECT pDevObj; //初始化驱动例程 pDriverObj->MajorFunction[IRP_MJ_CREATE]=DispatchCreate; pDriverObj->MajorFunction[IRP_MJ_CLOSE]=DispatchClose; pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]=DispatchIoctl; pDriverObj->DriverUnload=DriverUnload; WIN64内核编程基础班(作者:胡文亮;:) //创建驱动设备 RtlInitUnicodeString(&ustrDevName,DEVICE_NAME); status=IoCreateDevice(pDriverObj,0,&ustrDevName,FILE_DEVICE_UNKNOWN, 0,FALSE,&pDevObj); if(!NT_SUCCESS(status))return status; if(IoIsWdmVersionAvailable(1,0x10)) RtlInitUnicodeString(&ustrLinkName,LINK_GLOBAL_NAME); else RtlInitUnicodeString(&ustrLinkName,LINK_NAME); //创建符号链接 status=IoCreateSymbolicLink(&ustrLinkName,&ustrDevName); if(!NT_SUCCESS(status)) { IoDeleteDevice(pDevObj); return status; } //走到这里驱动实际上已经初始化完成,下面添加的是功能初始化的代码 DbgPrint("[KrnlHW64]DriverEntry\n"); return STATUS_SUCCESS; }
讯享网

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/54614.html