书接前文 回到之前说过的manifest文件
https://blog.vrqq.org/archives/779/
- manifest文件能用link.exe写入,还可以后天修改(推荐后天mt.exe方式)
- 微软建议 每个manifest仅和单个文件关联(当然也可以关联多个)
- Please Know that before used, this is an undocumented feature.
给exe的manifest加参数 完整manifest如下
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="myprogram.quick.start"
version="20.20.20.20" processorArchitecture="x86" />
<file name="ffmpeg.dll" loadFrom="C:\TheOtherPath\ffmpeg_other_name.dll"></file>
</assembly>
- 选用ApplicationManifest https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests
<file>
: addloadFrom
property, https://localcoder.org/dll-redirection-using-manifestsloadFrom
可以填诸如%windir%\System32\kernel32.dll
但注意,若System32下的dll未经签名("签名"见后文) 即使文件存在 也会在运行时提示"找不到文件"- 活用这个参数,可以把程序目录整的干净点,尤其依赖很多时
- read command usage example below
签名、验签、版本号、和dll依赖
dll依赖
- 假设上文文件名为app2.manifest
- 验证写的对不对
mt.exe -manifest app2.manifest -validate_manifest
- 将app2.manifest挂入exe
mt.exe -outputresource:"myapp.exe";#1 -manifest app2.manifest
- 查看挂好的文件: VS打开文件夹,然后双击exe文件,右侧会出一个目录树,在
RT_MANIFEST
里 - 从exe导出manifest文件
mt.exe -inputresource:"myapp.exe";#1 -out:app2.manifest
- 增量更新
mt.exe -updateresource:"myapp.exe";#1 -manifest patch3.manifest
版本号: 有两种
- 一种是单个文件的 "version, author, ..." 在右键属性里
另一种是manifest内规定的"version of file collection covered by manifest"
- 常见情况是: 一个manifest内嵌在单个文件内,所以和前一种"version"产生了歧义
- 一种不常见的情况: manifest内使用
file
指定了很多文件,这些文件都归属于当前manifest,见例子 https://blog.vrqq.org/archives/779/
数字签名
和https网站签名一样,使用 "证书crt" + "私钥key" 给dll/exe挂签名,证书的种类为 "OV Code Certificate" and "EV Code Certification",关键词 "Code Signing Certificate"
- This type of certificate is different with SSL-certificate
- 添加数字签名后,于文件属性可见 "Digital Signatures"
- 输出数字签名详情:
signtool verify /pa /v c:\Windows\system32\kernel32.dll
- publicKeyToken 对于.Net程序 支持StrongName:
sn -T YourAssembly.dll
- publicKeyToken 对于普通程序:
pktextract c:\workingdir\fable\check-same.cer
- 工具 https://docs.microsoft.com/en-us/windows/win32/seccrypto/signtool
验签
很可惜,操作系统不支持用签名校验“程序包”完整性,但WindowsDefender可以
- https://docs.microsoft.com/en-us/cpp/build/reference/manifestdependency-specify-manifest-dependencies?view=msvc-170
- 编译时打开INTEGRITYCHECK: (link.exe) https://docs.microsoft.com/en-us/cpp/build/reference/integritycheck-require-signature-check?view=msvc-170
后期打开INTEGRITYCHECK:
editbin /INTEGRITYCHECK myapp.exe
- 打上这之后,运行自签名证书的程序会被WindowsDefender拒绝
后期关闭INTEGRITYCHECK:
editbin /INTEGRITYCHECK:no myapp.exe
- 可以敲掉这个标志位,也不能防破解
- editbin工具详见 https://docs.microsoft.com/en-us/cpp/build/reference/editbin-reference?view=msvc-170
- 引篇关联不大的文档 https://social.technet.microsoft.com/wiki/contents/articles/255.forced-integrity-signing-of-portable-executable-pe-files.aspx
直觉上说 manifest可以包括"验证依赖是否完整",以及依赖的那些dll是不是系统dll
- 操作系统保证了 C:\Windows\System32 这个目录不会乱搞 (关键词: 目录签名)
manifest文件中有一条
assemblyIdentity.publicKeyToken
,看起来可以验证依赖的程序集是不是原生的- 但来看看这里,微软并没有给VC++6.0以上版本太多关爱 https://docs.microsoft.com/en-us/windows/win32/sbscs/supported-microsoft-side-by-side-assemblies
- 换个角度想,这个manifest和签名如果被敲掉全换了呢?所以仅能防个dll hell,而不是anti-hack
写在最后
防破解、 防debug 和 防注入 在很多角度上是一回事,无非是再汇编代码里插桩,游戏厂商做不到,加壳厂商也做不到
用户组已经覆盖了正常使用,没有一个像模像样的container 否则快捷键、截屏、文件下载都没有了
也倡导软件开发者们:主动避免申请管理员权限,高权限代码主动开源。