开篇废话
使用前请确认: AC 连接 + 电池有电 Bitlocker off 万一砖了……不关我的事
最近有个单是给笔记本批量重装系统,也就是简单初始化,大部分东西都通过无人值守+奇怪脚本解决了,
但是 BIOS 更新并不会通过 WSUS 来推送没,至少机器到我手上的时候没收到过 BIOS 的更新,不想某个 L / D 开机就给你更 BIOS 了。
所以研究了下 BIOS 更新部分有没有静默安装的参数,凭我的直觉是有的,于是就有这篇文章了。
当然本文太水了,所以有个 #额外 部分可以看看,然后笑话我(
命令
首先 VAIO 找到对应的最新 bios 下载包,这个教程里面的是这一款:
https://solutions.vaio.com/6403
创建快捷方式增加 /VPM_NonInteractive 静默参数:
SP000847.exe /VPM_NonInteractive
或者 cmd:
start "" /wait "SP000847.exe" /VPM_NonInteractive
然后如果需要更新的情况下,大概等待个2分钟左右,就会自动重启系统进行 BIOS 自动更新了。
运行起来的话是只有 UAC 窗口的,剩下的都是静默状态,如果是直接打开 exe 的话需要点2-3个弹窗然后 start ,因此很方便进行系统封装后自动执行的命令。 最简单的就是放在开始菜单的启动目录,当然 UAC 的问题需要手动点确认,所以可以考虑放在 oobe 进桌面时执行?具体我没研究了。
正文
当然这个要讲一下怎么找到的静默参数了,全网是没有任何这个参数的介绍的,当然主要是 VAIO 只在日本有,其解决方案基本上也是私密的(猜测)
本来想拆包然后找到 bios 直接更新的,但是 7-zip / winrar 没有什么想法,然后跑了 binwalk 也没有看到藏了什么文件:
❯ binwalk SP000847.exe
/Users/h/Downloads/SP000847.exe
--------------------------------------------------------------------------------
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
2845781 0x2B6C55 Windows
PE
binary,
machine
type:
Intel
x86-64
--------------------------------------------------------------------------------
Analyzed 1 file for 85 file signatures (187 magic patterns) in 102.0 milliseconds
于是就 g 了,接下来我直接把文件塞到了 Ghidra ,众所周知,Windows PE 的程序的启动参数基本是 / 开头的,于是一眼就看到了非常像的参数了:

看上去就一个 /VPM_NonInteractive 是可以接受传入的,看上去名字也很像静默执行的感觉(NonInteractive)。
所以我就直接执行了,然后过几分钟 pc 就重启进行一个更新 BIOS 操作了,除了 UAC 以外没有任何需要交互的操作。
附上伪代码:
/* WARNING: Function: __security_check_cookie replaced with injection: security_check_cookie */
bool FUN_1400059d0(longlong param_1,longlong *param_2)
{
int *piVar1;
wchar_t *pwVar2;
wchar_t *pwVar3;
wchar_t wVar4;
uint uVar5;
longlong *plVar6;
longlong lVar7;
size_t sVar8;
size_t sVar9;
ulonglong uVar10;
wchar_t *pwVar11;
uint uVar12;
int iVar13;
ulonglong uVar14;
bool bVar15;
undefined1 auStack_308 [32];
undefined4 local_2e8;
undefined8 local_2e0;
wchar_t *local_2d8;
longlong local_2d0;
longlong local_2c8;
longlong local_2c0;
undefined1 local_2b8 [64];
undefined8 local_278;
ulonglong local_48;
ulonglong local_38;
local_38 = DAT_14027f930 ^ (ulonglong)auStack_308;
uVar10 = 0;
local_2c8 = param_1;
plVar6 = (longlong *)FUN_140022698();
if (plVar6 == (longlong *)0x0) {
/* WARNING: Subroutine does not return */
FUN_140004cc0(0x80004005);
}
lVar7 = (**(code **)(*plVar6 + 0x18))(plVar6);
pwVar11 = (wchar_t *)(lVar7 + 0x18);
uVar12 = 0xffffffff;
uVar14 = uVar10;
local_2d8 = pwVar11;
do {
lVar7 = *param_2;
pwVar2 = (wchar_t *)(lVar7 + uVar14 * 2);
pwVar3 = (wchar_t *)(lVar7 + (longlong)*(int *)(lVar7 + -0x10) * 2);
if (pwVar2 < pwVar3) {
sVar8 = wcsspn(pwVar2,L" ");
if (pwVar3 <= pwVar2 + (int)sVar8) goto LAB_140005aa4;
sVar9 = wcscspn(pwVar2 + (int)sVar8,L" ");
iVar13 = (int)sVar8 + (int)uVar14;
FUN_140006480(param_2,&local_2d0,iVar13,sVar9 & 0xffffffff);
uVar5 = iVar13 + 1 + (int)sVar9;
}
else {
LAB_140005aa4:
if ((*(longlong **)(*param_2 + -0x18) == (longlong *)0x0) ||
(plVar6 = (longlong *)(**(code **)(**(longlong **)(*param_2 + -0x18) + 0x20))(),
plVar6 == (longlong *)0x0)) {
plVar6 = (longlong *)FUN_140022698();
plVar6 = (longlong *)(**(code **)(*plVar6 + 0x20))(plVar6);
if (plVar6 == (longlong *)0x0) {
/* WARNING: Subroutine does not return */
FUN_140004cc0(0x80004005);
}
}
local_2d0 = (**(code **)(*plVar6 + 0x18))();
local_2d0 = local_2d0 + 0x18;
uVar5 = uVar12;
}
lVar7 = local_2d0;
uVar14 = (ulonglong)uVar5;
pwVar2 = pwVar11 + -0xc;
if ((wchar_t *)(local_2d0 + -0x18) != pwVar2) {
if ((*(int *)(pwVar11 + -4) < 0) || (*(longlong *)(local_2d0 + -0x18) != *(longlong *)pwVar2))
{
FUN_140004ce0(&local_2d8,local_2d0,*(undefined4 *)(local_2d0 + -0x10));
pwVar11 = local_2d8;
}
else {
lVar7 = FUN_140004630();
LOCK();
pwVar11 = pwVar11 + -4;
iVar13 = *(int *)pwVar11;
*(int *)pwVar11 = *(int *)pwVar11 + -1;
UNLOCK();
if (iVar13 < 2) {
(**(code **)(**(longlong **)pwVar2 + 8))(*(longlong **)pwVar2,pwVar2);
}
local_2d8 = (wchar_t *)(lVar7 + 0x18);
pwVar11 = local_2d8;
lVar7 = local_2d0;
}
}
wVar4 = *pwVar11;
LOCK();
piVar1 = (int *)(lVar7 + -8);
iVar13 = *piVar1;
*piVar1 = *piVar1 + -1;
UNLOCK();
if (iVar13 < 2) {
(**(code **)(**(longlong **)(lVar7 + -0x18) + 8))();
}
if (wVar4 == L'\0') {
bVar15 = false;
pwVar11 = local_2d8;
goto LAB_140005cb8;
}
FUN_140005f80(&local_2d8);
pwVar11 = local_2d8;
iVar13 = FID_conflict:_wcsicoll(local_2d8,L"/VPM_NonInteractive");
if (iVar13 == 0) {
if ((-1 < *(int *)(*param_2 + -0x10)) &&
(lVar7 = FUN_1401bb6b4(*param_2,L"/VPM_NonInteractive"), lVar7 != 0)) {
uVar12 = (uint)(lVar7 - *param_2 >> 1);
}
FUN_140006370(param_2,uVar12,0x13);
FUN_1400155a0(local_2b8);
local_2c0 = FUN_1401b7e10(0xb8,&PTR_14023bdc0);
if (local_2c0 != 0) {
uVar10 = FUN_140007aa0(local_2c0,local_278);
}
local_48 = uVar10;
if (uVar10 != 0) {
local_2e0 = 0;
local_2e8 = 4;
lVar7 = FUN_1400292d4(FUN_140012910,uVar10,0,0);
*(longlong *)(uVar10 + 0x60) = lVar7;
if (lVar7 != 0) {
*(undefined4 *)(lVar7 + 0x50) = 0;
ResumeThread(*(HANDLE *)(*(longlong *)(uVar10 + 0x60) + 0x58));
}
}
lVar7 = local_2c8;
iVar13 = *(int *)(local_2c8 + 0x1b4);
while (iVar13 == 0) {
Sleep(2000);
iVar13 = *(int *)(lVar7 + 0x1b4);
}
iVar13 = *(int *)(lVar7 + 0x1b0);
FUN_1400056a0(local_2b8);
bVar15 = iVar13 == 0;
LAB_140005cb8:
LOCK();
pwVar2 = pwVar11 + -4;
iVar13 = *(int *)pwVar2;
*(int *)pwVar2 = *(int *)pwVar2 + -1;
UNLOCK();
if (iVar13 < 2) {
(**(code **)(**(longlong **)(pwVar11 + -0xc) + 8))();
}
return bVar15;
}
if ((int)uVar5 < 0) {
/* WARNING: Subroutine does not return */
FUN_140004cc0(0x80070057);
}
} while( true );
}
额外
其实这次接的单最后是以我离开现场、系统全部重做为结局。对同事以及因此被拖延的工期还是挺抱歉的。
先介绍简单背景:
对面公司拿出了好几页的纸质的手顺让我们全部手工安装,于是总结了下步骤写成了 batch 简化下实际操作,想着偷下懒,也顺便给同事减轻一点负担。
到了第二阶段,有些软件安装不太顺利。我稍微调查了一下,判断是软件自身的问题,只要放在那里等自动更新即可解决。
但是客户完全不理睬我的意见以及解释,我当时又有点 KY(空気読めない)地多提醒了几次,甚至软件厂商的 KB 都给客户看了,提示的度,也就是 KY 程度对于我来说还是很难掌控的,然后可能在其他方面总之应该是认为我在顶嘴,违反流程还是什么的,让客户感觉到了不安。
最后在客户又在演示重装那个有问题的软件,但是还是失败了2次后,我再次提示了下,然后过了一会让我马上滚蛋了,说我不按照 manual 来操作。
后面的事情就更戏剧化了,有个同事把我们用批处理跑的事暴露了,于是我罪上加罪,很自然地就成了这个项目延期的主要责任人。
不过让我滚了也好,把火力矛头都对向我了后,那么对剩下在现场的同事大概就会温柔许多了。
当然还是我的问题。如果一开始就老老实实按照文档操作,大概也不会出什么问题,何必多此一举呢。只是出于一点技术上的追求,还是不自觉地偏离了客户要求的轨道。
现在回想起来,当客户都能给出 N 页流程纸让我们手填了,其实就已经说明这不会是一个轻松的项目。不过公司第一次接这种活也没有经验,按照业界最低价格就接了。
实际上我本身也不太擅长和这种客户沟通。事情很多、细节很多,如果多确认点的话一天又过去了。
但甲方终究是甲方,甚至有些有歧义的问题我都是通过同事帮忙发邮件去确认的。
而且说实话,在我看来那 N 页流程纸本身几乎没有什么实质性的指导意义。
写了那么多步骤,却连最基本的系统母盘用什么 iso 都没有说明。
严格来说,我甚至可以装一个 Windows 21H2,让大家怀旧一下,也依然完全符合这份流程。
当然,对我来说这次算是一个很深刻的教训。
对于这种 流程驱动、事件主导 的公司来说,一旦已经形成了非常详细而僵化的操作流程,那么效率往往就不是优先考虑的事情。
而这种环境,大概也确实不太适合我这种习惯优先考虑效率的人。
毕竟也正是因为流程已经固化到这种程度,这样简单的 PC 初始化工作才会被外包出来。 在很多公司内部,这类事情其实很容易消化。通过无人值守部署(稍微查一下微软文档就能生成的 unattend.xml 和组策略),一个人同时处理几十台机器并不是什么困难的事情。如果机器数量再多一点,甚至可以直接使用 PXE 网络安装方案。
而在这里,却是由明显不太理解部署流程的人写出一份手顺,再让技术人员逐条执行。
对我来说,这种体验多少有些奇怪。
直到让我滚蛋,我才意识到这种模式下,其实对于操作者来说,我是没有任何裁量权的。或者再简单点说,就是我无脑执行,出错了就应该直接推锅,而不是在这里研究解决方案去顶嘴。
本质上,这其实是技术逻辑和流程需求之间的冲突。当一个明显缺乏技术意义的流程被要求逐条执行时,对技术人员来说多少会有一种违背专业判断的感觉,说得再简单点就是被侮辱了。
总之还是很忧愁的,因为我的技术能力在这次案件里面如果这样就完全派不上用场了,对双方都不友好,对面只是要求听话的稍微会点电脑的打工仔而已,我这么上心干什么。
说了那么多,感觉最优解就是尽量不要再接这种 技术含量接近 0、又完全事件驱动型 的项目。
期间最离谱的是找了个借口说我在系统里面放了特制的病毒,这个病毒不会让系统无法启动,而是会专门破坏用来安装系统的 U 盘,据说已经坏掉了好几块。
把本来还在郁闷着的我整乐了,大家都是个技术者,破坏u盘在说什么天方夜谭吗。
找个好点的理由或者没有理由直接来要我也会给的啊!
不过借着这个理由,对方顺便把我的初始化部署脚本就这样要了过去。
没想到在 2026 年还能碰到这种级别的阴谋论式的 PUA,一边甩锅,一边顺手把脚本拿走。
* 我还是想学下隔空毁坏u盘的技术,毕竟在我的认知里面只有希沃白板的断头台才能做到物理毁坏U盘:

不过再想想也释然了,客户在 Google maps 的风评其实是很微妙的,也符合目前接触的画风,
如果不用这种流程驱动型的文件来维护权威,那么这种会社无法存活下去。
最后,在我心目中 夢グループ 在我心中的地位还在上升,原来石田社长已经非常善良了。
总结
大家都是程序员,很多习惯其实都是共通的。为了方便调试或部署,一些隐藏参数被嵌入程序里其实是很常见的,也算是约定俗成的做法。
不过很多时候这些参数并不会在文档或其他地方标明,但通常还是可以通过反编译等手段把它们找出来。
(当然本文其实没有做到这一步,只是通过简单的字符串匹配就找到了静默运行的参数)。
想起了我博客的第一篇文章了~~(Hello World 是不算的)~~:
在 macOS 10.15 以上 刷入 IPCC 文件 / On macOS 10.15 or later enable carrier-testing
博客的起点 = = 扒程序的隐藏逻辑,怀念高中的时候了。
完