吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3318|回复: 49
上一主题 下一主题
收起左侧

[原创] SandboxiePlus 高级功能无限试用破解

  [复制链接]
跳转到指定楼层
楼主
暴龙兽 发表于 2025-3-22 22:01 回帖奖励

前言

前几天偶然发现SandboxiePlus的一些有意思的高级功能,比如:数据保护、安全强化和应用程隔离。但这些功能都要收费,免费的证书有效期也只有10天,每个PC只能申请三次。




虽然它已经开源了,鼓励大家提交代码,使用这个软件,看起来破解它没太大的必要,但你自己编译的程序没有微软的签名,正常使用这个程序需要关闭强制驱动签名(DSE),对于没有虚拟机环境的用户来说显然不可行,这无疑将更大的风险暴露了出来。换句话说,如果我有虚拟机环境了,我也没必要使用SandboxiePlus,除非你是研究这个程序的。本篇文章介绍了如何在其官方发布的程序中(带微软官方签名),通过替换一些模块,实现无限试用其高级功能。

注意:这里的证书只是一段字符串,不是.DER、.CER或.PFX那种格式的证书,不要搞混了。

验证流程

首先需要获取一个试用证书,这个证书肯定是有效的,然后分析整个程序如何对这个证书的内容进行验证。

获取试用证书

获取证书的路径在选项->全局配置->捐赠支持->获取一个免费试用许可证



接下来需要输入一个邮箱地址,这个邮箱地址可以是无效的,它并不会像你的邮箱中发送一个验证链接,然后点击确定就行了。


最后等待几秒中,SandboxiePlus会需要一个权限,向自己的安装路径中的Certificate.dat文件写入获取的证书内容,我这里的证书如下:

NAME: bill
DATE: 17.03.2025
TYPE: EVALUATION-10
SOFTWARE: Sandboxie-Plus
HWID: 915BB029-C29E-4ACB-B8C7-065BEF13003C
UPDATEKEY: D0AF829D7FEE7640664ACB28F0129C99
SIGNATURE: Vj3hDYSa3QmNZ79URapkTK2hR2pUa+kjF1ArxsxVDYI+KE0hevIimSbNyfyQvsxUgU4mi5ppMOMZL82UYkMWgA==

上述流程对应的代码是OnlineUpdater.cpp的COnlineUpdater::GetSupportCert函数中,该函数中会获取之前输入的邮箱地址、当前计算机用户名以及和驱动交互拿到PC硬件SMBIOS中的UUID,然后拼接成下面格式的URL

https://sandboxie-plus.com/get_cert.php?eMail=xxx&Name=xxx&HwId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx

向服务端发送网络请求,最后服务端返回的就是上面证书的内容。另一种验证方法是通过序列号,这个应该是没有和PC硬件进行绑定的,这种方法这里就不介绍了,感兴趣的小伙伴可以自行研究一下。

驱动验证

证书的验证主要在驱动侧,52pojie论坛上面从Sandboxie源码分析软件注册机制及逆向思路这篇文章介绍了如何绕过驱动的验证,总结来说就是让驱动的验证函数直接返回STATUS_SUCCESS,绕过验证。这不符合我们需求,而且这种方法现在已经无效了,一些高级功能还是无法使用。
驱动的验证函数是verify.c中的KphValidateCertificate函数,主要验证流程如下:

  1. 打开并获取Certificate.dat文件的内容,解析成如下key:value的形式,
WCHAR *ptr;
WCHAR *name;
WCHAR *value;
ULONG temp_len;

// parse tag name: value

ptr = wcschr(line, L':');
if ((! ptr) || ptr == line) {
    status = STATUS_INVALID_PARAMETER;
    break;
}
value = &ptr[1];

// eliminate trailing whitespace in the tag name

while (ptr > line) {
    --ptr;
    if (*ptr > 32) {
        ++ptr;
        break;
    }
}
*ptr = L'\0';

name = line;

// eliminate leading and trailing whitespace in value

while (*value <= 32) {
    if (! (*value))
        break;
    ++value;
}

if (*value == L'\0') {
    status = STATUS_INVALID_PARAMETER;
    break;
}

ptr = value + wcslen(value);
while (ptr > value) {
    --ptr;
    if (*ptr > 32) {
        ++ptr;
        break;
    }
}
*ptr = L'\0';
/*
name : key
{
    "NAME":"bill",
    "DATE":"17.03.2025",
    "TYPE":"EVALUATION-10",
    "SOFTWARE":"Sandboxie-Plus",
    "HWID":"915BB029-C29E-4ACB-B8C7-065BEF13003C",
    "UPDATEKEY":"D0AF829D7FEE7640664ACB28F0129C99",
}
*/

获取字段中的信息,如下:

  • "NAME"字段的值表示用户名,
  • "DATA"字段的值表示试用证书的开始日期,
  • "TYPE"字段的值"EVALUATION"表示证书类型,"10"表示有效试用期时间,单位是天
  • "SOFTWARE"字段的值表示软件名称,必须是"Sandboxie-Plus",任何类型的证书都是"Sandboxie-Plus",否则无法验证通过。
    else if (_wcsicmp(L"SOFTWARE", name) == 0) { // if software is specified it must be the right one
    if (_wcsicmp(value, SOFTWARE_NAME) != 0) {
        status = STATUS_OBJECT_TYPE_MISMATCH;
        goto CleanupExit;
    }
    }
  • "UPDATEKEY"字段的值表示证书的更新密钥,如果这个值存在一个黑名单中,则验证失败。
  • "HWID"字段的值表示硬件ID,如果和当前机器的硬件ID不相同,验证失败。
    else if (_wcsicmp(L"HWID", name) == 0) { // if HwId is specified it must be the right one
    extern wchar_t g_uuid_str[40];
    if (_wcsicmp(value, g_uuid_str) != 0) {
        status = STATUS_FIRMWARE_IMAGE_INVALID;
        goto CleanupExit;
    }
    }

2.然后将key和value输入填入缓存区,使用SHA256算法进行hash运算.

// 初始化hash
if(!NT_SUCCESS(status = MyInitHash(&hashObj)))
    goto CleanupExit;
// 填充数据
if (NT_SUCCESS(RtlUnicodeToUTF8N(temp, line_size, &temp_len, name, wcslen(name) * sizeof(wchar_t))))
    MyHashData(&hashObj, temp, temp_len);

if (NT_SUCCESS(RtlUnicodeToUTF8N(temp, line_size, &temp_len, value, wcslen(value) * sizeof(wchar_t))))
    MyHashData(&hashObj, temp, temp_len);
// 计算hash
if(!NT_SUCCESS(status = MyFinishHash(&hashObj, &hash, &hashSize)))
    goto CleanupExit;

3.签名验证。验证函数函数如下,Hash和HashSize就是上文中的sha256值和长度,Signature是证书中的"SIGNATURE"对应的值,这个值是经过base64编码的,到验证函数这个地方已经经过解码了。

static UCHAR KphpTrustedPublicKey[] =
{
    0x45, 0x43, 0x53, 0x31, 0x20, 0x00, 0x00, 0x00, 0x05, 0x7A, 0x12, 0x5A, 0xF8, 0x54, 0x01, 0x42,
    0xDB, 0x19, 0x87, 0xFC, 0xC4, 0xE3, 0xD3, 0x8D, 0x46, 0x7B, 0x74, 0x01, 0x12, 0xFC, 0x78, 0xEB,
    0xEF, 0x7F, 0xF6, 0xAF, 0x4D, 0x9A, 0x3A, 0xF6, 0x64, 0x90, 0xDB, 0xE3, 0x48, 0xAB, 0x3E, 0xA7,
    0x2F, 0xC1, 0x18, 0x32, 0xBD, 0x23, 0x02, 0x9D, 0x3F, 0xF3, 0x27, 0x86, 0x71, 0x45, 0x26, 0x14,
    0x14, 0xF5, 0x19, 0xAA, 0x2D, 0xEE, 0x50, 0x10
};

NTSTATUS KphVerifySignature(
    _In_ PVOID Hash,
    _In_ ULONG HashSize,
    _In_ PUCHAR Signature,
    _In_ ULONG SignatureSize
    )
{
    NTSTATUS status;
    BCRYPT_ALG_HANDLE signAlgHandle = NULL;
    BCRYPT_KEY_HANDLE keyHandle = NULL;
    PVOID hash = NULL;
    ULONG hashSize;

    // Import the trusted public key.
    // KPH_SIGN_ALGORITHM -> BCRYPT_ECDSA_P256_ALGORITHM
    if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&signAlgHandle, KPH_SIGN_ALGORITHM, NULL, 0)))
        goto CleanupExit;
    if (!NT_SUCCESS(status = BCryptImportKeyPair(signAlgHandle, NULL, KPH_BLOB_PUBLIC, &keyHandle,
        KphpTrustedPublicKey, sizeof(KphpTrustedPublicKey), 0))) // KPH_BLOB_PUBLIC -> BCRYPT_ECCPUBLIC_BLOB
    {
        goto CleanupExit;
    }

    // Verify the hash.

    if (!NT_SUCCESS(status = BCryptVerifySignature(keyHandle, NULL, Hash, HashSize, Signature,
        SignatureSize, 0)))
    {
        goto CleanupExit;
    }

CleanupExit:
    if (keyHandle)
        BCryptDestroyKey(keyHandle);
    if (signAlgHandle)
        BCryptCloseAlgorithmProvider(signAlgHandle, 0);

    return status;
}

这个函数试用的签名算法是BCRYPT_ECDSA_P256_ALGORITHM.

4.验证通过之后,开始填充Verify_CertInfo全局变量,它的类型是SCertInfo。SandboxiePlus用户态和驱动进行通信,返回Verify_CertInfo的内容,来查询当前机器是否有资格使用一些高级功能。

typedef union _SCertInfo {
    unsigned long long State;
    struct {
        unsigned long
            active      : 1,    // certificate is active
            expired     : 1,    // certificate is expired but may be active
            outdated    : 1,    // certificate is expired, not anymore valid for the current build
            unused_1    : 2,    // DEPRECATED
            grace_period: 1,    // the certificate is expired and or outdated but we keep it valid for 1 extra month to allof wor a seamless renewal
            reservd_2   : 2,

            type        : 5,
            level       : 3,

            reservd_3   : 8,

            reservd_4   : 4,    // More features
            opt_desk    : 1,    // Isolated Sandboxie Desktops:             "UseSandboxDesktop"
            opt_net     : 1,    // Advanced Network features:               "NetworkDnsFilter", "NetworkUseProxy".
            opt_enc     : 1,    // Box Encryption and Box Protection:       "ConfidentialBox", "UseFileImage", "EnableEFS".
            opt_sec     : 1;    // Various security enhanced box types:   "UseSecurityMode", "SysCallLockDown", "RestrictDevices", "UseRuleSpecificity", "UsePrivacyMode", "ProtectHostImages",
                                // as well as reduced isolation box type:   "NoSecurityIsolation".

                                // Other features, available with any cert: "UseRamDisk", "ForceUsbDrives",
                                // as well as Automatic Updates, etc....

        long expirers_in_sec;
    };
} SCertInfo;

前面签名已经验证通过了,所以将active设置为1。根据"TYPE"设置type,这里为eCertEvaluation,对应的level为eCertMaxLevel表示可以试用SandboxiePlus的所有高级功能,部分代码如下:

// 设置type
 else if (_wcsicmp(type, L"EVALUATION") == 0 || _wcsicmp(type, L"TEST") == 0)
            Verify_CertInfo.type = eCertEvaluation;
// 设置level
else if (CERT_IS_TYPE(Verify_CertInfo, eCertEvaluation)) // in evaluation the level field holds the amount of days to allow evaluation for
{
    if(days) expiration_date.QuadPart = cert_date.QuadPart + KphGetDateInterval((CSHORT)(days), 0, 0);
    else expiration_date.QuadPart = cert_date.QuadPart + KphGetDateInterval((CSHORT)(level ? _wtoi(level) : 7), 0, 0); // x days, default 7
    Verify_CertInfo.level = eCertMaxLevel;
}
// 设置高级功能,注意没有break,会fall-through
switch (Verify_CertInfo.level)
{
    case eCertMaxLevel:
    //case eCertUltimate:
        Verify_CertInfo.opt_desk = 1;
    case eCertAdvanced:
        Verify_CertInfo.opt_net = 1;
    case eCertAdvanced1:
        Verify_CertInfo.opt_enc = 1;
    case eCertStandard2:
    case eCertStandard:
        Verify_CertInfo.opt_sec = 1;
    //case eCertBasic:
}

接下来就是填充expired,判断当前证书是否过期。如果证书类型是eCertEternal,将永远有效。验证eCertEvaluation证书有效期逻辑如下:

LARGE_INTEGER SystemTime;
LARGE_INTEGER LocalTime;
KeQuerySystemTime(&SystemTime);
ExSystemTimeToLocalTime(&SystemTime, &LocalTime);

   // check if this certificate is expired
if (expiration_date.QuadPart < LocalTime.QuadPart)
    Verify_CertInfo.expired = 1;
Verify_CertInfo.expirers_in_sec = (ULONG)((expiration_date.QuadPart - LocalTime.QuadPart) / 10000000ll); // 100ns steps -> 1sec

总结:这个验证过程就是获取证书内容,对除签名字段以外的其他内容进行sha256运算,然后hash值和签名使用ECDSA算法进行验证。验证通过之后,填充全局变量Verify_CertInfo。

破解思路

破解私钥

修改机器时间

  • 假如你不怕麻烦的话,可以申请一个有效试用证书,不断修改当前机器的时间,实现永远在有效期内。

修改用户态查询结果

上文中介绍了驱动中的验证逻辑,用户态通过和内核态通信来判断是否可以使用一些高级功能,其实就是返回Verify_CertInfo中的内容。那么能不能通过修改用户态的结果来绕过验证?

  • 情况一:假如构造一个无效证书,修改用户态的查询结果,是否可行?答案是不可行。因为你绕过了用户态验证,但内核态的Verify_CertInfo中的信息并没有变,当你使用一些高级功能,内核态也会进行判断对应的字段是否有效,相关代码如下:

    _FX PROCESS *Process_Create(
    HANDLE ProcessId, const BOX *box, const WCHAR *image_path,
    KIRQL *out_irql)
    {
    ......
    if (!Verify_CertInfo.opt_sec && !proc->image_sbie) {
    
        const WCHAR* exclusive_setting = NULL;
        if (proc->use_security_mode)
            exclusive_setting = L"UseSecurityMode";
        else if (proc->is_locked_down)
            exclusive_setting = L"SysCallLockDown";
        else if (proc->restrict_devices)
            exclusive_setting = L"RestrictDevices";
        else
    #ifdef USE_MATCH_PATH_EX
        if (proc->use_rule_specificity)
            exclusive_setting = L"UseRuleSpecificity";
        else if (proc->use_privacy_mode)
            exclusive_setting = L"UsePrivacyMode";
        else
    #endif
        if (proc->bAppCompartment)
            exclusive_setting = L"NoSecurityIsolation";
        else if (proc->protect_host_images)
            exclusive_setting = L"ProtectHostImages";
    
        if (exclusive_setting) {
    
            Log_Msg_Process(MSG_6004, proc->box->name, exclusive_setting, box->session_id, proc->pid);
    
            // allow the process to run for a sort while to allow the features to be evaluated
            Process_ScheduleKill(proc, 5*60*1000); // 5 minutes
        }
    }
    if (!Verify_CertInfo.opt_enc && !proc->image_sbie) {
    
        const WCHAR* exclusive_setting = NULL;
        if (proc->confidential_box)
            exclusive_setting = L"ConfidentialBox";
    
        if (exclusive_setting) {
    
            Log_Msg_Process(MSG_6009, proc->box->name, exclusive_setting, box->session_id, proc->pid);
    
            Pool_Delete(pool);
            Process_CreateTerminated(ProcessId, box->session_id);
            return NULL;
        }
    }
    ......
    }
  • 情况二:假如我申请一个有效试用证书,但我能否修改用户态的查询结果,实现软件的无限试用?答案是可以。当我一个试用证书过期了,_SCertInfo结构体中除了expired之外的其他成员都是正常的,而expired字段的校验交给了用户态,内核态并没有校验。查找所有参数IoControlCode为API_QUERY_DRIVER_INFO,调用NtDeviceIoControlFile的代码,修改返回结果,将expired字段设置为0,expirers_in_sec设置为0xffffffff,即可实现无限试用。




总结

本文利用了SandboxPlus验证逻辑漏洞,通过修改SandboxiePlus用户态程序查询证书信息的结果,实现了无限试用官方正式版高级功能的效果。

免费评分

参与人数 11威望 +2 吾爱币 +107 热心值 +10 收起 理由
nankehhh + 1 用心讨论,共获提升!
ffdds + 1 + 1 谢谢@Thanks!
sarex + 1 + 1 用心讨论,共获提升!
LAOBILAXI233 + 1 热心回复!
gaosld + 1 + 1 谢谢@Thanks!
Hmily + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
wari01 + 1 + 1 用心讨论,共获提升!
hwh425 + 1 谢谢@Thanks!
5omggx + 1 + 1 用心讨论,共获提升!
ArthurCummings + 1 + 1 谢谢@Thanks!
lac9 + 1 谢谢@Thanks!

查看全部评分

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

推荐
bachelor66 发表于 2025-3-25 08:25
本帖最后由 bachelor66 于 2025-3-25 09:30 编辑
暴龙兽 发表于 2025-3-24 21:40
网上搜同名文章,已经编译出来了。

那个也是大佬发布的吗?感谢分享                                             
推荐
urufu 发表于 2025-3-23 12:59
IoControlCode为API_QUERY_DRIVER_INFO,调用NtDeviceIoControlFile的代码,修改返回结果,将expired字段设置为0
再琢磨一下~
沙发
junjiezyh 发表于 2025-3-23 09:53
大佬牛逼,要是能直接成为永久正式版就更好了
3#
花葬 发表于 2025-3-23 10:21
看懂了,但是我做不到
4#
sdieedu 发表于 2025-3-23 10:52
看起来不错
5#
huangchaojun 发表于 2025-3-23 11:03
沙盒很实用,期待更高级的破解研究
6#
cux666 发表于 2025-3-23 11:07
技术活,非小白能轻松使用,赞!
7#
mdictfan 发表于 2025-3-23 11:23
学习一下,多谢!
8#
dd114514 发表于 2025-3-23 12:17
看起来还不错
9#
downloading 发表于 2025-3-23 12:59
离小白还是那么远
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-3-27 08:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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