首页 / 资讯中心 / 文章详情

VMware虚拟机Linux密码重置实战:从手工到Python自动化

VMware虚拟机Linux密码重置实战:从手工到Python自动化 ★ FEATURED ARTICLE
做虚拟化运维这些年我接到最多的紧急请求之一就是虚拟机密码丢失。业务负责人出差大半个月回来Linux虚拟机root密码怎么都想不起来员工离职交接时账号密码根本没写进文档。这种时候总有人跑来问我能不能把VMware虚拟机的密码破解掉先说实话这篇文章标题里虽然写了“破解”但真正高频刚需的并不是逆向分析加密算法也不是暴力枚举口令而是密码重置与恢复。VMware虚拟机密码问题要分两层看一层是guest操作系统登录密码一层是虚拟磁盘加密。方向判断错了再炫酷的工具也白搭。我这篇以最常见的Linux虚拟机为例子从手工重置讲起再到一个自用的Python辅助脚本我内部代号叫pyvmx-cracker把原理、步骤和现场踩过的坑一次说清楚。适合虚拟化运维、系统管理员以及所有被虚拟机密码问题折磨过的同学参考。1. 先分清两个概念方向错了再折腾也白搭1.1 操作系统登录密码和虚拟磁盘加密不是一回事很多求助的人把“虚拟机密码”当成一个单一概念实际上这里藏着两种完全不同的密码模型。第一种是操作系统登录密码。表现是虚拟机正常开机到了登录界面卡住密码不对进不去。这类密码的本质是认证数据Linux里保存在/etc/shadowWindows里保存在SAM数据库。它们不是不可逆的加密密文更像是一份密码哈希的对照表。你忘了原来的密码没关系只要能用一种受系统信任的方式绕过登录认证或者把新密码的哈希写回这些文件就完成了重置。第二种是虚拟磁盘加密。表现是vSphere或Workstation里打开虚拟机时提示需要输入加密密钥没有密钥整个虚拟机文件就是一团密文。这种状态下操作系统登录口令根本没有起效的机会因为磁盘层就已经被锁死了。处理这种问题只能走密钥找回、密钥管理服务或备份恢复不存在“改一个文件就能绕过”的合法通道。我遇到很多新手一上来就问“有什么工具能破解VMware加密密码”实际上他们手里大部分虚拟机根本没有启用加密只是登录密码忘了。把这两层剥开处理路径会清晰得多登录密码走重置路线磁盘加密走密钥恢复路线。类型卡住的位置典型现象常规处理方法操作系统登录密码guest系统内部能开机界面要求密码单用户模式重置、修改shadow虚拟机加密密钥宿主机/文件层开机前就要求输入密钥密钥管理系统、恢复密钥、备份还原分区/磁盘加密如LUKSguest磁盘层GRUB之后提示密码保留密钥文件、密码重置盘1.2 遇到虚拟机密码问题先做这三步确认动手之前不管谁来求助我都坚持先确认三件事。第一所有权与授权。这台虚拟机是不是你负责的有没有系统所有者、上级主管或项目负责人的明确授权企业环境里虚拟机往往承载着业务数据和他人工作成果未授权操作轻则违反内部制度重则踩法律红线。没有授权我不会碰。第二快照与备份。虚拟机当前有没有可回滚的快照如果连快照都没有至少确认重要数据在备份系统里可恢复。密码重置本身不算高风险操作但任何对磁盘的写操作都有意外可能没有逃生通道就别上路。第三加密状态。在打开虚拟机时、在vSphere中检查虚拟机属性或直接看vmx文件里有没有encryption相关配置项。只要出现加密字样立刻停止重置思路转去走密钥恢复流程。这三条任何一条不满足我会建议先回去走审批或找负责人确认而不是贸然操作。2. 手工重置一台Linux虚拟机从GRUB到root shell2.1 为什么改内核参数就能绕过密码要理解为什么要改GRUB先看虚拟机开机后发生了什么。固件加载GRUBGRUB加载内核和initramfs然后init进程接管系统启动各种服务最后进入多用户登录界面。密码校验发生在最后的登录阶段。如果我们能告诉内核“别启动init直接给我一个shell”就相当于在保安上岗之前溜进了机房。Linux下常用的启动参数有三个rd.breakRHEL/CentOS体系的dracut initramfs阶段中断停在switch_root之前的shell。init/bin/bashDebian/Ubuntu体系常用直接把init程序换成bash。single或1老SysV体系里的单用户模式现在多数发行版也保留。这三个参数的共同点是让系统启动过程中断在登录服务之前给操作者一个root权限的命令行。企业里CentOS/RHEL出现频率最高所以下面以rd.break为主讲。2.2 一台CentOS虚拟机的手工重置全过程假设目标是一台CentOS 7虚拟机root密码丢失需要重置。标准流程如下。拍摄快照。VMware Workstation里右键虚拟机选择“快照-拍摄快照”vSphere里在虚拟机列表右键选择“快照-生成快照”。快照的意思是哪怕后面GRUB参数改错了也可以一键回到当前状态这是整个操作的安全网。打开虚拟机电源立刻点击虚拟机窗口连续按Esc或Shift确保GRUB菜单完整出现。在vSphere里需要先打开控制台窗口再操作。光标停在默认内核那一行按e进入编辑界面。找到linux16或linuxefi开头的那一行移动到行尾空格后追加rd.break。按CtrlX启动。系统会在一个提示符下停住显示类似switch root的信息。接下来执行mount -o remount,rw /sysroot chroot /sysroot passwd root解释一下为什么必须先重新挂载。rd.break进入的临时环境里真正的系统根目录被挂在/sysroot而且是只读的。如果直接执行passwd改的是initramfs临时环境里的影子文件重启后等于白改。chroot /sysroot后才是真正进入了原系统。输入两次新密码后建议顺手执行touch /.autorelabel。这一步容易被忽略。CentOS/RHEL默认开启SELinux如果系统文件的安全上下文因为这次修改发生变化重启后可能出现登录异常、服务起不来甚至反复重启。/.autorelabel这个标记文件会告诉内核下次启动时对所有文件重新打SELinux标签。最后输入exit退出chroot再执行reboot重启。可以连按两次exit或者直接reboot -f强制重启。重启后系统会进入正常流程用刚才设置的新密码登录即可。2.3 另一个思路直接修改/etc/shadow文件如果你不想在GRUB里人肉操作或者几次都没抓住GRUB菜单出现的时机还有第二条路关机把vmdk挂载到宿主机上直接改/etc/shadow。shadow文件的每一行代表一个用户字段用冒号分割。第一字段是用户名第二字段是密码哈希。改密码的原理不是破解旧哈希而是用openssl passwd -6生成一个新密码的哈希替换第二字段。系统登录时只会校验输入的密码哈希是否和这个字段一致哈希换掉就等于密码换掉。openssl passwd -6 YourNewPass这条命令会输出类似$6$salt$hash的字符串把它放到/etc/shadow里对应用户的第二个字段即可。这个思路可靠性更高因为不用处理GRUB交互也是后面脚本的基础。但有一个重要限制如果根分区启用了LUKS这类磁盘加密宿主机挂载到的只是密文无法直接读取文件系统。这种情况下仍然需要先解锁加密层才能进入下一步。3. Python脚本实战pyvmx-cracker的完整实现3.1 脚本能做什么以及在什么前提下才允许做手工流程在单台虚拟机上很快但企业环境里往往不是只有一台机器。多台虚拟机密码失效、批量交接、临时排查这时候一步步点控制台界面很浪费时间。我把“挂载vmdk、改shadow、触发SELinux relabel、恢复权限”这套流程固化成了Python脚本内部代号叫pyvmx-cracker。先明确边界。这个脚本不是暴力破解器也不是“万能钥匙”它做的是在你有合法权限的前提下把密码重置流程自动化。适用场景是本机或工作机可以直接访问vmdk文件典型场景是VMware Workstation。虚拟机已关机。guest是Linux且根分区没有启用整盘加密。为什么不处理vSphere里的虚拟机因为vSphere的vmdk通常在共享存储上宿主机无法直接访问。需要先导出虚拟机或把磁盘映射到可访问的主机再做后续操作。脚本本身不做导出那部分工作按各企业对存储的管理方式自行处理。3.2 完整Python脚本脚本依赖libguestfs。在Ubuntu/Debian上安装sudo apt install libguestfs-tools python3-guestfs在CentOS/RHEL上安装sudo yum install libguestfs-tools python3-libguestfs脚本源码如下保留核心流程可直接保存运行#!/usr/bin/env python3 # -*- coding: utf-8 -*- pyvmx-cracker —— VMware虚拟机Linux密码重置辅助工具 仅用于授权场景下的密码恢复禁止用于未授权虚拟机。 原理通过libguestfs打开vmdk修改/etc/shadow中的密码哈希。 依赖python3、libguestfs-tools、python3-guestfs、openssl import argparse import re import subprocess import sys from pathlib import Path try: import guestfs except ImportError: sys.exit(缺少依赖请安装 python3-guestfs 或 python3-libguestfs) def parse_vmx(vmx_path: Path): 从vmx文件里解析vmdk路径。 pattern re.compile(rfileName\s*\s*([^]\.vmdk), re.IGNORECASE) disks [] with open(vmx_path, r, encodingutf-8, errorsignore) as fh: for line in fh: m pattern.search(line) if m: disks.append(m.group(1)) return disks def vm_running(vmx_path: Path): 通过vmrun检查虚拟机是否在运行。 try: out subprocess.check_output( [vmrun, list], textTrue, stderrsubprocess.DEVNULL ) return str(vmx_path) in out except (subprocess.CalledProcessError, FileNotFoundError): # 没有vmrun时由用户自己保证虚拟机已关机 return False def gen_hash(password: str): 调用openssl生成SHA-512密码哈希。 return subprocess.check_output( [openssl, passwd, -6, password], textTrue, stderrsubprocess.DEVNULL, ).strip() class GuestDiskEditor: def __init__(self, disk: str): self.g guestfs.GuestFS(python_return_dictFalse) self.g.add_drive(disk) self.g.launch() roots self.g.inspect_os() if not roots: raise RuntimeError(无法识别guest操作系统磁盘可能已加密或格式不支持) self.root roots[0] # 挂载根文件系统读取原始shadow作为备份 self.g.mount(self.root, /) self.original_shadow self.g.read_file(/etc/shadow).decode( utf-8, errorsreplace ) def replace_user_password_hash(self, user: str, new_hash: str): lines self.original_shadow.splitlines() for i, line in enumerate(lines): fields line.split(:) if fields[0] user and len(fields) 2: fields[1] new_hash lines[i] :.join(fields) return \n.join(lines) \n raise RuntimeError(fshadow文件中未找到用户 {user}) def set_password(self, user: str, new_hash: str): new_content self.replace_user_password_hash(user, new_hash) # 备份原始shadow self.g.write(/etc/shadow.pyvmx.bak, self.original_shadow.encode()) self.g.chmod(0o640, /etc/shadow.pyvmx.bak) # 写入新shadow并修复权限 self.g.write(/etc/shadow, new_content.encode()) self.g.chmod(0o640, /etc/shadow) # 触发SELinux重新标记 self.g.touch(/.autorelabel) def close(self): try: self.g.umount_all() except RuntimeError: pass self.g.close() def main(): parser argparse.ArgumentParser( descriptionVMware虚拟机Linux密码重置工具仅限授权环境 ) parser.add_argument(--vmx, requiredTrue, help目标虚拟机的.vmx文件路径) parser.add_argument(--password, requiredTrue, help要设置的新密码) parser.add_argument(--user, defaultroot, help要重置密码的用户名默认root) parser.add_argument(--force, actionstore_true, help虚拟机运行中也尝试不推荐) args parser.parse_args() vmx_path Path(args.vmx).resolve() if not vmx_path.exists(): sys.exit(fvmx文件不存在: {vmx_path}) if vm_running(vmx_path) and not args.force: sys.exit(虚拟机正在运行请先关机。强制操作有损坏文件系统的风险。) disks parse_vmx(vmx_path) if not disks: sys.exit(vmx中未找到vmdk磁盘) disk_path Path(disks[0]) if not disk_path.is_absolute(): disk_path vmx_path.parent / disk_path if not disk_path.exists(): sys.exit(fvmdk文件不存在: {disk_path}) print(f[1/3] 打开磁盘 {disk_path}) editor GuestDiskEditor(str(disk_path)) print(f[2/3] 生成新密码哈希) new_hash gen_hash(args.password) print(f[3/3] 修改 /etc/shadow 中的 {args.user} 密码) editor.set_password(args.user, new_hash) editor.close() print(完成。现在可以启动虚拟机使用新密码登录。) if __name__ __main__: main()3.3 运行示例和验证假设虚拟机文件在/opt/vms/centos7/目录下重置root密码为NewPass2024python3 pyvmx-cracker.py --vmx /opt/vms/centos7/centos7.vmx --password NewPass2024正常输出如下[1/3] 打开磁盘 /opt/vms/centos7/centos7.vmdk [2/3] 生成新密码哈希 [3/3] 修改 /etc/shadow 中的 root 密码 完成。现在可以启动虚拟机使用新密码登录。如果系统启用了SELinux虚拟机第一次启动会多花一两分钟做relabel这是正常现象。启动后先用新密码登录一次确认能进系统再回去删除之前拍摄的快照整个操作闭环就完成了。4. 现场实战中的问题和排障记录4.1 改完密码仍登录不进去这是遇到最多的反馈。密码明明改了重启后还是卡在登录界面先不要怀疑脚本改坏了重点检查几件事。第一SELinux上下文。如果重置时忘记创建/.autorelabel标记重启后文件的安全上下文可能处于异常状态表现就是密码正确也进不去或者进去了各种服务报错。解决办法是再次进入单用户模式执行touch /.autorelabel后重启。第二PAM或认证方式限制。有些系统把root登录限制在特定终端或只能通过SSH key登录单纯改/etc/shadow里的哈希并不够。遇到这种情况要看/etc/ssh/sshd_config里的PermitRootLogin、/etc/security下的PAM配置。第三密码特殊字符的键盘布局问题。这个坑很隐蔽。我曾在现场把密码设置成带!和的强密码手工控制台美式键盘没问题用户在自己的中文输入法终端里怎么都打不出来。密码一时半会清不掉最后还是改成数字加大小写字母组合才解决。重置密码时如果面向的是非技术人员建议避免过分依赖特殊字符或者统一在SSH客户端里验证通过后再交接。4.2 libguestfs打不开vmdk脚本报“无法识别guest操作系统”或打开磁盘失败大概率是快照链问题。VMware Workstation里做过多个快照后虚拟机当前使用的不是基础vmdk而是类似xxx-000001.vmdk的增量盘。vmx文件里的fileName指向的通常是当前生效的快照盘但如果你在Workstation里删除过快照磁盘描述符可能指向一条断裂的链。处理方法是先打开虚拟机确认能正常启动然后干净关机。必要时先在Workstation里执行“删除快照”操作把增量盘合并回基础磁盘再运行脚本。还有一种情况是vmdk被转换过格式比如从其他虚拟化平台迁移而来描述符里记录的格式信息有偏差。遇到这种先用qemu-img info看一眼实际格式再人工确认。split类型的vmdk也就是2GB分片那种不需要担心libguestfs认识描述符文件给它指到主vmdk即可。4.3 Windows虚拟机密码怎么处理生产环境里Windows虚拟机密码丢失也很常见思路类似但工具不同。最常用来重置本地管理员密码的方法是用Windows安装ISO启动进入“修复计算机-疑难解答-高级选项-命令提示符”把utilman.exe替换为cmd.exe重启回到登录界面后点“轻松访问”弹出的就是管理员cmd窗口再执行net user 用户名 新密码。这个思路只对未启用BitLocker加密的本地账号有效。如果系统盘做了BitLocker必须先提供恢复密钥解锁磁盘否则所有文件层面的操作都会失败。域控账号认证走的是域控制器重置的是本地SAM数据库没有意义需要走域管理员通道处理。脚本没有覆盖Windows因为libguestfs虽然能识别NTFS文件系统但SAM数据库的解析还需要额外处理注册表结构和系统配置单元复杂度不是同一个量级。Windows场景建议还是走安装ISO方案。4.4 常见问题速查表现象可能原因对策改完密码仍登录失败SELinux relabel未触发单用户模式执行touch /.autorelabel后重启系统提示passwd权限错误/etc/shadow权限异常检查权限为0640属主root:shadowlibguestfs识别失败vmdk是增量快照链合并快照后再试或确认当前生效磁盘文件虚拟机开机提示要密钥虚拟机加密已启用停止重置走密钥恢复流程GRUB编辑后内核崩溃手工改坏启动参数快照回滚换shadow方案5. 写在最后快照、授权与恢复SOP5.1 我习惯的恢复操作顺序密码丢失之后的慌乱是正常的但操作顺序不能乱。我自己固定下来的流程是这样的先确认授权再打快照然后只读探测磁盘确认文件系统正常后写改动启动验证验证通过后删除临时快照最后在工单或文档里记录本次操作的时间、原因和结果。这套流程看着繁琐但它能覆盖绝大多数意外。尤其是“只读探测”这一步我踩过坑之后才养成的习惯。早期我图快脚本打开磁盘直接写有一次文件系统处于不一致状态写进去的shadow数据损坏虚拟机直接起不来。后来改成先以只读方式打开、确认能正常读到文件再进入写流程再也没有出过类似事故。5.2 密码策略与权限边界密码管理是另一件值得投入的事。企业里root密码不应该只存在一个人脑子里。我推荐至少做到三点第一把break-glass密码放在团队共用的密码管理器或Vault里权限单独申请第二每季度从测试虚拟机里抽一台实际走一遍密码恢复流程真出事时不会手忙脚乱第三如果虚拟机模板支持装上cloud-init这类配置注入工具之后密码注入可以直接走模板通道不用再碰宿主机级别操作。再强调一次红线没有授权不碰加密虚拟机不试图绕过操作之前先和负责人确认恢复操作要留痕。这不是场面话而是你我作为从业者必须守住的底线。密码恢复能力是一把工具工具用在对的地方能救命用错地方就是给自己找大麻烦。最后说个个人体会。这个脚本最早不叫pyvmx-cracker刚开始只是几行shell命令后来在使用中逐渐加了vmdk自动定位、shadow备份、权限修复才慢慢成型。真正让我淡定的不是脚本本身而是对启动链路和密码存储机制的理解。理解了原理你就能自己判断该走哪条路以及怎么在出问题时收场。希望这篇分享能帮你把虚拟机密码恢复做成一个可控的运维动作而不是一次心惊胆战的救火。
阅读完成 · 觉得有帮助?
咨询建站