吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 712|回复: 9
上一主题 下一主题
收起左侧

[原创] GlassWire 3.11.1164 云许可算法分析

  [复制链接]
跳转到指定楼层
楼主
73214 发表于 2026-10-27 15:57 回帖奖励

[原创]GlassWire 3.11.1164 云许可算法分析

程序名称:GlassWire
程序版本:3.11.1164(x64)
程序语言:多语言
程序平台:Windows 10 / 11
加壳类型:WinLicense 3.x(.themida + .boot)
分析工具:IDA Pro、Python 3、SQLite
文章类型:原创 · 算法分析  

试用程序请用官方安装包(附件已传,或自行下载):

安装包 SHA-256(changelog 公布):

0D3C736CDCC73EA134F5392C4DC6D0AA48056C408B518D6A4299D022F36E18A2

下面只改本地云许可存储,不改 GlassWire.exe / GWCtlSrv.exe 的代码。同一套 protobuf 和 Blowfish 密钥还在,新版本一般也能用。


一、先看它怎么存许可

服务启动时走两条通道。

1. 本地文件通道

路径:C:\ProgramData\GlassWire\share\license.dat

格式:[正文][256 字节 RSA-2048 签名]。VerifyLicenseSignature(sub_7FF663BE6180)用内嵌公钥验整段正文。没有私钥就伪造不了。日志里的 License type: N 走的是这条。云许可加载成功时,这行会一直是 0。

2. 云许可通道

路径:C:\ProgramData\GlassWire\service-full\cloud\cloud.db

表:options(name TEXT PRIMARY KEY, value BLOB),行名 License。读取语句:

SELECT name, value FROM options WHERE name LIKE(?)

绑定字面量 License(sub_7FF6637245C0)。这条通道没有签名。后面整篇都对着它。


二、壳和 dump

3.11 的 GlassWire.exe、GWCtlSrv.exe 都是 WinLicense 3。进程内 Frida 在 stub 里活不下来,OEP 抓不到。

实际用的是外部 dump:拉起进程,盯第一个可执行节的熵,连续两次低于 6.8 就 NtSuspendProcess,再用 Scylla 把映像抠出来。dump 入口是占位 RVA 0x1000,只给静态分析用。

GWCtlSrv dump 的 image base 是 0x7FF662EF0000。早先用 0x7FF662EF1000 会整页偏高,跟代码还能蒙对,读 .rdata 就全错。核对方法:Blowfish π 表,IDA 0x7FF664837D70 必须读到:

88 6a 3f 24 d3 08 a3 85

对不上就先别往下跟。


三、云许可的 protobuf

.rdata 里嵌了 cloud_consumer_subscription.proto,包名 glasswire.cloud.consumer.api:

License {
  string id = 1;
  enum Type { Free = 0; Premium = 1; }
  enum Status {
    NOSTATUS = 0;
    ACTIVE = 1;
    PLAIN_TRIAL = 2;
    FULLILLED_TRIAL = 3;
    NO_SUBSCRIPTION = 4;
    MAX_LICENSES_REACHED = 5;
  }
  Subscription.Duration duration = 4;
}

EncryptedLicense {
  Version version = 1;   // 磁盘上行里不出现
  bytes license = 2;     // License 序列化后再 Blowfish
}

Duration {
  string create_timestamp = 1;
  string expire_timestamp = 2;
}

注意两套枚举不要混:

消息 字段 含义
云 License.Type 0 / 1 Free / Premium
旧 LicenseInfo.LicenseStatus 0..7 Free, Basic, Pro, Elite=3, Trial, SubBasic, SubPro, SubElite

云通道上写 type=3(旧 Elite),界面直接显示 FREE。3.11 产品侧已经没有 Elite,云 Type 只有两档。

Duration 两个字段都是 string,不是 varint 时间戳。

磁盘上实际存的是只有 field 2 的 EncryptedLicense,再做标准 Base64,以 TEXT 写入 options.value。


四、Blowfish

两边通道共用同一套密码。

  • 算法:Blowfish-CBC
  • 块序:大端(左移拼 32 位,和 LicenseEncryptor 一致)
  • IV:8 字节全 0
  • 密钥 24 字节:
1cad28831904f9131fb50b9c7a2f5d40761d6bc5759ceb19

来源有两处,值相同:

  • 旧通道:dump 文件偏移 0x1916548(LicenseInfoPrivate::DecryptLicense)
  • 云通道:LicenseEncryptor(sub_7FF66375C820)里六个 DWORD 拼回来

P/S 表是标准 π 常数,小端 DWORD,dump 文件偏移 0x1946970,共 4168 字节。表必须按 S[4][256] 拷。按四个 256 项数组去 S0 + i*256 会走出第一张表,自测能加解密,活服务照样报 license decryption failed。

填充(加密 sub_7FF663869CB0,解密 sub_7FF663869930):

pad = 8 - (len % 8)          // 结果在 1..8
payload = plaintext || 00*pad || uint64_le(pad)

解密读 trailer 低 32 位当 pad,再截成 len - pad - 8。trailer 不在 1..8,日志就是 license decryption failed。

活进程崩溃转储里 worker 帧的 Blowfish schedule 和这 24 字节密钥推出来的 schedule 逐字节相同,密钥以活服务为准。


五、value 怎么写进 SQLite

读 value 的路径是 OpenSSL BIO(sub_7FF66386A0C0):

BIO_new_mem_buf(value)
 -> BIO_f_base64,BIO_FLAGS_BASE64_NO_PADDING(flag 0x100)
 -> BIO_push
 -> BIO_read(512) 泵进 memory BIO
 -> BIO_ctrl flush / get_mem_data

断言字符串 crypto\bio\bss_mem.c 能对上库。

所以 options.License 只认一种形态:EncryptedLicense protobuf 的裸 Base64,TEXT 存储。不要加 Base64_ 前缀。那个前缀是 glasswire.conf 里 CloudAuthTokens 一类配置用的。

实测过的失败形态:

写入内容 结果
原始 protobuf 当 BLOB BIO 把二进制当 Base64 吃。pad 爆炸,std::length_error,服务崩溃循环,SCM 停掉
十六进制文本 hex 字母都在 Base64 表里,解出来是另一堆字节。日志 encrypted license parsing failed(FromEncryptedBytes 第 249 行),服务还活着
Base64_ 前缀 解码器连前缀一起吃,解析失败
裸 Base64 TEXT 能加载、能解密、服务会按自己的格式再加密写回

加载成功后服务会把同一个 CloudLicense 重新序列化再写回去(Duration 的 varint 更紧)。能看到这一步,说明整条链是通的:Base64 → protobuf → Blowfish → 内存对象 → 再加密 → 再存储。

还有一个坑:LIKE('License') 会同时命中 TEXT 名和 BLOB 名。有效期解析失败时,云组件会留下一行 名字类型是 BLOB 的空 License。下次启动先读到这个空行,日志 encrypted license data is empty,真正的 TEXT 行被挡住。写入前先清干净:

DELETE FROM options WHERE CAST(name AS TEXT) = 'License';
INSERT INTO options(name, value) VALUES('License', ?);

打开库要用 READWRITE。服务挂着 WAL 时,READONLY 贴不上 -shm,读会失败。


六、有效期字符串

服务解析 Duration 用的格式和它自己渲染的格式一样(sub_7FF66381C240):

%Y-%m-%dT%H:%M:%S

没有尾巴上的 Z。

下面三种都会解析成 0:

  • 2025-01-01T00:00:00Z
  • "1735689600" 这种 epoch 数字串
  • 根本不带 duration 字段

解析为 0 时 protobuf 还能进内存,但随后 LicenseEncryptor::Encrypt 失败,日志连续两条:

license serialization failed
license encryption failed

云组件把状态打回未授权,并留下上面说的 BLOB 空行。

过期时间写到年 3000,字符串能解析,32 位 epoch 溢出,关于页倒计时变成乱值。安全上限是 2037-12-31T23:59:59(unix 2145916799)。一组能用的值:

2025-01-01T00:00:00  ->  2037-12-31T23:59:59

付费行必须带 Duration,不能省。


七、CloudAccountState

只写 License 行,界面徽章仍是 FREE。还要改 glasswire.conf 里的 CloudAccountState。

该值是 protobuf 的小写十六进制,同样没有 Base64_ 前缀。

field 1 = ConsumerSession 状态
field 3 = device_info
field 4 = server_info

field 1 在已看过的版本里都排第一(key 字节 0x08)。枚举在 dump VA 0x7FF6647CE990:

kStateNotSet=0
kStateUnregistered=1
kStateRegistering=2
kStateUnauthorized=3
kStateAuthorizing=4
kStateUnauthorizing=5
kStateReady=6
kStateExpired=7
kStateRequestingAuthToken=8

把 field 1 改成 6,后面的 field 3 / field 4 留下。截成只剩 field 1,服务会打:

device id changed: State device id: ,

然后用现场设备信息把整段 protobuf 重写一遍。

状态机之后会请求:

/agent-api/v1/license?device_id=<device>
/api/v1.1/agent/user/me

400 / 503 不会把一条 Duration 合法的行打回去。心跳参数在 Type=1 时是 l=Premium。

测试里看到 field 1 掉到 3 或 8,原因是 Duration 管道失败,不是这几个 HTTP 错误本身。

启动画面上那个「启动服务」是另一条路:许可 id 长度 44,再加 LicenseCore::DoActivationFailed(license_core.cpp 第 1107 行)里的签名判断。磁盘上的云许可行不走这条,服务启动时直接读。


八、算法还原(Python)

pycryptodome 的 Blowfish 按大端块、零 IV、自定义填充用即可。

import datetime
import struct
from Crypto.Cipher import Blowfish

KEY = bytes.fromhex("1cad28831904f9131fb50b9c7a2f5d40761d6bc5759ceb19")

def varint(n):
    out = bytearray()
    while True:
        b = n & 0x7F
        n >>= 7
        if n:
            out.append(b | 0x80)
        else:
            out.append(b)
            return bytes(out)

def vfield(num, value):
    return varint((num << 3) | 0) + varint(value)

def bfield(num, value):
    return varint((num << 3) | 2) + varint(len(value)) + value

def iso_noz(epoch):
    t = datetime.datetime.fromtimestamp(epoch, datetime.timezone.utc)
    return t.strftime("%Y-%m-%dT%H:%M:%S").encode()

def build_license(lic_id, from_ts, to_ts):
    dur = bfield(1, iso_noz(from_ts)) + bfield(2, iso_noz(to_ts))
    return (
        bfield(1, lic_id.encode())
        + vfield(2, 1)   # Premium
        + vfield(3, 1)   # ACTIVE
        + bfield(4, dur)
    )

def gw_encrypt(pt):
    pad = 8 - (len(pt) % 8)
    payload = pt + b"\x00" * pad + struct.pack("<Q", pad)
    return Blowfish.new(KEY, Blowfish.MODE_CBC, iv=b"\x00" * 8).encrypt(payload)

def stored_value(lic_id, from_ts, to_ts):
    inner = build_license(lic_id, from_ts, to_ts)
    enc = gw_encrypt(inner)
    blob = bfield(2, enc)
    import base64
    return base64.b64encode(blob).decode()

if __name__ == "__main__":
    print(stored_value(
        "GLWFORGE0000PREMIUM000TEST000000010000000000",
        1735689600,   # 2025-01-01T00:00:00
        2145916799,   # 2037-12-31T23:59:59
    ))

已知答案(防自己写错表或端序):明文

0a2c474c57464f52474530303030454c49544530303030544553543030303030303031303030303030303030303010011801

对应密文

5349edacf44cb2f1fa81891024f342d8c0137cc61e27cc0e4448f7858827cf1ff8e7a2078b62a26a4d7dcd36c59ec3198c37a37ba694dcf7de6f08f9083c1df4

对不上就不要写盘。

CloudAccountState 只改 field 1 那个 varint 字节(状态 0..8 都是单字节),其余不动。例如原文以 08 03 ... 开头(未授权)改成 08 06 ...。


九、写入顺序

服务在跑时不要改库。

  1. 停服务 GlassWire,结束 GlassWire.exe
  2. 备份 cloud.db、glasswire.conf、glasswire.db
  3. 按第五节 DELETE + INSERT 写入 License
  4. CloudAccountState field 1 写成 6
  5. 启动服务,等几秒
  6. 翻最新日志,下列字符串在启动时刻之后不得出现:
FromEncryptedBytes
encrypted license
decryption failed
serialization failed
encryption failed
  1. 再开 UI

回滚用备份覆盖这三份文件即可。


十、怎么确认生效

能对上的现象:

  • 左上角徽章:PREMIUM
  • 绿色 UPGRADE 按钮变成头像
  • 底部 Get All Premium Features 横条消失
  • 心跳:l=Premium

对不上、别被骗的现象:

  • 日志 License type: N(旧文件通道)
  • 关于页「还剩几个小时」(见下一节)

CloudAuthTokens 不用改。头像只是 kStateReady 看起来像已登录,不是重新走了一遍门户。


十一、关于页倒计时

关于页在徽章已经是 Premium 时,仍可能显示 Only a few hours remaining。

UI 里 DaysRemaining(UI dump 0x7ff7b77db220)走 fill_timerange。has_duration 的判定是 get_type() - 4 <= 3,也就是旧类型 4..7(试用 / 订阅)。然后 (expire - now) / 3600 / 24。

磁盘加载伪造的云许可,不会走 API MakeLicense(0x7ff6637ca950)去填 LicenseInfo.time_expire。对 GlassWire.exe 进程做字符串扫描,伪造的 id、ISO 文本、unix 时间戳都不在映像里。GWCtlSrv.exe 里能看到 ISO 文本,看不到解析后的 unix 时间。

glasswire.db 的 license_data 是服务端缓存,UI 进程不映射这块。付费功能和徽章不依赖关于页那一行字。


十二、3.8 的旧方法和 3.11 的差别

3.8.1061 是脱 WinLicense 之后改两处机器码:档位 getter 恒回 6,过期判断恒回假。那两个 hex 特征到 3.11 对不上。

3.11 走云存储,不碰代码,所以不依赖具体指令排布。密钥或 protobuf 一旦换掉,日志里的解密 / 序列化失败会先告诉你,不要硬写。

启动画面激活流程(44 字符 id + 正则)是死的,全局指针还指到一份源码路径字符串。和磁盘云许可不是同一条路。


附件

  1. 官方 3.11.1164 安装包(或上面的官方链接)
  2. 还原脚本(第八节源码)
  3. 独立写入工具源码 gw_patcher.cpp(MSVC C++17,管理员清单,运行时加载 winsqlite3.dll)

分析用的 dump 体积大,不随帖提供。需要 IDA 时自己装官方包,按第二节 dump 即可。

GlassWire.7z

155.62 KB, 下载次数: 22, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 3吾爱币 +3 热心值 +3 收起 理由
GS9452 + 1 谢谢@Thanks!
Tonyha7 + 2 + 1 谢谢@Thanks!
lapangxe + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
dork 发表于 2026-10-27 21:02
虽然楼主花费了不少Tokens,但过程还是有几处值得我们自己的AI进行学习的,已收藏。
沙发
Mas9ue14 发表于 2026-10-27 17:05
3#
lapangxe 发表于 2026-10-27 17:24
以为很复杂,结果很简单,已顺利升级成 PREMIUM 版
4#
宇宙第一强者 发表于 2026-10-27 17:43
千万别用这个玩意,电脑会蓝屏 ,我之前使用电脑隔三岔五蓝屏 把我电脑电源都干坏了.
5#
 楼主| 73214 发表于 2026-10-27 18:01 |楼主
宇宙第一强者 发表于 2026-10-27 17:43
千万别用这个玩意,电脑会蓝屏 ,我之前使用电脑隔三岔五蓝屏 把我电脑电源都干坏了.

蓝屏和电源损坏跟这个 patcher 对不上。

帖子刚发出来,谈不上「隔三岔五蓝屏几天」。你说的是更早的问题,不是这个工具。

这个工具不改 GlassWire.exe / GWCtlSrv.exe,也不碰驱动。它只停服务,改 cloud.db 里的 License 和 glasswire.conf 的 CloudAccountState,再把服务拉起来。用户态写配置,进不了内核,更写不到电源。

GlassWire 自带的 gwdrv.sys 才是内核组件。蓝屏要查那个驱动、dump、还是别的软件,别把旧故障安到刚发的帖上。

有 minidump 或具体 stop code 可以贴出来对一下。没有的话,这锅这个工具接不住。
6#
wyp123 发表于 2026-10-27 19:10
以前没学习版用的是NetLimiter这个,这个好用
8#
Cleverwwh 发表于 2026-10-28 00:10
本帖最后由 Cleverwwh 于 2026-10-28 00:51 编辑

云许可的校验流程还原得比较完整,抓包和内存对照的部分对逆向学习很有帮助,感谢分享。
9#
kloco303 发表于 2026-10-28 07:59
牛人啊,分析学习!。。。。
10#
wgyx 发表于 2026-10-28 08:37
73214 发表于 2026-10-27 18:01
蓝屏和电源损坏跟这个 patcher 对不上。

帖子刚发出来,谈不上「隔三岔五蓝屏几天」。你说的是更早的 ...

好家伙用的豆包啊,哈哈
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-10-28 12:59

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表