你有没有遇到过这种情况:一台测试用的Linux虚拟机放了两三个月,再打开时死活想不起来root密码;或者给客户部署了一个Windows虚拟机,交接时对方一脸无奈说"密码忘了,进不去系统了"。身边的同事第一反应往往是"破解一下",但说句大实话,真正的虚拟机密码恢复,九成以上是"重置"而不是"破解"——系统是你自己的、磁盘文件也是你手里的,你需要解决的只是"没有登录凭证时如何重新拿回控制权"这件事。这篇文章就把VMware Workstation和VirtualBox下常见的Linux/Windows虚拟机密码恢复方法、底层原理、操作细节和坑一次讲清楚,适合运维、测试、以及把虚拟机当主力开发环境的朋友参考。我先把话说在前头:所有操作仅适用于你拥有或已获授权的虚拟机,用来找回自己忘记的密码;未经授权去动别人的系统,无论在哪个圈子都是大忌。
1. 先搞清楚:这到底算不算"破解"
1.1 你需要先分清合法边界
很多人一搜"虚拟机密码破解",脑子里浮现的都是暴力跑字典、绕过登录界面那套东西。但实际操作里,碰到最多的情况就是"自己设的密码忘了"或者"维护的旧虚拟机密钥没有交接记录"。自己的虚拟机,用重置的办法拿回访问权,完全合规;但如果是别人托管的、没有书面授权的虚拟机,那一律不要碰,哪怕对方口头说"没事你试试"。我见过有人为了在同事面前展示技术,偷偷去重置别人测试机的密码,结果那台虚拟机里跑着一个没备份的数据库,最后数据没救回来,既丢了里子也丢了面子。所以这篇文章的边界非常明确:讨论的是找回你自己系统的访问权,不是入侵。
1.2 虚拟机密码到底存在哪里
要理解后续的操作,得先知道系统密码放在哪。Linux系统的用户密码哈希保存在/etc/shadow文件里,普通用户不可读,只有root能读写;当你输入密码登录时,系统会把输入内容做哈希运算,再和shadow里存的那串值比对。Windows系统则是把SAM(Security Account Manager)数据库存放在C:\Windows\System32\config\SAM,注册表里还存着一份缓存,密码哈希同样在里面。明白了这一点,思路就打开了:只要能读取并修改这些密码文件,就能重置密码,根本不需要"爆破"。
虚拟机相对物理机有个天然优势——整个磁盘就是一个普通文件(VMDK、VHD、VDI或QCOW2),宿主机可以直接挂载、复制、修改。这就是虚拟环境下密码恢复比物理机容易得多的根本原因。物理机你可能还得拆机、做PE盘、进BIOS改启动顺序,虚拟机只需要在VMware或VirtualBox的界面里换一个启动镜像就行。
1.3 动手之前先做三件准备
先说个血泪教训:我曾经在一台运行着CentOS 7的虚拟机上直接修改/etc/shadow里的密码哈希,改完重启发现系统完美启动,我还挺得意。结果第二天才发现,这台机器上有应用在读取同一个用户的密码做定时任务,我这么一改,把整个联动逻辑搞崩了。所以在重置前,我建议所有操作都先做准备:
- 快照(Snapshot):在VMware或VirtualBox里给当前状态打一个快照。一旦操作失误,可以秒回原状,这是虚拟机环境给的最大容错福利,不用白不用。
- 备份磁盘文件:把VMDK或VDI文件复制一份到其他目录。快照擅长防"改坏",全量备份则能防"磁盘损坏",两件事最好都做。
- 记录当前版本信息:确认虚拟机里装的具体是哪个系统版本、用了什么文件系统、有没有开启磁盘加密(LUKS/BitLocker)。这些信息决定了你选哪条重置路线,比如Ubuntu 22.04默认的GRUB策略和CentOS 6时代的GRUB就完全不同。
2. Linux虚拟机忘记密码:折腾GRUB是主流办法
2.1 单用户模式重置密码的完整流程
Linux系统的密码重置,最常用的路数是进入单用户模式,也就是跳过正常的登录界面,直接拿到一个root shell。绝大多数发行版,包括Ubuntu、Debian、CentOS、Rocky Linux,流程都差不多。
第一步,启动虚拟机,在GRUB菜单出现时按e键进入编辑模式。以CentOS/RHEL系为例,找到以linux16或linuxefi开头的那一行,它负责引导真正的内核,行尾会有rhgb quiet这种参数。把这两个参数删掉或保留都行,关键是追加一段内容:
rw init=/sysroot/bin/sh注意这里一定要写rw,意思是让根文件系统以读写方式挂载。如果不加,默认是只读挂载,后续操作会直接报"Read-only file system"。
第二步,按Ctrl + X或F10启动进入这个特殊的shell。在RHEL/CentOS 7之后的版本里,你会进入一个带switch_root提示符的临时环境,需要手动执行:
chroot /sysroot之所以要先chroot,是因为此时系统还没完成正常的初始化流程,真正的根目录挂在/sysroot下。进入chroot环境之后,你面对的就是一个完整可读写的根目录了。
第三步,直接改密码。最简单的方式:
passwd root输入两遍新密码即可。如果是重置普通用户,比如testuser,就执行passwd testuser。改完之后,在RHEL系系统上还有一个非常关键的步骤——SELinux重打标签:
touch /.autorelabel为什么要做这一步?因为SELinux会给文件打安全上下文标签,你刚才用shell直接修改了/etc/shadow,这个文件的SELinux标签可能已经不对了。如果不重打标签,重启后系统极有可能因为SELinux拒绝访问/etc/shadow,出现无法登录或者各种诡异问题。Ubuntu/Debian系统默认SELinux未启用,这一步可以跳过。
第四步,重启。直接执行reboot或者exit之后正常重启,用新密码登录即可。
2.2 进不去GRUB?用LiveCD路线改shadow
单用户模式虽然快,但有个前提:你能进GRUB菜单。如果GRUB被隐藏了(默认超时设成0)、GRUB菜单损坏、或者虚拟机用了UEFI引导且启动项乱了,这条路就断了。这时候就需要"曲线救国"——用LiveCD镜像启动一个临时系统,挂载原来的磁盘,直接修改密码文件。
第一步,在虚拟机设置里把ISO镜像换成Ubuntu或CentOS的安装盘。以Ubuntu Live镜像为例,启动后选择"Try or Install Ubuntu",进入Live桌面环境。
第二步,打开终端,查看磁盘分区:
sudo fdisk -l虚拟机磁盘一般是/dev/sda或/dev/nvme0n1。Linux系统分区通常是/dev/sda1(EFI分区)、/dev/sda2(根分区)这种布局。挂载根分区:
sudo mount /dev/sda2 /mnt这里有个很常见的坑:如果根分区是LVM逻辑卷,分区名会变成/dev/mapper/centos-root或/dev/mapper/ubuntu--vg-ubuntu--lv,直接用fdisk -l看不到。先用sudo lvs查看逻辑卷列表,再挂载对应路径。
第三步,挂载完以后,需要把宿主系统的相关目录绑定过去,否则chroot进去之后网络、设备都没有。执行:
sudo mount --bind /dev /mnt/dev sudo mount --bind /proc /mnt/proc sudo mount --bind /sys /mnt/sys然后chroot进去:
sudo chroot /mnt接下来就和单用户模式一样了,用passwd修改密码,必要的时候执行touch /.autorelabel。
还有一招更直接的:不进入chroot,写一个小脚本把新密码哈希替换到/etc/shadow。如果你是在另一台Linux机器上操作虚拟磁盘,可以用openssl passwd -6生成哈希:
openssl passwd -6 mynewpassword然后用sed替换/mnt/etc/shadow里对应行的第二个字段。这招适合脚本化批量处理,但我个人不推荐新手直接用,因为容易搞错字段格式,手动改错一个字符都会导致密码无法验证。
2.3 为什么单用户模式不是万能钥匙
如果你按上面的流程操作会发现,单用户模式在很多新发行版上不是百分百成功的。主要原因有几个:
第一,systemd的默认target限制。现代systemd系统里,传统的单用户模式本质上是被引导进入rescue.target或emergency.target。但有些系统在GRUB里没有显式配置该target,或者root文件系统挂载失败后直接掉进emergency shell,而emergency shell有时是只读的。所以我在前面特意强调内核实参里要加rw,而不是依赖系统自动挂载。
第二,签名校验与安全启动。如果虚拟机的固件启用了Secure Boot,而你的Ubuntu版本又完整验证了内核签名和initramfs签名,那么手动修改过的GRUB启动项可能直接被拒。这时候要么在BIOS/虚拟机固件设置里临时关闭Secure Boot,要么走LiveCD路线,后者更省心。
第三,密码字段本身被锁。有些系统的/etc/shadow里,密码字段开头是!或*,表示该账户被锁定或密码登录被禁止。单用户模式下用passwd重置,如果发现重置完了还是没法登录,记得检查一下shadow里的字段。可以用passwd -u root解锁账户,或者直接看usermod -L/-U的状态。这个细节不多见,但排查问题时容易绕弯路。
3. Windows虚拟机忘记密码:替换法效率最高
3.1 用Windows安装镜像进入恢复环境
Windows虚拟机的密码恢复思路和Linux不一样,Windows没有"单用户模式"这种通用的等效方案,但有一个流传很广、也确实有效的"辅助工具替换法"。核心思路是:Windows系统有一个叫"轻松使用"(Utilman.exe)的辅助功能,可以在登录界面底部被触发,而且它是以SYSTEM权限运行的。如果我们把这个文件替换成cmd.exe,那在登录界面点一下"轻松使用",就能得到一个SYSTEM权限的命令行,想改什么密码都行。
具体操作分几步。
第一步,把Windows安装ISO挂载到虚拟机光驱,在虚拟机设置里勾选"启动时连接"。启动时按F2或DEL进入固件界面,把光驱启动顺序调到硬盘之前;或者直接在VMware的电源菜单里选择"打开电源时进入固件"。
第二步,从ISO启动后,在安装界面按Shift + F10打开命令提示符。现在需要找到系统装在哪个盘。执行:
diskpart list volume假设计算机硬盘是C:,执行以下命令把原系统的utilman.exe备份出来:
move C:\Windows\System32\utilman.exe C:\Windows\System32\utilman.exe.bak copy C:\Windows\System32\cmd.exe C:\Windows\System32\utilman.exe如果你在使用Windows 10/11较新的镜像时发现move命令提示权限不足,可以先把ISO里的install.wim释放出来的PE环境跑起来,或者直接用下一步提到的chntpw路线。在PE环境里,C:盘可能变成D:,需要先用dir D:\Windows确认一下。
第三步,关闭命令提示符,正常重启虚拟机,这时候不是从ISO启动了,改成从硬盘启动。在锁屏界面,点击右下角的"轻松使用"图标(就是那个小人加时钟的图标),弹出的不再是辅助功能设置,而是一个管理员命令行窗口。在里面执行:
net user先看一下有哪些用户,然后重置管理员或其他用户密码:
net user Administrator newpassword123需要注意,net user改密码时会受本地策略中的"密码复杂度要求"影响,如果系统开启了复杂度策略,太简单的密码会失败。测试机还好,域环境下可能还会触发账户锁定策略,这个后面细说。
改完密码后,双击锁屏界面的用户头像,输入新密码,就能进系统了。进去之后别忘了把utilman.exe还原,否则以后该功能不可用。从恢复环境里反向操作即可:
copy C:\Windows\System32\utilman.exe.bak C:\Windows\System32\utilman.exe del C:\Windows\System32\utilman.exe.bak3.2 用chntpw离线修改Windows SAM数据库
替换法依赖Windows能进入恢复环境或PE。但如果虚拟机的BitLocker加密、恢复环境组件故障、或者你手里连Windows安装ISO都没有,可以考虑用chntpw这个开源小工具。它是专门用来离线编辑Windows注册表SAM文件的,在Linux下就能运行。
思路是:先把Windows虚拟磁盘挂载到一个Linux环境(这一步我会在第四章详细讲),然后找到Windows/System32/config/SAM文件,用chntpw读取和修改。基本命令:
chntpw -i SAM进入交互菜单后,选择1(Edit user data and passwords),然后输入用户名。chntpw会显示几个选项:1清空密码、2设置一个新密码(它写的是Unlock并重设)、3设为管理员组成员等。我实际测试下来,选项1(blank password)最省事,因为chntpw直接写NT哈希的空密码,比它自己生成的哈希兼容性更好。
清空密码之后,Windows锁屏界面里直接按回车就能登录,然后再去net user设置新密码。这里说个细节,chntpw清空密码后,有些Windows版本第一次登录会卡在"正在准备桌面"较长时间,不要慌,等一会儿就好,实在不行再重启一次。
chntpw的局限性在于它不能处理BitLocker加密的磁盘,一旦SAM文件本身被加密,必须在挂载前先用BitLocker密钥解锁卷。另外它对Windows 11的本地账户支持还行,但微软账户登录就会复杂很多——这里不讨论在线账户,只针对本地账户,毕竟虚拟机场景里绝大多数都是本地账户。
3.3 重置之后要处理的三个细节
Windows密码重置成功,不代表万事大吉。以下几个细节很容易被忽略,但影响很大:
第一,替换文件一定要还原。我见过有人用替换法进了系统,密码也改了,但是utilman.exe一直没还原。过了一个月需要用到"轻松使用"功能时才发现系统组件损坏,修复起来特别麻烦。趁刚登录系统还记得,第一时间还原最稳。
第二,账号锁定状态。如果这台虚拟机曾经被人暴力尝试过密码,或者加入了域环境(虽然虚拟机场景少见),重置密码时可能遇到账户被锁定的情况。在cmd窗口里执行net user username /active:yes可以确认账户是否禁用,再执行:
net user username /times看一下是否有登录时间限制。本地虚拟机一般没有这个限制,但加固过的Windows Server镜像就可能有。
第三,Windows密码哈希缓存。重置密码后,其他设备如果之前用这台虚拟机的凭据连过来(比如宿主机映射了虚拟机的共享文件夹),需要重新输入新密码。如果发现连接不上,清理宿主机上凭据管理器里的旧记录即可。
4. 实操环节:VMDK/VHD镜像的挂载与密码文件定位
4.1 在宿主机上把虚拟磁盘变成可访问盘
不管是Linux还是Windows方案,都有一个共通的底层技能:把虚拟磁盘文件挂载成宿主机可访问的盘。这项技能在密码重置之外也很有用,比如从旧虚拟机里拷数据、修复损坏的系统文件。
最省事的做法是直接在VMware Workstation的虚拟机设置里操作。选中硬盘设备,点击"映射",勾选"以只读模式打开",Windows宿主机就会像插了一个U盘一样,把VMDK里的分区显示成盘符。注意,默认强烈建议只读打开,可写模式下如果VMware在宿主机上不支持文件系统日志,容易把Ext4文件系统写坏。
VirtualBox稍微麻烦一点,它的VDI文件不能直接映射,但可以转换成VMDK之后再映射:
VBoxManage clonehd source.vdi destination.vmdk --format VMDK还有一种通用方案:用qemu-nbd在Linux宿主机上挂载各种格式的磁盘镜像,对QCOW2和VDI、VMDK都有效:
sudo modprobe nbd max_part=8 sudo qemu-nbd -c /dev/nbd0 /path/to/disk.qcow2 sudo fdisk -l /dev/nbd0挂载后,分区设备是/dev/nbd0p1、/dev/nbd0p2,直接用mount挂载对应分区即可。用完后记得:
sudo qemu-nbd -d /dev/nbd0断开连接,否则镜像文件一直处于占用状态。
4.2 用DiskGenius把虚拟机磁盘转成U盘或物理盘
很多做系统维护的朋友喜欢用DiskGenius,它在Windows下可以直接读取VMDK和VHD,还支持把虚拟机磁盘文件转换成可以在物理机上启动的格式。热搜里"diskgenius转虚拟机为u盘"指的就是这类操作:把虚拟磁盘的分区克隆到U盘或物理硬盘上。
这个操作对密码恢复有什么意义?举个实际场景:一台Windows虚拟机完全无法进入修复模式,你又不想用chntpw在Linux下操作,可以把虚拟磁盘克隆到一个U盘,然后用这个U盘在任意物理机上启动,再利用Windows PE环境去修改SAM文件。虽然听着绕,但在排查"虚拟机启动蓝屏"这类问题上特别管用。
具体步骤并不复杂:打开DiskGenius,依次选择"磁盘"→"打开虚拟磁盘文件",加载VMDK后,选中要克隆的分区,执行"克隆分区"到目标U盘。克隆完成后,把U盘接到正常的物理机或另一台虚拟机,设置成从U盘启动。这时你面对的就是一个几乎和原系统一模一样的Windows环境,可以自由使用PE工具或手动替换utilman.exe。
需要特别提醒:克隆分区时,原虚拟机和目标盘的分区结构最好保持一致,否则启动时会因为BCD文件里的盘点不符而蓝屏。DiskGenius通常会自动处理,但保险起见,克隆完成后先在虚拟机里测试一次,再拿到物理机上折腾。
4.3 LUKS和BitLocker:先解开磁盘加密才是关键
现在的Linux发行版安装时经常顺手就开LUKS全盘加密,Windows 10/11的虚拟机也越来越多启用BitLocker。这种情况下,前面所有"直接挂载、直接修改密码文件"的方案基本全部失效——你看到的都是密文。
Linux LUKS的处理相对容易。在LiveCD环境或宿主机上,先安装cryptsetup,然后用:
sudo cryptsetup luksOpen /dev/sda2 my_vm_crypt输入原虚拟机的LUKS密码后,会生成一个/dev/mapper/my_vm_crypt设备,接下来再正常挂载这个解密后的设备就行。问题在于:如果你连LUKS密码也忘了,那就只能认栽,这就是全盘加密的代价。这也是我不建议在虚拟机里做全盘加密、却把密钥文件放在宿主机明文目录里的原因——效果等于给门上挂了个小锁,但钥匙就搁门垫底下。
Windows BitLocker稍微复杂一点。BitLocker有两种钥匙:恢复密钥(48位数字串)和TPM芯片验证。虚拟机的BitLocker通常不依赖TPM,而是用虚拟机启动时的固定密钥,所以需要你手里有恢复密钥。挂载VHDX/VMDK到Windows宿主机后,如果分区显示为BitLocker加密,可以尝试:
manage-bde -unlock E: -RecoveryPassword xxxxx-xxxxxx-...解锁成功后,E盘才能被访问,SAM文件才不是密文。如果你既忘了系统密码又找不到BitLocker恢复密钥,那这个虚拟机基本没有常规恢复手段了,这就是加密的意义。好消息是,很多用虚拟机跑Windows的人实际上并没有启用BitLocker,只是开了"设备加密"的假象,此时SAM文件在挂载后仍然可以直接读取。
5. 常见问题与排查技巧实录
5.1 我踩过的坑和排查思路
做虚拟机密码恢复这些年,我积累了一些很实在的坑,整理成表格方便你对照排查:
| 现象 | 可能原因 | 处理思路 |
|---|---|---|
| GRUB编辑后按Ctrl+X黑屏无反应 | 内核实参没有加rw,或root分区类型与initramfs不匹配 | 重新编辑,确认root=参数指向正确分区,加上rw后用rdbreak调试 |
单用户模式下passwd报"Authentication token manipulation error" | /etc/shadow所在文件系统只读挂载,或SELinux阻止写操作 | 检查挂载状态,先执行mount -o remount,rw /,再执行chmod 600 /etc/shadow |
| 重置密码后登录仍然被拒绝 | shadow文件字段被误改,或账户被锁定(shadow字段中有!) | 查看shadow第二字段是否正常,执行passwd -u解锁 |
| Windows替换utilman.exe后点击无反应 | 系统启用了Windows Defender篡改保护,或文件替换被权限拦截 | 检查文件是否真的替换成功,必要时偏移到PE环境操作 |
| chntpw清空密码后进系统卡死 | Windows正在做首次登录初始化 | 等5-10分钟,若仍无响应,重启一次再试 |
| 挂载VMDK时Windows提示"磁盘无法识别" | VMDK是精简置备,宿主机无法映射不连续块 | 先尝试vmware-vdiskmanager -R修复,或改用qemu-nbd方式挂载 |
| BitLocker加密导致SAM无法读取 | 卷处于加密锁定状态,未解锁 | 先找恢复密钥,用manage-bde解锁后再操作 |
5.2 几条保命的运维习惯
第一,任何重置都先打快照,然后确认快照能正常回滚。操作完成后,快照不要急着删,至少保留一个工作周期。虚拟机的快照不是摆设,我见过太多人改完密码后发现系统里某个服务起不来,想回滚却发现自己压根没打快照。
第二,密码管理要用工具,不要靠脑子。对待虚拟机密码的遗忘问题,最好的方案其实是让它永远不会发生。可以用KeePass或Bitwarden,甚至就是一张加密的Excel表,把每个虚拟机的IP、系统版本、账号、密码、最后修改时间记录下来。我自己的习惯是,每台虚拟机交付前都在备注里写清"初始密码/重置日期",并同步到团队共享的Wiki里。
第三,能进系统就配置SSH密钥或Windows远程桌面。如果虚拟机是Linux,启用PermitRootLogin prohibit-password,把公钥放进去;如果是Windows,打开远程桌面并添加一个仅用于管理的本地账户,并把密码记录下来放到安全的地方。这样即使忘了密码,也可能通过密钥或另一个管理入口绕过登录界面进行重置,不需要每次都去动磁盘文件。
第四,区分"重置密码"和"恢复数据"两个目标。有时候你其实只需要拿到里面的数据,不需要进系统。这时候千万别急着改密码,先考虑直接挂载磁盘拷贝文件。改密码有一个隐藏风险:某些应用会把密码哈希放在配置文件里(比如MySQL的user表、或者Web应用的DB连接串),重置系统密码虽然不影响这些数据,但会误导你以为是"所有密码都变了",从而在排查问题时绕远路。
最后再分享一点经验
讲完这些方法,我最大的体会是:虚拟机密码恢复这件事,技术本身并不难,真正难的是判断场景、控制风险和养成习惯。永远先确认这台机器归属权在你手里,永远先做快照,永远别在把密码写到团队文档之外的地方。真到需要重置的那一刻,你反而会庆幸自己当初留着后手——比如一个SSH公钥、一条BitLocker恢复密钥、或者虚拟机旁边那个不起眼的备份文件。这些看似琐碎的准备工作,才是让"密码破解"从应急救火变成常规操作的关键。