UWP应用:Repacks & Hacks
今天遇到了需要修改 UWP 程序的情况,步骤比较繁杂,在此记录一下。
Repacks
获取程序文件
- appx 文件可以通过抓包的方式直接获取下载地址。我在搜索过程中发现了很多相关的教程,都比较老了,有些地方变动比较大。
首先 Microsoft Store 会产生一个到http://dl.delivery.mp.microsoft.com/filestreamingservice/files/{GUID}/piecehash
的请求,确定程序版本、哈希、分段等信息。然后在http://tlu.dl.delivery.mp.microsoft.com/filestreamingservice/files/{GUID}?P1={}&P2={}&P3={}&P4={}
分段下载文件。只要访问 URL ,就可以下载到完整的 appx 。
- 直接打开应用的安装目录(在
C:\Program Files\WindowsApps\
下),把所有文件复制出来。如果不能直接打开这个文件夹,可能需要调整文件夹的高级安全设置,加入当前用户的访问权限。事实证明,对于我测试的一个程序来说,在打包之后它确实能够运行,所以这也可以算是一种可行方法吧。
解包
使用makeappx.exe unpack /p foo.appx /d unpacked /l
对 appx 进行解包,得到的目录结构如下:
如果makeappx
报错,很有可能抓包得到的是 App Bundle 。根据文件头可知其为一个 zip 文件,里面的内容有不同分辨率的资源文件和 x64 、 x86 两个架构的程序文件。Unbundle 命令为makeappx.exe unbundle /p rest.appxbundle /d unpacked
。
原安装包留下的不必要的结构有:AppxSignature.p7x
文件和AppxBlockMap.xml
文件(指出文件实际位置信息的xml)。直接把这些文件删除就可以。
重新打包
为了能正常安装 appx 程序包,我们必须准备一个用于签名的证书。在 Powershell 中,执行
# 制作自签名证书,记录输出的证书指纹
New-SelfSignedCertificate -Type Custom -Subject "CN=Contoso Software" -KeyUsage DigitalSignature -FriendlyName "Your friendly name goes here" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}")
# 使用密码方式导出
$password = ConvertTo-SecureString -String <Your Password> -Force -AsPlainText
Export-PfxCertificate -cert "Cert:\CurrentUser\My\<Certificate Thumbprint>" -FilePath <FilePath>.pfx -Password $password
打开AppxManifest.xml
,将Identity
节点中的Publisher
属性改为刚刚制作的证书中的Subject
值,如CN=Contoso Software
。之后就可以打包、签名了。
makeappx.exe pack /d unpacked /p repacked.appx /l
signtool.exe sign /fd SHA256 /a /f mycert.pfx /p "mycertpassword" repacked.appx
signtool
中指定使用 SHA256 的原因是makeappx
默认使用SHA256。
Hacks
如何让一个正在试用中的应用认为它已经被购买?对于 dotnet 程序,微软在Windows.Services.Store
中提供了StoreAppLicense
类作为应用可以获取到的返回值类型。在官方示例中,说明了其用法:
StoreAppLicense license = await storeContext.GetAppLicenseAsync();
if (license.IsActive)
{
if (license.IsTrial)
{
LicenseMode.Text = "Trial license";
}
else
{
LicenseMode.Text = "Full license";
}
}
else
{
LicenseMode.Text = "Inactive license";
}
StoreAppLicense.IsActive
和 StoreAppLicense.IsTrial
都是只读的属性,所以修改它们需要用到反射。但很幸运的是,我要修改的程序中自己封装了一个用来获取许可的类,也提供了相同名称的两个只读属性。在 C# 中,属性的get
和set
都是函数,所以可以直接修改它们的IL代码强制其返回指定的布尔值,达到欺骗程序的目的。
处理 UWP 程序相对来说比较困难。它不允许直接启动,事实上 Visual Studio 在调试 UWP 程序时,会先将其安装到系统中,目前我还没有找到很好的动态调试的方法。其次 XAML 交互部分的代码中可能存在大量匿名函数,对程序的修改工作制造了一定的阻碍。