在之前的文章中我们提到了使用:
或者等效语句:
来获取硬盘的序列号和UID,但是文章并没有解析上述语句是如何进入内核查询到序列号和UID的,让同班同学很不开心,这篇文章进行补充说明,让友友们能够清晰的了解面对这些类似的查询语句,我们该如何分析出他是通过哪一个驱动,通过哪些结构进行解析的。
老样子在虚拟机中打开powershell,查询我们的硬盘序列号与UID:

复制硬盘序列号到CE中搜索wchar_t*类型(不理解的请看之前的相关文章):

为了确认查询语句访问的究竟是哪一个内存地址,我们可以逐个修改,然后不断重试查询语句,看修改哪一个地址后,查询的结果也随之改变,那么就是查询语句访问的内存地址。这了为了各位操作方便提前透露该内存地址是MiVaNonPagedPool区间内的内存,如何获取该区间论坛有对应的文章讲解,如果无法实现的读者较多,我后续上传。

这里我们在CE中定位到了这个地址,修改首位字符为5后,查询语句也跟随变动,说明这个内核内存地址就是我们查询语句访问的内存地址。
接下来我们在Windbg中对这个内核内存地址下一字节的硬件访问断点:
ba表示硬件断点,r读取(w写入,e执行),1表示一字节,u @Rip L5表示显示当前RIP的5行代码,g表示继续执行(不理解的可以百度搜索学习windbg硬件断点)。
需要注意的就是下断前记得关闭CE,或者不要再让CE读取我们要下访问断的内存地址,否则会一直输出CE驱动读取该地址的代码:

这种情况我们断下后,bl打开断点列表,找到对应断点,点击Clear清除指定断点即可。
随后关闭CE,重新下硬件访问断点,重新执行查询语句,我这里就不选择继续执行了,把g去掉就行:
我们回到powershell再次执行查询语句:

可以看到断在了spaceport.sys驱动(虚拟机WIN11 24H2)中的函数RtlStringCbCopyW内部,这个函数就是将字符串拷贝将参数3拷贝给参数1,我们可以直接kv查看堆栈信息,也可以下硬件访问断点时直接打印堆栈信息,把:u @Rip换成k即可。
这里我们就获取到了查询语句的调用流,是如何从应用层进入内核访问内核地址获取序列号的:

我们将虚拟机内的spaceport.sys拖入IDA中分析,定位到spaceport!SpIoctlGetDriveInfo+0xa3b的位置,RtlStringCbCopyW函数内部就没什么必要看了,因为就是个字符串拷贝函数: 
我们重点关心这里的v13的来源,这里+10其实就是+80也就是+0x50,比较基础就不废话了。你可以对你认为疑似v13来源的位置直接bp下断,看是否执行到对应的位置,这里就直接说结果了,v13来源于SpFindDriveByTempId这个函数的返回值:

你现在可能有这一种思路,找到参数v123[20]的来源,调用函数SpFindDriveByTempId,获取返回值。不过,我们还是先进入函数SpFindDriveByTempId中查看:

从伪代码中查看,貌似确实用到了这个参数,并且还用了一个全局变量解析结构,但是我们一定要切记的就是,Windbg对于查看全局变量是优于IDA的。
这是IDA的符号解析得到的全局变量,还需要结构体解析:

这是Windbg的符号解析:

我们拿到了这个全局变量,根据代码走一遍:

Rdx = 0xffffd402`ed2ac1f8,然后add rdx,0xF0,
Rdx = FFFFD402ED2AC2E8,然后mov r9,[rdx],

R9 = 0x ffffd402`ed71d868,
最后lea rax, [r9-248h]
Rax = 0x FFFFD402ED71D620

我们就拿到了v13,最后别忘了加上我们最初的偏移0x50:

最后就获取到了这条查询指令访问的内核内存地址,其余查询语句均是相同的思路,不管是什么硬件都可以用相同的方式进行分析,不过有些硬件的序列号需要重启WMI服务才会更新,注意这个问题就行,希望本文能做到抛砖引玉的效果。视频分析之后再录制。所以在遇到全局变量时,涉及复杂的结构解析,需要很多结构偏移时不妨用Windbg查看。补充:因为我的虚拟机中就只有一个硬盘,物理机存在多硬盘的情况,就会导致SpFindDriveByTempId函数要循环,感兴趣的可以看看。
Get-PhysicalDisk | Select-Object FriendlyName, SerialNumber, UniqueId
Get-PhysicalDisk | Select-Object FriendlyName, SerialNumber, UniqueId
Get-CimInstance -ClassName MSFT_PhysicalDisk -Namespace root/Microsoft/Windows/Storage | Select-Object FriendlyName, SerialNumber, UniqueId
Get-CimInstance -ClassName MSFT_PhysicalDisk -Namespace root/Microsoft/Windows/Storage | Select-Object FriendlyName, SerialNumber, UniqueId
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!