吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5661|回复: 18
收起左侧

[学习记录] 【笔记】windows驱动编程学习-从hello world出发

  [复制链接]
jy40 发表于 2020-3-9 10:26
本帖最后由 jy40 于 2020-3-9 10:36 编辑

最近在学习windwos下的驱动编程

开个贴记录一下一些相关的知识点,以及遇到的问题(各种蓝屏的姿势)


配置好VS、WDK以及双机调试环境后,开始学习
首先,从最简单的驱动程序开始,写个Hello World
[C] 纯文本查看 复制代码
#include<ntddk.h>

VOID DriverUnload(PDRIVER_OBJECT pdriver) {
        DbgPrint("Unload Success\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pdriver, PUNICODE_STRING pReg) {
        DbgPrint("Hello World\n");
        pdriver->DriverUnload = DriverUnload;
        return STATUS_SUCCESS;
}

按f7编译生成以后,即可在自己的目录下寻找到 .sys后缀的文件,这就是我们生成的驱动文件了,同样是pe文件的格式

驱动_hello world

驱动_hello world

此时进入我们的虚拟机,我这里用的是win xp sp3环境进行驱动开发学习的,将.sys驱动复制进去,使用驱动装载器将我们的驱动装载
驱动装载器可以去github上下载,搜索关键词"DriverLoader"即可搜索到结果,在后续弄明白驱动装载的原理后,也打算实现一个自己的驱动装载工具
(D3MSUFOEIO)3HV33V(G.png
点击Load即为装载驱动,Unload即为卸载驱动
可以使用DbgView来查看我们的结果,需要在使用的时候按Ctrl+K或者是勾选图中的Capture Kernel选项。
JU~UAK81AU7USJYSX7RYY.png
当然,这时候踩到了第一个坑,驱动装载后,直接蓝屏了!
原来是由于实验环境是win xp环境,而vs2019默认的目标环境是win10,我们需要在设置里修改目标平台属性
9Z_8ZE6PG{2KYK`2DE`V89D.png
经过测试,指定目标平台版本为windows 7也可以在win xp系统中运行
ABX[GBQ13K7{3YC3(UR3GN8.png
再次装载驱动,即可在DbgView中看到打印出的Hello World字符

第一个程序所包含的知识点

DriverEntry:
该函数就相当于C语言中的main函数,相当于驱动模块的入口点,在装载驱动的时候执行其中的代码。该函数有两个参数,一个是驱动对象的指针pDriver,该结构会在后续为大家介绍,还有一个参数是指向UNICODE字符串的指针,储存了驱动注册到的注册表目录,可以使用DbgPrint函数以%zW参数输出
DbgPrint:
相当于写3环c程序中的printf程序
DriverUnload:
驱动卸载时所执行的函数,定义后需要在入口函数中将卸载函数的地址赋值给pdriver->DriverUnload


    点击驱动装载器的Unload,即可在DbgView中看到结果
}4RCT5V1}9UT)]FZFN(QG.png
此时,我们的第一个驱动程序的执行周期算是结束了,从装载的时候执行DriverEntry到卸载的时候执行DriverUnload函数,接下来,就是对pDriver对象进行研究
我们可以使用DbgPrint("%X",pdriver);将指针的值打印出来
_27FM[1E{`5PM]RXI8VVIU4.png
81240DA0就是pDriver对象的地址,在windbg中中断下来,使用dt _DRIVER_OBJECT 81240DA0  指令查看该结构的内容,结果如下
2]G00Z_K1XTC([I5MSNAXLC.png
可以看到驱动名等一些驱动的参数,比如驱动名,比如驱动的卸载函数的地址,我们反编译一下他
7{0SXNTYX_17H_)@M_8JV_3.png
可以很清晰的看到调用了一个DbgPrint函数,而push的则是我们的字符串参数,感兴趣的可以自己尝试跟进一下查看字符串的值是否为"Unload Success“
这里我们对DriverSection进行着重研究

DriverSection是个结构体,指向了 _LDR_DATA_TABLE_ENTRY结构,使用dt _LDR_DATA_TABLE_ENTRY 0x8129d4a8 查看结构内容
2013OB8~`~S{E0@%%O25$A4.png
可以看到在DriverSection结构体的首部是一个链表,查阅资料得知,这是一个指向系统中已经加载驱动的双向链表,我们可以通过遍历这个列表得到系统中已经加载的所有驱动模块,读者可以自己使用dt指令对双向链表的节点进行观察
看到这个,可以进行下拓展,写个驱动模块以遍历出系统中已经安装的驱动名称等信息,或者将自己的驱动节点从该链表中断链以达到隐藏的目的(听说断链技术已经不适用于win 10,会导致蓝屏)
遍历的代码如下
首先需要自己定义一个DriverSection结构体,这个结构体windows未导出
[C] 纯文本查看 复制代码
typedef struct _DRIVER_SECTION {
        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;
                };
        };
        ULONG TimeDateStamp;
        PVOID LoadedImports;
        PVOID EntryPointActivationContext;
        PVOID PatchInformation;
}LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
        pDriver->DriverUnload = DriverUnload;
        PLDR_DATA_TABLE_ENTRY MyDriverList = (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;

        while (1) {
                DbgPrint("%wZ", &MyDriverList->BaseDllName);
                MyDriverList = MyDriverList->InLoadOrderLinks.Flink;
                if (MyDriverList == (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection) {
                        DbgPrint("end\n");
                        break;
                }
        }
        return STATUS_SUCCESS;
}

6S`2BDA2NTHC_FFO`M60F)2.png 遍历的结果如图所示,就不截全了


驱动断链的代码如下

[C] 纯文本查看 复制代码
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
        pDriver->DriverUnload = DriverUnload;
        PLDR_DATA_TABLE_ENTRY MyDriverList = (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
        MyDriverList->InLoadOrderLinks.Blink->Flink = MyDriverList->InLoadOrderLinks.Flink;
        MyDriverList->InLoadOrderLinks.Flink->Blink = MyDriverList->InLoadOrderLinks.Blink;
        return STATUS_SUCCESS;
}

实验时,先将断链的驱动装载至其中,然后再重新装载遍历驱动对象的模块
实验结果如下
06SW5@K[_QG_%]2A8MXJS18.png
可以看到无法寻找到我们的HideMyself.sys模块,隐藏成功
然而这种隐藏并不是非常实用的,首先前面提到过的,无法在win10 x64下使用;其次驱动对象pDriver头4个成员的值是固定的,会被内存搜索的方式暴力定位到驱动对象,只能对抗一些API的检索,为了防止被这种方式搜索到,可以考虑将pDriver的头4个成员置零;最后,系统注册一个驱动的时候,除了向该链表添加节点外,还有对注册表进行写入的操作,所以注册表也会暴露驱动模块的存在,要想实现真正的隐藏必须要注意这一点


萌新第一次发帖,如有不足希望大佬提出意见以补足

免费评分

参与人数 4吾爱币 +7 热心值 +4 收起 理由
kiriiri + 1 + 1 用心讨论,共获提升!
阳光下的少年 + 1 干吧得
女萝岩 + 1 + 1 我很赞同!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

ldw471427015 发表于 2020-3-9 11:21
贼强啊
simon6902 发表于 2020-3-9 20:38
wingking 发表于 2020-3-14 02:48
ewfa 发表于 2020-3-14 09:05
谢谢分享,大佬nb
ciker_li 发表于 2020-3-14 09:32
厉害,厉害
内心xi 发表于 2020-3-17 16:08
小白可以学这东西?
无法撤销 发表于 2020-6-17 13:36
如果用这种方式。后期不优化,那么必须神机才能装载。占用资源过高。
sunxugood 发表于 2020-6-23 12:23

谢谢分享,大佬
阳光下的少年 发表于 2020-7-3 12:11
有点意思, 看上去挺复杂的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-26 00:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表