在之前的文章中通过Powershell使用CIM指令查询了硬盘的相关信息:
用CE搜索char*类型的序列号时,有一个地址是在ClipSp.sys中的:
我们就来简单解析一下想要知道他的来源该如何操作,首先我们记录下它距离模块基址的偏移=0x9F024,重启虚拟机,第一次断点断下时重新加载符号(否则只有nt一个模块有符号),可以看到此时还未将硬盘序列号写入这个地址,我们对地址头部下1字节硬件写入断点: 之后直接运行虚拟机,当我们进入登陆页面输入密码后才会触发断点: 我们当前断下的位置你也可以到IDA分析,或者查看调用堆栈进行分析,因为属于能用IDA正常分析的普通情况我们这里就暂时略过。我们继续执行。我们记录下第二次断下的位置后,到IDA中查看: 可以看到IDA中的字节与windbg断下的位置的字节并不相符,这种情况在nt模块的初始化函数中也能看到。对于这种情况我们用windbg分析即可。我们先查看全部寄存器的值,然后查看rcx寄存器的值,发现rcx存储了我们的硬盘序列号,那么我们追rcx的来源即可。然后-0x100字节查看汇编代码: 那么我们用windbg查看调用的这两个函数分别是什么: 所以这里的执行流程就是调用ExAllocatePool2申请内存,再调用ZwDeviceIoControlFile,用我们申请的内存当作OutputBuffer接收数据。我们计算下这两个函数的调用点距离模块基址的偏移分为:0xF11E6和0xF123E。我们重启电脑,在他申请内存之前断下,我们重启后先直接查看这两个地址的汇编代码: 可以看到依旧不是真实的代码段数据,所以和之前一样我们先对clipsp+0x9F024的位置下硬件写入断点。进入登陆界面输入密码断下后,再查看0xF11E6和0xF123E偏移的位置: 可以看到当且仅当我们的Rip指针断在clipsp模块内时,代码段就是解密后的数据了。我们对这两个地址下软件断点。 我们就拿到了作为ZwDeviceIoControlFile函数输出缓冲区的申请的内存的地址,调用ZwDeviceIoControlFile之后就会在输出缓冲区中写入我们的硬盘信息。 从上图中可以看到调用ZwDeviceIoControlFile之后,地址ffffe78c6666d740就分别在+0x39的偏移处写入了硬盘的名称,在+8B的位置写入了硬盘的序列号。所以我们继续重启,对申请到的内存+0x39和+0x8B的位置下硬件写入断点。 断下后我们查看堆栈返回,发现就是我们应用层使用DeviceIoControl,控制码IOCTL_STORAGE_QUERY_PROPERTY查询的流程,因为调用了函数RaUnitStorageQueryPropertyIoctl,如果是使用IOCTL_SCSI_PASS_THROUGH进行查询的话,走的就是RaUnitScsiPassThroughIoctl函数了。那我们当作不知道这种查询是如何获取序列号的来继续逆向,我们根据堆栈返回一层一层的逐级往上分析: 我们发现一直追下去貌似有问题,那么此时我们就对堆栈返回中最近的除nt模块外最远调用返回处,在调用之前下断,查看0x70与0x18的位置值得情况。我们重启后依旧是执行之前的操作,在调用函数ZwDeviceIoControlFile之前,才对RaUnitDeviceControlIrp的调用处下软件断点,避免系统其他位置调用干扰: 如果你从未分析过这个函数的话建议先看这个函数:IofCallDriver 查看堆栈可以知道,从IofCallDriver进入函数RaDriverDeviceControlIrp,说明函数RaDriverDeviceControlIrp的参数1是DeviceObject类型的,我们就在IDA中修改参数1的类型: 回到函数RaGetUnitStorageDeviceProperty,可以分析得出他的参数1是DeviceExtension,在storport中它对应的结构是_RAID_UNIT_EXTENSION,我们修改参数1的类型后: 所以现在我们重启,在执行ZwDeviceIoControlFile之前对函数RaGetUnitStorageDeviceProperty下软件断点。 说明clipsp.sys中保存的硬盘序列号就是通过复制这里的数据获取到的。接下来我们打开DeviceTree,搜索Device,RaidPort,点击搜索到的结果的上方的Device,验证Type是否是FILE_DEVICE_DISK: 我们这里拿到的DeviceExtension和我们刚刚拿到的就是一致的,这也是绝大多数开源的HWID Spoofer源码修改机器码所使用的方式。当然他们的cllipsp.sys下的序列号肯定是没有改的。
# powershell
Get
-
CimInstance
ClassName MSFT_PhysicalDisk
Namespace root
/
Microsoft
Windows
Storage | Select
Object
FriendlyName, SerialNumber, UniqueId
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
关于解密后的代码段Dump问题:断在ClipSp.sys内后,windbg .writemem C:\clipsp_dump.bin [clipsp.sys base] [clipsp.sys end],也可以dump下解密后的代码段,IDA中定位时用字节码搜索,windbg中的偏移与IDA中对不上时,直接相减,IDA中定位那两个函数指针的偏移同样需要减去刚刚计算的差值。