在帮Sandboxie-Plus这个开源项目撰写代码的时候正好写到了这个功能,写在这里记录一下。
我们首先需要新建一个动态链接库项目,在Visual Studio中新建一个“Win32 应用程序”类型的解决方案,子类型选择动态链接库。然后我们需要编译Detours并将结果链接到项目中,可参考:
https://blog.csdn.net/m0_63548806/article/details/134996049
经过对于一些上层函数进行逆向操作,我追踪到了一个在用户层相对底层的函数:GetVolumeInformationByHandleW
MSDN文档:
https://learn.microsoft.com/zh-cn/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationbyhandlew
将函数原型在动态链接库中定义并在DllMain中执行挂钩后我们便可以编写HOOK后的重定向函数了。
我们希望针对不同的盘符能有不同的返回,且对于同一分区的返回在单次运行会话中始终相同,因此需要创建一个Map.在Sandboxie的项目中,动态链接库所定义的文件位于一个.c文件中,因此我们不得不自行实现Map数据类型,但我们在这个实现中可以使用C++标准库:
include<map>
这样一来,我们可以将原函数返回的序列号作为键,临时生成的序列号作为值了。
此外,考虑到要适应多线程的环境,为了避免出现数据不同步的情况,我们要做同步处理。
在全局范围内定义:
首先进入函数,
调用原函数地址其返回的硬盘序列号,并将其返回值放置到rtn这个布尔类型变量中。
然后判断,如果
那么,
等待线程释放对“锁”的使用权。
随后,我们应该将ourSerialNumber作为Key传入Map中查找。在这里使用的是Sandboxie的自建库,标准库与之不同。
接下来判断,如果lpCachedSerialNumber不为空,则说明程序之前请求过同一分区的序列号,直接将之前的生成结果复制到上级程序给出的缓冲区:
否则,则说明这是程序第一次访问这一分区的序列号,那么生成一个随机的值,传递给上层程序,并以原函数返回的序列号为Key,随机生成结果为Value插入到Map中。在这里生成随机数和Map都是用的自建库,实际操作中随机数生成可以使用rand标准库。
随后,释放同步锁的所有权。
最后,返回原函数给出的返回值。
此外,你还需要一个注入程序用来对系统中每一个用户层程序进行注入,这个在Sandboxie-Plus中由LowLevel实现,在实际应用中可以自行选择。