简介:一份面向Windows系统管理员与安全爱好者的口令取证小工具,专门解决Win2000/NT4系统下本地登录口令遗忘后的找回问题。其原理是利用Winlogon进程会以明文形式保存登录域名和用户名,通过指定进程PID即可在内存中定位并解码加密口令。资源以RAR压缩包发布,共5个文件,包含两个可直接运行的exe程序、完整的C++源码、HTML说明文档及界面截图,整包仅106KB。目前已有793人学习下载。源码完整演示了申请调试权限、遍历进程、读取Winlogon内存、匹配用户名字符串、暴力解密口令的流程,并对Windows NT与2000的存储结构差异做了适配,适合系统管理员、安全测试人员以及想研究Windows内部机制的程序员参考学习。
1. findpass 到底能干什么:一行命令找回本地密码的利器
如果你管着一批 Windows 工作站或者自己忘了本机管理员密码,findpass 这个工具会让你少走很多弯路。它不需要重置密码、不需要引导盘,只要你在系统里有一个能打开命令行的高权限账户,运行一条命令就能把当前用户或已登录用户的明文密码直接从内存里“捞”出来。我第一次用它是在某次设备交接时:前任管理员没留密码,系统里只有一个普通的运维账号,靠着 findpass 在几分钟内拿回了管理员权限,省了一下午的重装时间。这个工具适合做本地密码恢复、资产交接审计、以及授权范围内的密码安全验证,新手也能照着步骤跑通。
2. 原理先行:findpass 从内存里“捞”密码的逻辑
2.1 为什么能直接从系统里拿到明文密码
很多人第一次听说 findpass 时都有个疑问:Windows 不是只保存密码哈希吗?为什么还能拿到明文?这里的关键在于“登录会话”和“身份验证令牌”的存储方式。当你登录 Windows 后,系统为了支持单点登录、网络资源访问等能力,会在内存中缓存一份当前用户的凭据(包括明文密码形式的安全支持提供程序数据)。findpass 的原理就是去读取这个内存区域,定位到特定结构体,然后解析出明文密码。
常见做法是打开进程列表,找到 LSASS(本地安全认证子系统服务)的进程句柄,通过 NtQuerySystemInformation 或者直接读取进程的 PEB 链来获取认证凭据存储的地址。findpass 的核心逻辑并不是暴力破解,而是“读内存 + 结构匹配”。所以它运行起来非常快,几十毫秒就能出结果,不像字典攻击那样要跑半天。
注意,这里有一个前提:findpass 拿到的是“已经登录”或者“正在会话中”的用户密码。如果目标用户当前是断开的、未登录状态,内存中就没有对应的明文凭据。这点在实际使用时要先确认,否则容易误以为工具失效。
2.2 支持的系统版本与权限边界
findpass 在 Windows XP 到 Windows 10 早期版本上表现稳定,但在 Windows 10 较新版本以及 Windows 11 上会经常碰壁。原因在于新版本系统对 LSASS 进程增加了额外的保护机制(比如 Credential Guard、基于虚拟化的安全),把明文凭据隔离到了独立的安全进程里,普通 API 读不到。
权限边界也很明确:运行 findpass 时,当前命令行窗口必须具备至少管理员权限。如果只是普通用户权限,打开 LSASS 进程会被拒绝,程序会直接报“OpenProcess failed”。有少数版本在 SYSTEM 权限下能读到更多会话的凭据,但一般管理员就够了。
2.3 编译与运行环境准备
如果你拿到的是源码包,需要自己编译。findpass 早期版本是用 C 写的,在 Visual Studio 里新建一个控制台项目,把源文件放进去,编译目标选择 x86 或 x64 取决于目标系统。我在实际中使用的是 x64 版本,因为现在大部分机器都是 64 位系统。
编译前要确认 Windows SDK 版本,常用的 _WIN32_WINNT 宏要设成对应版本。比如目标系统是 Windows 7 及以上,可以在预处理器里加_WIN32_WINNT=0x0601。如果不设置,部分 API 的声明会不完整,导致编译报错。
运行环境方面,findpass 是命令行程序,不需要安装,把编译出来的 exe 文件放到任意目录,在管理员命令行里执行即可。如果要远程使用,可以通过计划任务或服务方式部署,后面我会专门讲。
3. 实操:findpass 的下载、编译与第一轮查询
3.1 下载源码与编译参数
我通常从可信的代码仓库拉取 findpass 的源码,但不会直接使用网上随意流传的二进制包,因为这种小工具被植入后门的概率不低。源码包一般包含几个文件:findpass.c、findpass.h、Makefile 或 Visual Studio 工程文件。
拿到源码后,建议先看一遍主函数,确认没有恶意逻辑,再开始编译。我用 Visual Studio 2019 或 2022 的命令行工具编译,示例命令如下:
cl.exe /nologo /O2 /D "_CRT_SECURE_NO_WARNINGS" /D "_WIN32_WINNT=0x0601" findpass.c /Fe:findpass.exe /link user32.lib advapi32.lib参数说明:/O2是优化速度,/D定义预处理宏,_CRT_SECURE_NO_WARNINGS屏蔽掉一些不建议使用的函数警告,_WIN32_WINNT=0x0601表示面向 Windows 7 及以上。/Fe指定输出文件名,最后的user32.lib advapi32.lib是链接库,findpass 依赖这两个库的某些 API。
编译完成后,建议先在一台安全的测试机上验证 exe 能否正常运行,再分发到目标机器。
3.2 本地运行:从命令行到拿到密码
先打开管理员命令行,切换到 findpass.exe 所在目录,然后直接执行:
findpass.exe正常情况会输出类似下面的内容:
Logon Name: Administrator Domain/Computer: WORKGROUP / WIN-ABC123 Password: 123456逻辑说明:findpass 没有交互参数,它默认枚举当前系统所有活跃的登录会话,找到有明文凭据的会话后,打印用户名和密码。如果系统里只有一个活动用户,直接就能看到结果。
如果你想要指定进程或指定会话,不太走运,原版 findpass 不支持参数过滤。我一般会先执行一次看全部输出,再用findstr筛选:
findpass.exe | findstr /i "Administrator"这样能把包含 Administrator 的行单独捞出来,方便在输出很长时快速定位。
3.3 常见执行报错与参数调整
运行时报错大多围绕权限和 API 兼容。比如OpenProcess failed: 5表示权限不足,需要确认命令行是否以管理员身份启动。如果当前账户是管理员,但 UAC 没关,也需要右键“以管理员身份运行”,否则令牌仍是受限的。
还有一个常见报错是NtQuerySystemInformation failed: 0xC0000005。这个一般是系统版本太新,LSASS 内存结构变化导致地址读取失败。遇到这种情况,别在同一个系统上反复尝试,要么换老版本 Windows 测试,要么用支持新系统的替代方案。
如果输出乱码,比如密码里面中文或特殊字符显示不正常,这是控制台编码问题。执行前先用命令把代码页改成 UTF-8:
chcp 65001然后再运行 findpass.exe,输出一般就正常了。如果密码含非常规符号,建议配合后面讲的输出重定向,把结果写到文件里,避免控制台缓冲区截断。
4. 避坑指南:findpass 的五个翻车现场
4.1 杀软误报:现象、原因与解决
现象:运行 findpass.exe 时,Windows Defender 或其他杀毒软件直接弹窗并删除文件,或者拦截进程启动。
原因:findpass 的行为模式是“读取系统进程内存 + 提取凭据”,这和恶意软件的凭据窃取行为高度相似,杀毒引擎会通过行为特征判定为风险程序,哪怕它本身是合法的恢复工具。
解决:最简单的方法是先将目录加入杀软的信任白名单。在 PowerShell 里可以这样执行:
Add-MpPreference -ExclusionPath "C:\Tools\findpass"这里C:\Tools\findpass是我存放工具的目录,你可以换成自己的实际路径。加入白名单后,重新把 exe 拷贝进去就能运行了。但注意,如果是商业杀软,需要到控制台单独配置排除项,命令行不一定有用。
另一个思路是自行编译时加一些“无害干扰”来降低特征命中率。常见做法是修改字符串常量的编码方式,比如把硬编码的进程名拆成多个拼接片段,让静态扫描不那么容易判定。但这种方法只建议在授权测试环境中使用,别拿去做任何不在自己权限范围内的操作。
4.2 系统版本兼容:现象、原因与解决
现象:在 Windows 10 1809 以后的版本上执行,程序卡住不动,或者只输出版本信息就退出,拿不到密码。
原因:微软从 1809 版本开始默认开启“内存完整性”(基于虚拟化的安全),LSASS 的凭据被隔离到 VBS 环境中,普通进程拿不到结构体的物理地址。findpass 这类基于传统内存读取的工具天然失效。
解决:遇到这种情况,先看系统是否开启 Credential Guard。以管理员身份运行命令:
msinfo32在“系统摘要”里查看“基于虚拟化的安全”状态,如果显示“正在运行”,说明隔离机制已经生效。这时候不要跟系统硬碰,改用兼容新版本的工具或方法。对于密码恢复场景,可以直接用系统内置的“重置密码”功能,或者通过安全模式下的管理员账户处理。
4.3 权限不足:现象、原因与解决
现象:执行 findpass.exe 后,窗口直接打印[ERROR] OpenProcess failed: 5,没有任何密码输出。
原因:OpenProcess 的权限不足,没有请求到 PROCESS_QUERY_INFORMATION 权限。即使你当前是管理员,也可能因为 UAC 提权没有生效,或者进程运行在低权限令牌下。
解决:确认命令行窗口标题栏里是否带有“管理员”字样。没有的话,按 Win 键,输入 cmd,右键“以管理员身份运行”。如果已经是管理员还报错,检查一下进程是否被安全软件降权。我遇到过某些安全软件把命令行进程强制限制到普通权限,解决方法是暂时退出安全软件的控制保护,运行完再恢复。
4.4 内存越权与稳定性
现象:在部分老系统上,findpass 执行时偶尔会蓝屏,或者导致 LSASS 进程崩溃,触发系统强制重启。
原因:findpass 通过进程句柄读取内存时,如果结构体偏移量算错,可能读到非法地址,在某些没做异常处理的内核版本上,会直接触发蓝屏保护机制。尤其在使用非官方修改版源码时,这个概率更高。
解决:使用官方原版编译,不要随意合并网上的二开补丁。运行前先做快照或者开个虚拟机。如果是物理机,确保系统数据已备份。我在真实环境里一般不用 findpass 直接在核心生产服务器上跑,而是先在有代表性的测试机上验证,确认版本匹配后再操作。
4.5 编码乱码与输出问题
现象:密码输出为问号或矩形,特别是在中文系统下,密码含中文占位符时容易这样。
原因:控制台代码页与系统区域不匹配,或者 findpass 内部用 ANSI 编码输出,而控制台是 GBK。
解决:使用chcp 65001切换到 UTF-8 代码页,如果还不行,就把输出重定向到文件,然后用编辑器打开。重定向命令:
findpass.exe > result.txt 2>&1注意,如果密码里面含换行符,重定向后会多出一行,这是程序输出格式的问题,不影响实际密码串。拿结果时建议用十六进制查看器核对一下真实字节。
5. 实战场景:给域内主机做密码审计时的 findpass 用法
5.1 场景一:本地管理员密码遗忘后的应急恢复
某次项目交接,对方只给了普通运维账户,Administrator 密码没人知道。这时用 findpass 的思路是:先以运维账户登录,然后通过提权到管理员权限运行工具,拿到当前登录用户的明文密码。如果运维账户本身就是本机管理员组的一员,那直接就能操作。
具体步骤:先打开管理员 PowerShell,然后执行:
whoami /groups | findstr /i "S-1-5-32-544"如果能看到S-1-5-32-544(管理员组 SID),说明当前令牌具备管理员权限。接下来切到 findpass 目录运行:
Set-Location C:\Tools .\findpass.exe拿到密码后,先验证一下能不能登录 Administrator 账户。如果 findpass 拿到的恰好是当前登录的运维密码,那就用这个密码去改 Administrator 密码:
net user Administrator NewPassword注意,这里改的是重置后的新密码,不是 findpass 输出的原密码。如果原密码就是之前管理员设置的重要凭据,建议先记录下来,再重置为临时密码,交接后由对方自行修改。
5.2 场景二:批量收集本机缓存密码并导出
在维护一批离线机器时,机器上可能存在多个本地账户的缓存凭据。findpass 默认只输出当前活跃会话,但通过系统计划任务方式,可以让它在登录时自动运行,并把结果写到日志文件。
常见做法是把 findpass.exe 复制到目标机器的C:\ProgramData\FindPass目录下,然后创建一个登录触发的计划任务:
schtasks /Create /TN "FindPassAudit" /TR "C:\ProgramData\FindPass\findpass.exe > C:\ProgramData\FindPass\result_%COMPUTERNAME%.txt" /SC ONLOGON /RL HIGHEST /F这里的关键:/RL HIGHEST表示以最高权限运行,/SC ONLOGON表示用户登录时触发。输出文件名里包含了计算机名,方便后续收集。
任务创建后,等下一次目标用户登录时,就会自动生成结果文件。你也可以手动触发验证:
schtasks /Run /TN "FindPassAudit"然后检查 result 文件内容。如果有些机器没有密码输出,先看看登录会话是否正常,不要直接认为工具失败。
5.3 场景三:与自动化巡检脚本配合
在授权巡检中,我们需要批量比对本地管理员密码强度。可以写个脚本循环执行 findpass,把结果解析成结构化数据。以下是我常用的 PowerShell 脚本片段:
$computers = Get-Content "C:\list\computers.txt" foreach ($computer in $computers) { $output = & "C:\Tools\findpass.exe" 2>&1 if ($output -match "Password:\s*(\S+)") { $password = $Matches[1] [PSCustomObject]@{Computer=$computer; Password=$password} } else { [PSCustomObject]@{Computer=$computer; Password="[No credential found]"} } } | Export-Csv -Path "C:\audit\passwords.csv" -NoTypeInformation -Encoding UTF8说明:脚本遍历计算机列表,每台机器执行一次 findpass,用正则提取Password:后面的非空白字符,最后统一导出 CSV。值得一提,这里假设脚本是在每台目标机器本地执行的。如果远端批量执行,需要配合 PsExec 或 PowerShell 远程会话,这属于另一个话题。
这个 CSV 导出结果可以直接喂给下一步的密码强度扫描脚本。我一般会在导出后立刻对密码做复杂度检查,比如长度是否小于 8、是否包含用户名。如果发现弱口令,就在资产表里标记风险,并推进修改。
6. 进阶:让 findpass 在授权对抗中更“聪明”
6.1 输出格式化为 CSV,对接资产表
原版 findpass 输出是纯文本,不方便程序读取。我一般会改用管道加正则来清洗。比如先执行 findpass,再把结果转换成一行 CSV:
$raw = (& "C:\Tools\findpass.exe" | Out-String) -replace "\r?\n",";" "Username;Computer;Password" | Out-File "C:\out\cred.csv" $raw | Out-File "C:\out\cred.csv" -Append这里用分号替代换行,是为了避免密码中可能的逗号混淆字段。严谨一点可以用 ConvertFrom-Csv 反转,但临时审计这套够用。如果密码本身带分号,那就得再深入做转义,不过实际场景中极少见。
6.2 防御视角:如何让自己的系统不被 findpass 命中
作为正向防御,最关键的一点是开启 Credential Guard。Windows 10 专业版以上系统,可以通过组策略强制开启:
- 计算机配置 -> 管理模板 -> 系统 -> 设备防护 -> 打开“基于虚拟化的安全”
- 设置为“已启用”,并将“平台安全级别”设为“安全启动”
开启后,LSASS 进程的明文凭据会被 VBS 隔离,findpass 这类工具即使读到 LSASS 句柄也拿不到有效明文。代价是部分老旧驱动不兼容,所以先在测试环境验证。
另一个习惯是避免在同一台机器上长时间保持管理员会话。findpass 能抓到的是活跃会话中的密码,如果管理员用完即走、锁屏并退出会话,工具就很难拿到凭据。我在部署服务器时,会强制设置屏幕锁定超时时间为 5 分钟,并禁止用户使用“记住密码”功能。
6.3 结尾:一个必须养成的习惯
我自己用 findpass 的次数越多,越警惕一个事实:能救你于水火的工具,一样能被别人用来对付你。所以现在每次安装完系统,我都会先跑一遍 findpass,确认它拿不到任何明文凭据,然后才放心交给业务使用。那之后我又养成了一个强制习惯:所有涉及凭据的工具都放在一个专用目录里,用完立即删除,并定期检查 LSASS 是否被异常读取。这条路走下来,踩过不少坑,但也慢慢摸清了工具的边界。希望我的这些经验能帮你安全、合规地用它解决问题。
本文还有配套的精品资源,点击获取