request-free-img

Windows API Set 详解:那些 api-ms-win- 开头 DLL 文件的底层原理

你是否好奇过这些 api-ms-win- 开头的 DLL?

这一堆api-ms-win-开头的DLL文件到底是做什么用的呀?

如果你是WINDOWS桌面程序开发者,你在发布软件时是不是总会带上这些DLL文件

对此你是否好奇过呢?

其实它们有一个正式名称叫:API集

今天我就带着大家一起摸清楚WINDOWS下的API集的底层原理

DLL Hell 经典问题

在开始讲解API集之前,咱们先来看看不这么做会存在的问题

假设现在有一个程序A,它依赖common.dll的1.0版本

而程序B,它依赖common.dll的2.0版本

现在程序A安装时,为了使自己的程序能稳定运行,将系统中的common.dll覆盖了

然后程序B安装时,同样也为了使自己的程序能稳定运行,又将系统中的common.dll覆盖成了2.0版本

现在虽然程序B能正常运行,但是程序A 因为找不到 1.0 版本的特定 API 而崩溃。

这就是精典的DLL 地狱(DLL Hell)问题

API 函数迁移与维护难题

好,我们再来看第二个问题

微软公司在WINDOWS 7时,为了优化系统性能并简化API的管理将大家熟悉的

ADVAPI32.dll的中的函数迁移到了KERNEL32.dll

虽然ADVAPI32.dll中的相关函数被迁移走了,但是微软公司为了使那些依赖ADVAPI32.dll的旧程序能正常运行

ADVAPI32.dll中仍然保留 了相关函数的支持,这导至代码的维护难度以及成本大大增加

并且未来这种函数在不同DLL中的迁移的情况会频繁存在

那如何使得这种函数的迁移平滑进行又使得旧程序不受影响呢?

跨 Windows 版本兼容性挑战

再来看第三个问题

在 Windows 系统的演进过程中,每个新版本都会对内核、系统 API、DLL 结构进行优化

虽然这些优化可以带来更高的性能和安全性,但也引发了一个严重的问题:应用程序在不同 Windows 版本之间运行时会遇到兼容性障碍。

具体包括:API 实现细节差异,DLL 位置变化,废弃或替换的 API,调用约定和数据结构的变化等

那如何将各个应用程序和操作系统的DLL解耦呢?

性能、内存与安全考量

再来看第四个问题

操作系统的DLL因为要实现复杂的系统功能,大多都非常庞大

如果开发的应用程序需要加载大量的系统DLL,这势 必会增加了内存占用和程序启动时间

那要如何 提升了程序的启动速度和系统运行效率呢?

除以上问题之外,向用户暴露太多的系统核心DLL,也增加了黑客针对这些DLL进行漏洞利用的风险,

那要如何解决这些问题?

API Set(API 集)——微软的解决方案

答案就是API集

API 集(API SET)是微软从 Windows 7 开始引入的一种 API 模块化机制,旨在解决 DLL 依赖、跨版本兼容性、以及系统模块化管理 等问题。

它本质上是一套 API 重定向机制,将应用程序对特定 API 的调用映射(Redirect) 到实际实现这些功能的系统 DLL(如 kernel32.dll、kernelbase.dll)上。

API 集通过强契约名称进行标识

名称必须以 api- 或 ext- 开头。

以 api- 开头的名称表示该 API 存在于所有满足该 API 版本要求的 Windows 版本中。

而以 ext- 开头的名称表示该 API 可能不会存在于所有 Windows 版本中。

名称必须以 l<n>-<n>-<n> 结尾,其中 n 由十进制数字组成版本号

例如:

api-ms-win-core-file-l1-1-0.dll

api-ms-win-crt-runtime-l1-1-0.dll

它们就叫做API集(API SET)

API Set 的底层工作原理

那系统又是如何知道应该转发到具体哪个DLL上呢?

其实在Windows操作系统中,存在一个叫做ApiSetSchema.dll的文件用于管理API重定向机制。

该文件并不包含实际的功能实现,而是充当一个映射表,记录了以api-ms-win-开头的DLL(即API 集)与其实际实现DLL之间的对应关系。

ApiSetSchema.dll中包含一个名为.apiset的节,

该节记录了所有api-ms-系列动态库应被重定向到的目标DLL。

当应用程序请求加载一个api-ms-win-前缀的DLL时,系统会参考ApiSetSchema.dll中的映射关系,

将该请求重定向到实际的实现DLL。

系统初始化与重定向流程

具体来说,当Windows 系统初始化时,它会加载 ApiSetSchema.dll文件

并将.apiset 节映射到内核空间

同时设置 PEB,并将 ApiSetMap 指向 ApiSetSchema.dll中的.apiset

当有用户程序启动时

如果用户程序链接到一个以api-ms-win开头的DLL

内核会查找 ApiSetMap 映射表,从而找到函数实际实现的DLL例如 kernel32.dll,然后加载实际 DLL,例如 kernel32.dll,并执行真实函数的代码

+-----------------------------+
| Windows 系统初始化阶段 |
+-----------------------------+
            |
            V
+-----------------------------+
| 加载 ApiSetSchema.dll |
| - .apiset 节被映射到内核空间 |
+-----------------------------+
            |
            V
+-----------------------------+
| 设置 PEB (进程环境块) |
| - ApiSetMap 指向 .apiset |
+-----------------------------+
            |
            V
+-----------------------------+
| 启动 A.EXE 程序 |
+-----------------------------+
            |
            V
+-----------------------------+
| A.EXE 调用 MoveFileExW |
| (链接 api-ms-win-core-file- |
| l2-1-0.dll) |
+-----------------------------+
            |
            V
+-----------------------------+
| 查找 ApiSetMap 映射表 |
| (位于 PEB 中) |
+-----------------------------+
            |
            V
+-----------------------------+
| 映射到实际实现 DLL |
| 例如: kernel32.dll 或 |
| kernelbase.dll |
+-----------------------------+
            |
            V
+-----------------------------+
| 加载实际 DLL (如 kernel32.dll) |
| 定位 MoveFileExW 实现 |
+-----------------------------+
            |
            V
+-----------------------------+
| 执行 MoveFileExW 实际代码 |
+-----------------------------+
            |
            V
+-----------------------------+
| 返回结果到 A.EXE |
+-----------------------------+

实际映射示例与验证

这种机制提高了系统的模块化和兼容性,使得应用程序可以在不同版本的 Windows 上无缝运行。

到此,可能你仍然心存疑惑

apisetschema.dll中的实现真的是这样的吗?

好的,我们现在就借助GITHUB上别人的PYTHONG脚本把apisetschema.dll中的apiset节打印出来给你看看

https://github.com/thewhiteninja/apysetschema

我们执行这个PYTHON程序

python main.py -f C:\Windows\System32\apisetschema.dll

看到了吗,这是我WINDOWS 11下apisetschema.dll文件的API集DLL和真实DLL的映射记录

它记录了每一个api-ms-win开头以及以ext-ms-开头的API集文件应该跳到哪个真实DLL

例如这个DLL api-ms-win-eventing-tdh-l1-1-2 就是跳转到这里tdh.dll

API Set 的演进历程

微软公司在Windows 7中开始引入 API 集机制

到Windows 8API Set 机制全面推广

而Windows 10 及以后版本,API 集已 成为核心架构

总结

现在对于WINDOWS的API集,你明白了吗?

发布说明:本文详细解析了 Windows API Set 机制,帮助开发者更好地理解系统 DLL 依赖与兼容性问题。适合 Windows 开发、系统底层研究等相关主题。


更多问题探讨,请关注公众号:程序员角