XP补丁包制作技术详解
在别的地方偶然发现了这个帖子,觉得写的不错,特此转过来与大家分享。一 QFE 以及相关介绍
QFE
Quick-Fix Engineering (QFE)
厂商(比如微软)为了及时能或者升级功修改缺陷而做的改动(支持)叫做QFEs.
我们平时为 Windows XP 安装补丁的时候,经常会看到补丁中出现 GDR 或 QFE 等字样,它们表示什么意思呢?原来微软已经为补丁中的更新系统文件划分了级别,其中 GDR 表示“普通分发版本”,而 QEF 则表示“快速修补工程更新版本”,其中 GDR 更新文件一般都进行了大量的严格测试,因此补丁的稳定性相对较高;而 QFE 更新文件一般所做的测试相对较少,因此其稳定性普遍不如 GDR。
由于更新文件划分了级别,因此 Windows 补丁也划分为两类:一类称为“安全修补程序”,这类补丁包同时包含 GDR 和 QEF 版本的更新文件,也就是两个副本,一般在 Windows 被发现严重漏洞时发布关键更新使用;第二类称为“修复程序”,一般都是一些非关键性更新,仅包含 QFE 版本的更新文件。
那么为什么“安全修补程序”要包含两种更新文件的版本呢?比如说我们现在要安装一个仅包含 QFE 版文件的非关键性更新。如果这个补丁需要更新的旧系统文件已经是 GDR 版,这时更新程序就会自动对比新旧文件的版本号。假如原先的 GDR 文件版本比补丁包中的 QEF 文件版本还要高,那么就会自动禁止补丁包中的 QFE 文件进行更新,而会改用和原 GDR文件版本号相同的 QEF 版文件来更新。那么上哪里去找这个和原 GDR 文件版本号相同的 QFE 文件呢?实际这个文件已经在计算机硬盘里了,因为在上一次安装包含这个 GDR 文件的“安全修补程序”时,已经将同版本的 QFE 也复制到了系统中备用。这就是为什么“安全修补程序”要同时包含 GDR 和 QFE 两个副本的原因。
再举一个例子,比如说我们现在要安装 KB896688 补丁,此补丁需要更新系统文件 %SystemRoot%\system32\MSHTML.DLL。由于 KB89668 补丁是一个“安全修补程序”,因此它同时包含 GDR 版和 QEF 版两个版本的 MSHTML.DLL 副本,它们的文件说明分别为“xpsp_sp2_gdr.051004-1415”和“xpsp.051004-1419”。执行更新程序后,安装程序会自动检测当前系统的 MSHTML.DLL 版本,如果发现原来的文件就是 GDR 版,那么就会用补丁包中的 GDR 版来更新;如果发现原来的文件是 QEF 版,则会用补丁包中的 QFE 版来更新。不论是哪种情况,更新完毕后,新的系统文件都将是更新后的 6.00.2900.2769 新版本号,只不过有 GDR 和 QFE (Quick fix engineering) 之分而已。
现在,我们再用 KB896688 的例子回过头说一说刚才提到的第一个例子。假设我们更新 KB896688 补丁之前,原系统文件 MSHTML.DLL 已经是 GDR 版,那么在更新补丁时,就会用 GDR 版的 xpsp_sp2_gdr.051004-1415 版的 MSHTML.DLL 进行更新。与此同时,更新程序会将那个 xpsp.051004-1419 的 QEF 文件复制到硬盘中,具体位置是 Windows 文件夹下的 $hf_mig$ 子文件夹。假设我们日后需要安装一个也需要修改 MSHTML.DLL 的其它非关键性补丁,这个补丁就会自动检测自己提供的 QEF 文件和 xpsp_sp2_gdr.051004-1415 相比哪个版本高。假如自己提供的 QEF 版本还不如 xpsp_sp2_gdr.051004-1415 版本高的话,就不会用自己的 QFE 文件进行更新,而是会从 Windows\$hf_mig$ 里把那个备用的 xpsp.051004-1419 拿出来,进行更新。
记得在新闻组中曾经有人问起 Windows\$hf_mig$ 文件夹是否可以删除的问题。现在经过上面的说明解释后就应该明白了,最好不要随便删除 Windows\$hf_mig$ 文件夹。删除此文件夹虽然不会引起系统立即崩溃,但是一旦出现上面所说的那种情况,就可能会发生安装新补丁后引起系统文件版本不匹配导致的兼容性问题。所以,不要轻易删除 Windows\$hf_mig$ 文件夹。
二 QFE补丁的提取
(1)以KB924270为例,当下载了补丁WindowsXP-KB924270-x86-CHS.exe之后,先建一个KB924270的目录,然后双击WindowsXP-KB924270-x86-CHS.exe
(2) 接下来,我们可以看到安装界面,同时它会自动释放产生一个临时文件夹 ,一般这个文件夹在某个分区的根目录下下,暂时不要点击安装,进入这个临时目录
(3)把这个临时目录下F:\3d73b4f6c3a91de6574d3c4b5d94\的SP2QFE与update目录复制到我们新建的KB924270目录
(3)进入KB924270\update目录,删除update_SP2GDR.inf以及update_SP1QFE.inf,这里是指所有文件名包括DGR.INF与SP1QFE名称的文件
这样你就得到了提取的QFE补丁
这里再简绍另一钟方法,跟刚才一样,你双击这个补丁WindowsXP-KB924270-x86-CHS.exe,按默认进行安装,安装完毕以后,去掉系统文件夹不显示隐藏文件夹属性,你进入到C:\WINDOWS\$hf_mig$目录,然后复制KB924270目录到补丁包目录,再删除KB924270目录下的其他文件,保留SP2QFE与UPDATE文件夹,接下来删除UPDATE里的包括SP1与QDR.INF的所有文件,这样,你的补丁包也提取成功了!
三 QFE补丁的安装
接上文,所有的QFE补丁安装都可以用update来安装,你进入到KB924270\update目录,双击update,出面的界面同你双击WindowsXP-KB924270-x86-CHS.exe出面的安装界面是一样的,静默安装参数也一样,update/? 所有的参数都会列表出来,当然我们这里应该进行的静默安装,那么,可以使用批处理 KB933729\update\update.exe /q /n /z 进行静默安装!
但是这里我们说的是QFE节点安装技术,这个参数在update/?是没有列表出来的,微软也只在其MSDN技术资料中初略涉及...
我就长话短说,加个参数吧 KB933729\update\update.exe /q /n /z /b:SP2QFE 这样update就会调整用update_SP2QFE.inf进行快速检测并安装补丁!!
你会发现,用这种方法集成的补丁方法在速度上,产生的系统拉圾文件上有无可比批的优势!
四 QFE补丁包中的安装程序(批处理)的制作
当提取完所有的补丁后,将他们集中在一个文件夹,这里以patch为例,其目录下包含了kb*****的补丁包目录,接下来我们就是采用NSIS来写个安装脚本了,我这里的比较简单,先检测补丁是否安装,安装好了就跳过,没有安装的话就安装
ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\HotFix\KB941202" "Comments"
IfErrors 0 +2
goto +3
DetailPrint 'KB941202 这个升级补丁已经打好了,本次跳过'
goto +8
ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Updates\Windows XP\SP3\KB941202" "type"
IfErrors 0 +2
goto +3
DetailPrint 'KB941202 这个升级补丁已经打好了,本次跳过'
goto +3
DetailPrint 'KB941202 升级补丁没有安装,正在安装'
ExecWait '"$EXEDIR\KB941202\update\update.exe" /q /n /z /b:SP2QFE'
所有的补丁我都是用这个语句来替换检测的,那位高人再写个高点的循环语句来帮下忙吧,NSIS的循坏语句偶实在不在行!!!!!
至于其他的NSIS安装界面的安装结束页面定义什么的偶这里就不献丑了!
至于用CMD批处理的话,偶这里提供下CCF-MAULO提脚本
@echo off
echo 正在检测 Windows XP 更新,请稍候...
qfecheck | findstr /i /c:"Current on system." >list.txt
echo 已安装>temp0.txt
if exist .\temp.txt del /f /q temp.txt
for /F "tokens=1 delims=:" %%i in (list.txt) do (echo Windows XP 更新 %%i 已安装 & echo %%i>>temp0.txt)
findstr /V /i /B /G:temp0.txt setup.txt>temp.txt
for /f "tokens=1 delims=-" %%i in (temp.txt) do echo Windows XP 更新 %%i 还未安装或安装不正确
echo 接下来将安装还未安装的 Windows XP 更新
for /f "tokens=1,2,3 delims=-" %%i in (temp.txt) do @(@echo 安装 Windows XP 更新 %%i && @start /wait .\%%i\%%j)
regedit /s mrt.reg
EXIT
注1:qfecheck是用来检测补丁是否已安装的小工具,具体的语句什么的,偶就不分析了!
注2:补丁包安装是有顺序的,不然的话会造成系统不稳定,这点许多论坛提供的补丁包都没有详细分析,我这里参考maulo的安装顺序,帖一下
KB893803v2|KB898461|KB941202|KB939653|KB923689|KB933729|KB936781|KB936782|
KB938829|KB938828|KB938127|KB936021|KB921503|KB923689|KB929123|KB935840|
KB935839|KB930916|KB930178|KB931261|KB931784|KB932168|KB925902|KB918118|
KB924667|KB926436|KB927779|KB927802|KB928255|KB928843|KB931836|KB926255|
KB924270|KB923980|KB923414|KB923191|KB922819|KB922582|KB920872|KB920685|
KB920683|KB920670|KB920213|KB919007|KB918439|KB917953|KB917344|KB916595|
KB914389|KB914388|KB913580|KB911927|kb911562|KB911280|KB910437|kb908531|
KB908519|KB905749|KB905414|KB904706|KB902400|KB901214|KB901190|KB901017|
KB900725|kb900485|KB899591|KB899587|KB896428|KB896423|KB896358|KB893756|
KB891781|KB890859|KB888302|KB886677|KB886185|KB885836|KB873339|
KB893803v2|KB898461|KB941202|KB939653|KB923689|KB933729|KB936781|KB936782|
KB938829|KB938828|KB938127|KB936021|KB921503|KB923689|KB929123|KB935840|
KB935839|KB930916|KB930178|KB931261|KB931784|KB932168|KB925902|KB918118|
KB924667|KB926436|KB927779|KB927802|KB928255|KB928843|KB931836|KB926255|
KB924270|KB923980|KB923414|KB923191|KB922819|KB922582|KB920872|KB920685|
KB920683|KB920670|KB920213|KB919007|KB918439|KB917953|KB917344|KB916595|
KB914389|KB914388|KB913580|KB911927|kb911562|KB911280|KB910437|kb908531|
KB908519|KB905749|KB905414|KB904706|KB902400|KB901214|KB901190|KB901017|
KB900725|kb900485|KB899591|KB899587|KB896428|KB896423|KB896358|KB893756|
KB891781|KB890859|KB888302|KB886677|KB886185|KB885836|KB873339|
五 QFE补丁包的打包
做好了上面的步骤之后,大伙可以发现,收集的KB*****文件夹中的大小达到了恐怖的187MB,汗,不过仔细分析可以发现,许多KB*****\update目录中有许多文件是一样的,虽然日期不同,但是内容却一样,这里简单列表一下
branches.inf------------------- 1KB
update.exe---------------------616KB
eula.txt---------------------------3KB
spcustom.dll-------------------21KB
其 实我们可以再压缩一下,eula.txt实际上没有用的,静默安装的话根本不会出现,所以可以把里面的文件清空(其实没多在必要)
这一看没有多少,也就640KB,但是数十个目录的话,就显得恐怖许多啦,所以,这里可以使用7-ZIP的共享压缩技术,为了在压缩的时候顺利通过CRC校验,呵呵,把所有的补丁包的上面列表文件都覆盖吧!
接下来就简单了,下载最新版本的7-ZIP压缩工具,选中所有的文件,然后右键,采用7-ZIP压缩,在出现的界面中,要注意几点,一,压缩算法采用LZMA,压缩级别选择极限压缩,并在压缩共享文件选项中打上勾.然后点确定吧!!!!.....................看到了没,呵呵,压缩得结果是不是很爽啊,我这里是33MB......(其实msxml.msi我也想去掉的,这样就又少了5MB,可惜最好是不能去掉)
下面的就是用7-zip的自解压模块进行打包了,具体的我不说了,提供一下我自已的脚本
config.txt
;!@Install@!UTF-8!
Title="大家园丁茶坊学生机系统V3.9升级补丁"
BeginPrompt="您确认要升级 大家园丁茶坊学生机V3.9 吗?"
RunProgram="setup.exe /T:%%T"
;!@InstallEnd@!
patch.bat
;!@Install@!UTF-8!
Title="╃赢政天下- 我最迷人WindowsxpSP2补丁集(更新之20071019)"
BeginPrompt=" 您确认要开始打WindowsXP SP2的补丁吗?"
RunProgram="setup.exe /T:%%T"
;!@InstallEnd@!
七 附录1 MAULO 本地补丁制作方法
这里来说一下具体的制作步骤,并列上批处理脚本,方便大家其它Windows 版本本地补丁包制作。这样制作的好处是安装快速,也方便后期加工,因为这些都是已解压的。本人在批处理上是门外汉,都是现学现用、现学现查写出来的,可能还不够精练,大家可以一起来讨论。这里以Windows server 2003 with sp1 为例进行说明。
1、安装全新原版Win 2003 sp1,建议在VM虚拟机中安装。
2、安装后马上关闭自动更新。安装好VM tools,以方便与宿主机的文件共享。联网并进行手动更新。
3、在更新已下载完毕并开始安装时,可以进行本地补丁安装源的备份了,在宿主机的E:盘下建立一个HOTFIX目录,再在这个目录下并列建立temp目录(为了与下面的脚本对应起来,建议这样建立,如果自己要改,下面的脚本中也要进行相应修改)。进入虚拟机系统盘的WINDOWS\SoftwareDistribution\Download目录下将所有的目录选定,并将它们拖动到宿主机的E:\HOTFIX\temp目录中,这时就会在双机之间进行文件复制。此外Download目录下还有几个没有扩展名的文件,其中一个5M多的为Windows Malicious Software Removal Tool,可以不去管它,而一个500多K的为KB922582的安装程序,加上exe扩展名并点击运行,不要点下一步进行安装,进入到C:或D:的根目录下,可以发现增加了一个如1091d42eb9e9e3da45这样的文件夹,将这个文件夹也拖到宿主机的E:\HOTFIX\temp目录中进行备份,这样应该说大部分的高优先的补丁都已备份齐了。说明一下,如果在虚拟机中复制这个文件夹,将会被阻止,而在虚拟机与宿主机之间进行复制就没有这个问题。
4、在宿主机的E:\HOTFIX\temp目录中建立一个批处理文件如autodo.cmd,内容如下:
代码:
del .\_file_to_execute_.txt /f/s/q/a
del .\_*.state /f/s/q/a
del .\$shtdwn$.req /f/s/q/a
del .\susdl.rq0 /f/s/q/a
del .\Windows*.psm /f/s/q/a
del .\update.url /f/s/q/a
dir /a:d /s /a /b | findstr /i /c:"update\KB" >list.txt
for /F "tokens=4 delims=\" %%i in (list.txt) do rd /S /Q %%i\backup
md ..\updates
for /F "tokens=4,6 delims=\." %%i in (list.txt) do move /y .\%%i ..\updates\%%j
dir ..\updates /a:d /s /a /b | findstr /i /c:"update\update.exe" >..\updates\setup.cmd运行这个批处理,最后会在e:\hotfix\updates\下得到了一个安装脚本setup.cmd,不过这个只能进行手动安装,要实现自动安装,可以将setup.cmd中的update.exe 替换成update.exe /q /n /z就可以了,另外将每行的"e:\hotfix\updates\"替换成".\",方便移动到其它地方安装。
至止本地安装源已其本制作完成了,不过这样的体积还比较大。后续可以进行分离和压缩,就可得到体积比较小的安装包了
八 附录2 QFE补丁批量提取方法
这是今天研究出来的,更新一下
第一 得到所有的补丁文件名
(1)下载完所有的补丁,保存在一个文件夹下,这里可以这样子做,解压缩雨林木风的补丁包,这样子我们就得到所有的单独补丁文件
(2)写批处理,第一步,提取所有的文件名到一个文件中
@echo off
dir /b |findstr /i "KB" >hotfix.txt
意义为列表所有的文件名中包含KB两个字符的文件名到hotfix.txt中,kb是忽略大小写的
这样我们在hotfix.txt中就得到了当前目录下所有补丁文件的名称
第二 提取所有的补丁到KB******目录
kb*****我们的目的和要求就是让计算机自动帮我们提取补丁中的目录和文件
补丁自动提取的参数是 kb***.exe /x:.\kb***
我们可以用以下批处理命令来完成
setlocal EnableDelayedExpansion
for /f "delims=" %%a in (hotfix.txt) do (
set var=%%a
set var=!var:kb=#!
set var=!var:*#=!
for /f "tokens=1 delims=-." %%b in ("!var!") do (
@echo 正在提取Windows_XP_Sp2_QFE 更新 kb%%b ,请稍等 && @%%a /x:.\kb%%b /q
)
上面这段bat代码特别感谢junchen2,lxmxn,26933062,slore,zerocq,fastslz等朋友们的指点
第三 提取QFE补丁安装所需要的文件
当目录提取出来之后,我们可以发现,KB******目录中包含了很多的目录,其中有许多我们不想要的,如何让计算机自动帮我们提取我们想要的文件呢?其中的sp2gdr,sp1qfe目录都是用不到的
通过分析我们可以发现,QFE节点安装方式只需要KB******目录中的两个目录update和sp2qfe目录
我们可以通过以下代码来让计算机自动帮我们完成这项工作
md .\kb%%b_backup
move .\kb%%b\update .\kb%%b
move .\kb%%b\sp2qfe .\kb%%b
rd .\kb%%b /s /q
ren kb%%b_backup kb%%b
这样我们就初步得到了kb******目录中QFE安装方式所需要的文件夹
接下来我们还要再精简一下,删除sp2qfe目录的sp1qfe.inf和sp2gdr.inf
通过以下代码可以完成
if exist qfe_bak_kb%%b\update\update_SP1QFE.inf del qfe_bak_kb%%b\update\update_SP1QFE.inf /q
if exist qfe_bak_kb%%b\update\update_SP2GDR.inf del qfe_bak_kb%%b\update\update_SP1GDR.inf /q
if exist qfe_bak_kb%%b\update\update_SP2GDR.inf del qfe_bak_kb%%b\update\update_SP2GDR.inf /q
这样我们就得到了QFE补丁的安装文件
参考:以下是我编写的完整批处理文件,不当之处请多多指正!
qfe_start.cmd
@echo off
dir /b |findstr /i "KB" >hotfix.txt
setlocal EnableDelayedExpansion
for /f "delims=" %%a in (hotfix.txt) do (
set var=%%a
set var=!var:kb=#!
set var=!var:*#=!
for /f "tokens=1 delims=-." %%b in ("!var!") do (
if exist kb%%b @echo -更新kb%%b已经提取,现在提取同名更新 KB%%b_2 ,请您手工分析...... && @%%a /x:.\kb%%b_2 /q
if not exist kb%%b @echo -正在提取Windows_XP_Sp2_CHS_QFE 更新 KB%%b ,请稍等 ...... && @%%a /x:.\qfe_bak_kb%%b /q
if not exist kb%%b md .\KB%%b
if exist qfe_bak_kb%%b move .\qfe_bak_kb%%b\update .\kb%%b
if exist qfe_bak_kb%%b move .\qfe_bak_kb%%b\sp2qfe .\kb%%b
if exist qfe_bak_kb%%b rd .\qfe_bak_kb%%b /s /q
if exist KB%%b\update\*SP1QFE.inf del kb%%b\update\*SP1QFE.inf /q
if exist KB%%b\update\*GDR.inf del kb%%b\update\*GDR.inf /q
echo -WindowsXP-KB%%b 的QFE更新部分已提取完成!
echo -
echo -
)
)
del hotfix.txt /q
cls
echo -
echo -
echo -
echo ------------------------------------------------------------------
echo -windows_XP_Sp2_QFE 补丁集已全部提取并制作完成! 请按任意键退出
echo -
echo -本补丁脚本编写制作:清风无影 2007.10.21
echo -http://bbs.winzheng.com
echo -http://bbs.ydxz.cn
echo ------------------------------------------------------------------
pause
qfe_start.rar
附录8 关于如何再精简补丁包体积的问题
同理,利用7Z的共享压缩原理,如果文件同名,CRC相同,就会只压缩一份
所以,把所有目录下的update.exe,spcustom.dll,updspapi.dll都采用最新的版本提供的文件!
用copy命令可以很容易实现
另外,所有update目录下的eula.txt,branches.inf由于是采用/q/n/z静默安装都是用不到的,所以也可以全部删除,可以用del或查找能容易实现.
最后,由于补丁包里有很多文件实际上由于更新时间的差异,但文件都是一样的,所以可以用新的代替旧的,这个可以用replace来实现!!
下面我提供一下脚本,这个可以放在补丁集目录下执行!
echo 请将本脚本放在QFE补丁集目录下执行
pause
md ..\source
copy kb943460\update\update.exe .\
copy kb943460\update\spcustom.dll .\
copy kb943460\update\updspapi.dll .\
dir /b /o-d |findstr /i "KB" >hotfix.txt
setlocal EnableDelayedExpansion
for /f "delims=" %%a in (hotfix.txt) do (
copy spcustom.dll %%a\update /y
copy update.exe %%a\update /y
copy updspapi.dll %%a\update /y
del %%a\update\eula.txt /q
del %%a\update\branches.inf /q
copy %%a\sp2qfe\*.*..\source
)
replace ..\source\*.* ..\qfe /s /u
del ..\source\*.* /q
rd ..\source /s /q
del .\hotfix.txt /q
del .\update.exe /q
del .\updspapi.dll /q
del .\spcustom.dll /q
echo QFE体积瘦身行为已经完成
pause 有这么麻烦吗?,我都直接用NLITE压缩进去,很方便的
页:
[1]