snowfox 发表于 2019-4-15 20:57

XX通3.4.3045 去广告码, 积分码算法分析(2019.4.30更新)

本帖最后由 snowfox 于 2019-7-31 12:58 编辑

2019.4.30 更新,
大家反馈的积分码无效问题, 这段忙一直没时间看, 趁着放假看了一下, 是因为积分一下加太多了
软件内有积分限制, 太多了反而无效, 重新制作了算号器, 大家下载新的就好了.
退出软件删除 C:\Users\Public\Nwt\data\sc 文件即可清空积分等信息

新的算号器下载

积分数据限制逻辑
uint64 *sub_5EEBC0()
{
uint64 *result; // eax

sub_631880(g_pSQLiteDatebase, g_pOnlieInfo);
result = &g_pOnlieInfo->Score;
if ( g_pOnlieInfo->Score >= 500000000 )
g_bTooManyScore = 1;
*result += (unsigned int)dword_B31FD8;
return result;
}


软件挺好用, 就是老弹广告, 好在作者提供了去广告码可以去除广告
随便输入任意字符串, 提示无效的广告码, 从提示入手
Spy一下, 确定软件应该是duilib开发的界面, 在软件目录下有res文件夹, 找到
res\ShiYeLine\value\string.xml 我们查找对应的提示文本, 看到

      <String Id="IDS_REMOVE_ADVERTISEMENT_SUCCESS_FORMAT">开通成功,到期时间为:%s。</String>
      <String Id="IDS_REMOVE_ADVERTISEMENT_CODE_EMPTY">请输入免广告码。</String>
      <String Id="IDS_REMOVE_ADVERTISEMENT_CODE_INVALID">无效的免广告码。</String>
      <String Id="IDS_REMOVE_ADVERTISEMENT_CODE_ADDED">免广告码已添加过。</String>

在IDA字符串列表中搜索 IDS_REMOVE_ADVERTISEMENT_CODE_INVALID
定位到函数 414570

if ( v62 )
{
    v29 = 0;
    i = 0;
    ret = sub_5EE630(&v29, (basic_string *)&strNoAdvCode, (void **)&i);
    if ( ret != 1 && v29 )
    {
      if ( ret == 2 )
      {
      string::string((basic_string *)&v50, L"IDS_REMOVE_ADVERTISEMENT_CODE_ADDED");// 免广告码已添加过。
      LOBYTE(v64) = 7;
      v8 = SkinUI::GetString((basic_string *)&v51, (basic_string *)&v50);
      LOBYTE(v64) = 8;
      string::substr((basic_string *)&v53, v8, 0, 0xFFFFFFFF);
      string::dtor((basic_string *)&v51);
      LOBYTE(v64) = 2;
      string::dtor((basic_string *)&v50);
      }
      else
      {
      string::string((basic_string *)&v50, L"IDS_REMOVE_ADVERTISEMENT_SUCCESS_FORMAT");// 开通成功,到期时间为:%s。
      LOBYTE(v64) = 9;
      SkinUI::GetString((basic_string *)&v57, (basic_string *)&v50);
      LOBYTE(v64) = 11;
      string::dtor((basic_string *)&v50);
      string::string((basic_string *)&v33, (void *)&WindowName);
      LOBYTE(v64) = 12;
      string::string((basic_string *)&v41, (void *)&WindowName);
      LOBYTE(v64) = 13;
      string::string((basic_string *)&v37, (void *)&WindowName);
      LOBYTE(v64) = 14;
      string::string((basic_string *)&v45, (void *)&WindowName);
      LOBYTE(v64) = 15;
      v9 = sub_4B0580((basic_string *)&v52, (unsigned int)i);
      LOBYTE(v64) = 16;
      if ( v9->_Myres < 8 )
          v10 = (int)&v9->Buf.pBuf;
      else
          v10 = (int)v9->Buf.pBuf;
      v11 = Format;
      if ( v59 < 8 )
          v11 = (wchar_t *)&Format;
      v12 = SkinUI::StringFormat((basic_string *)&v51, v11, v10);
      LOBYTE(v64) = 17;
      SkinUI::MsgBox(v12, v32, &v45, 0, &v37, &v41, &v33, 0);
      string::dtor((basic_string *)&v51);
      string::dtor((basic_string *)&v52);
      string::dtor((basic_string *)&v45);
      string::dtor((basic_string *)&v37);
      string::dtor((basic_string *)&v41);
      string::dtor((basic_string *)&v33);
      LOBYTE(v64) = 2;
      string::dtor((basic_string *)&v57);
      }
    }
    else
    {
      string::string((basic_string *)&v37, L"IDS_REMOVE_ADVERTISEMENT_CODE_INVALID");// 无效的免广告码。
      LOBYTE(v64) = 5;
      v13 = SkinUI::GetString((basic_string *)&v41, (basic_string *)&v37);
      //......
    }

很明显 5EE630 就是验证广告码的函数了, 下个断点调试一下, 可以确定第二个参数是我们输入的广告码, 进去看看是怎么验证的
signed int __fastcall sub_5EE630(_BYTE *a1, basic_string *input_code, void **a3)
{
//

v16 = 0;
v14 = a1;
if ( input_code->_Mysize != 64 )            // 输入的密钥需要是64字节长
    return 1;
StrToHex((int)HexBuf, input_code);
IV = 0;
*(_DWORD *)&IV = 0;
*(_DWORD *)&IV = 0;
*(_DWORD *)&IV = 0;
*(_WORD *)&IV = 0;
IV = 0;
sub_8B46C0(&Aes_ctx, (int)"rdnRk8FezbqVDOGAHL520ymb1jWEoA60", 256);
// 对我们输入的 1234567890123456789012345678901234567890123456789012345678901234 进行解密, Key是上面的字符串
// 得到
// AE EB A0 12 AB 47 4C 44 93 EA D8 EB 14 A5 A4 CD
// E9 8D 5B 07 A7 D2 C9 7E 27 16 45 20 88 C6 DE 36
Aes((int)&Aes_ctx, 0, 32, IV, HexBuf, HexBuf);
*(_DWORD *)&IV = *(_DWORD *)&HexBuf;
*(_DWORD *)IV = *(_DWORD *)&HexBuf;
*(_DWORD *)&IV = *(_DWORD *)&HexBuf;
*(_DWORD *)&IV = *(_DWORD *)&HexBuf;
Aes((int)&Aes_ctx, 0, 16, IV, HexBuf, HexBuf);// 对解密的前16字节再进行解密得到, 后16字节做为IV
                                                // 7A 49 C0 9E E1 F7 03 73 7B BE E7 2B B8 FB 11 46
                                                //             ===========
v3 = ntohl(*(u_long *)&HexBuf);
Magic = v3;
if ( v3 != 0x8A19B74F && v3 != 0x8A19B75F )   // 上面标注的4字节需要是 这二个值之一
    return 1;
sub_594300((int)&HexBuf, &SelfId);
v23 = 0;
SelfIdNotSame = 0;
if ( sub_406D10(&SelfId, 0, SelfId._Mysize, (int)L"00000000", 8u) )// 自己的Id不为0
{
    v4 = sub_5ED7D0((basic_string *)&strCodeId);
    LOBYTE(v23) = 1;
    v16 = 1;
    if ( (unsigned __int8)sub_422A10(v4, &SelfId) )
      SelfIdNotSame = 1;
}
v23 = 0;
if ( v16 & 1 && *((_DWORD *)&strCodeId.strCodeId.Buf.pBuf + 3) >= 8u )
    operator delete(*(void **)&strCodeId.gap_0);
if ( SelfIdNotSame )
{
    if ( SelfId._Myres >= 8 )
      operator delete(SelfId.Buf.pBuf);
    return 1;
}
*a3 = (void *)ntohl(*(u_long *)&HexBuf);
strIV._Myres = 7;
strIV._Mysize = 0;
*(_WORD *)strIV.Buf.buf = 0;
LOBYTE(v23) = 2;
sub_593FC0(&strIV, (unsigned __int8 *)&HexBuf);// 我们用的IV值转换成字符串
v7 = dword_B3C698;
v8 = dword_B3C680;
v9 = sub_61C9C0(&dword_B3C680, &v16, &strIV);
v10 = (int)v9;
v11 = *v9;
if ( !v11 || v11 != v8 )
    CheckDebug0(v7, v8, v10);
if ( *(_DWORD *)(v10 + 4) != v7 || sub_631BC0(g_pSQLiteDatebase, &strIV) )// 用IV值查询数据库, 看能不能找到, 如果 CodeId 为 IV值的有数据记录, 则失败
                                                // 没有则成功
{
    string::dtor(&strIV);
    string::dtor(&SelfId);
    result = 2;
}
else
{
    sub_403FA0(&dword_B3C680);
    if ( Magic == 0x8A19B74F )    //添加积分码
    {
      *v14 = 0;
      v12 = &g_pOnlieInfo->u8;
      v13 = __CFADD__(*a3, g_pOnlieInfo->u8);
      *(_DWORD *)v12 += *a3;
      *((_DWORD *)v12 + 1) += v13;
      sub_5EEB80((int)&dword_B31E40);
      strCodeId.strCodeId._Myres = 7;
      strCodeId.strCodeId._Mysize = 0;
      *(_WORD *)strCodeId.strCodeId.Buf.buf = 0;
      LOBYTE(v23) = 3;
      string::substr(&strCodeId.strCodeId, &strIV, 0, 0xFFFFFFFF);
      UpdateCodeId(g_pSQLiteDatebase, (basic_string *)&strCodeId);// 重写CodeId
      sub_4C40D0(&strCodeId);
    }
    else if ( Magic == 0x8A19B75F )
    {
      *v14 = 1;
      if ( (unsigned int)*a3 <= (unsigned int)g_time64_NoAdv )
      *a3 = (void *)g_time64_NoAdv;
      else
      WriteNoAdvTime(*a3);
    }
    string::dtor(&strIV);
    string::dtor(&SelfId);
    result = 0;
}
return result;
}

经过对此函数的分析, 广告码的生成方法为:
构造原始数据16字节
16字节分为4个DWORD第一个随意, 第二个是固定值 0x8A19B75F, 第三个DWORD是自己的ID值, 第四个DWORD是到期时长
生成算法如下:      DWORD id = _byteswap_ulong(wcstoul(strID, NULL, 16));
      BYTE InitValue[] = { 0x11,0x22,0x33,0x44,0x8A,0x19,0xB7,0x5F,0,0,0,0, 0x7D, 0x0D, 0, 0x79 };
      *(DWORD*)(InitValue + 8) = id;

      BYTE ivec = {
                0xE9, 0x8D, 0x5B, 0x07, 0xA7, 0xD2, 0xC9, 0x7E,
                0x27, 0x16, 0x45, 0x20, 0x88, 0xC6, 0xDE, 0x36 };
      BYTE ivec_src = { 0 };
      BYTE out = { 0 };
      BYTE src = { 0 };
      memset(src, 0, 32);
      memcpy(src, InitValue, 16);
      memcpy(ivec_src, ivec, 16);

      AES_KEY aeskey;
      AES_set_encrypt_key((BYTE*)"rdnRk8FezbqVDOGAHL520ymb1jWEoA60", 256, &aeskey);
      AES_cbc_encrypt(InitValue, out, 16, &aeskey, ivec, 1);
      memcpy(src, out, 16);
      memcpy(src + 16, ivec_src, 16);
      memset(ivec, 0, 16);
      AES_cbc_encrypt(src, out, 32, &aeskey, ivec, 1);

      CString result;
      for(int i=0; i<32; i++)
      {
                CStringtmpstr;
                tmpstr.Format(L"%02X", out);
                result += tmpstr;
      }


至此, 去广告完成.

晚上又抽空看了一下, 积分码与去广告码算法相同, 只是一个标志不同
算号器也顺带更新一下









神皇 发表于 2019-4-17 14:04

喜欢小姐姐 发表于 2019-4-15 22:07
没有搞个算号机吗?那有什么用

教你怎么做菜还要给你做好了喂你吗?

喜欢小姐姐 发表于 2019-4-15 22:07

没有搞个算号机吗?那有什么用

kamtang6688 发表于 2019-4-26 08:27

用算号器获取的积分无法开通,大神如果能把红名昵称 姓名加冠 排名优先功能破解就更完美!

dragontiger 发表于 2019-4-15 22:14

谢谢分享谢谢分享

lwxzero 发表于 2019-4-15 22:14

多谢发布

shaokui123 发表于 2019-4-15 22:26

厉害厉害谢谢

缘下有我 发表于 2019-4-16 00:00

提供技术支持,就是舒服。

cxw0102 发表于 2019-4-16 00:24


厉害厉害
吾爱破解论坛最帅的人是谁?答案:Hmily

dakjwx2015 发表于 2019-4-16 07:42

谢谢分享

huzpsb 发表于 2019-4-16 07:46

喜欢小姐姐 发表于 2019-4-15 22:07
没有搞个算号机吗?那有什么用

不要当伸手党
最后一个算法就是算号机。

ufoboyxj 发表于 2019-4-16 08:07

技术控,支持了,学习下
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: XX通3.4.3045 去广告码, 积分码算法分析(2019.4.30更新)