简介
由于一些特殊的情况,操作系统提供的密码复杂度检测,不能满足我们的需求。
比如 小写字母 大写字母 数字 特殊符号 我们需要全都存在(四选四),但是操作系统只能(四选三),
又或者类似 p@ssw0rd 之类的密码,虽然复杂度要求满足,但是太常见,很容易被密码字典破解。
所以我们需要注册一个自定义的密码检测规则,在创建或修改密码时,直接进行检测和处理。
过滤器的注册
微软操作系统提供了一种 Password Filter DLL 的方式,可以在 密码保存之前 对其进行处理。
该功能需要导出三个函数,而且必须编译为DLL类型,32位系统使用32位DLL,64位使用64位DLL。
1 | BOOLEAN InitializeChangeNotify(void); |
1 | NTSTATUS PasswordChangeNotify( |
1 | BOOLEAN PasswordFilter( |
其中 InitializeChangeNotify 函数用来初始化DLL信息,返回 TRUE 表示成功,FALSE 表示失败。
其中 PasswordFilter 函数用来自定义我们的过滤规则,参数 Password 就是需要检测的密码,前两个
参数是对应的 账户名称,参数 SetOperation 为 TRUE 时,表示 密码新建 操作,反之为 密码修改 操作,
返回 TRUE 表示 允许 本次操作,返回 FALSE 表示 拒绝 本次操作。
其中 PasswordChangeNotify 函数会在所有检测都已通过,系统准备存储该密码时调用,该函数多数是
做信息记录用,而且只能返回 STATUS_SUCCESS 返回值。
注册该过滤器DLL时,我们需要先把DLL文件,复制到操作系统 System32 目录下,注意用程序复制时,
会涉及到64位系统中32位程序的目录重定向问题。然后在如下注册表路径下
1 | HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Lsa |
存在一个 Notification Packages 注册表值,是 REG_MULTI_SZ 类型,如果不存在,需要新建一个,
注意 不要删除 原来自带的数据,要在原字符串 后边附加 新字符串,填写DLL的文件名,不要 .dll 后缀。
所有操作完毕后重启操作系统,该DLL过滤器就会被操作系统加载起来。
过滤器的代码
如下为相关三个函数的代码,我们只处理 PasswordFilter 函数,其余两个函数直接返回成功。
1 | BOOLEAN __stdcall InitializeChangeNotify(void) |
1 | NTSTATUS __stdcall PasswordChangeNotify( |
1 | BOOLEAN __stdcall PasswordFilter( |
这里需要注意的地方是,每个函数都需要声明 __stdcall 类型,但是这样在头文件中使用extern "C" 导出函数时,就变成 _InitializeChangeNotify@0 的样式,导致DLL加载失败,
所以我们需要创建一个 .def 文件来代替 extern "C" 声明导出函数,文件内容如下
1 | EXPORTS |
然后在工程配置中,配置属性 -> 链接器 -> 输入 -> 模块定义文件,加入该 .def 文件

最后如果在写过滤规则时,引入了其他的库,可以使用 多线程 (/MT) 配置,把相关函数编译到DLL中。