Windows逆向学习笔记——Source Insight 4 注册机制研究

目录

    • 前言
    • 环境准备
    • 0、简单po jie:修改两字节
    • 1、验证序列号的过程——逆向分析
      • 1.1 定位“Serial Number错误”弹窗代码
      • 1.2 Serial Number验证函数 分析
      • 1.3 构造可用的Serial Number
      • 1.4 验证Serial Number
    • 2、验证RSA签名的过程——逆向分析
      • 2.1 验证RSA签名的流程
      • 2.2 简单的po jie
      • 2.3 自签名license文件po jie
        • 2.2.1 Base64Decode函数
        • 2.2.2 VerifySignature函数
        • 2.2.3 自签名 si4.lic 文件
    • 3. 在线检查序列号

前言

这里po jie的是当前最新版本Source Insight 4.0.118,总结po jie过程有以下三个部分:

  1. 逆向Serial Number序列号验证算法,构造可用序列号
  2. 逆向分析验证license签名过程,自签名license文件,并使用自己的公钥替换程序中原始公钥
  3. 程序运行起来后,会单独开启一个线程在线检查Serial Number是否有效,需要修改二进制文件过掉此检查

除此之外,笔者也看到其他人的一些文章,提到有黑名单检查,因为没遇到这个逻辑,程序暂时也能用,所以这里的破解中没有涉及,后面如果遇到再研究也不迟。

文中用到的所有代码可点击右侧超链接,在 Github上查看

环境准备

IDA6.8、x32dbg
官网 下载sourceinsight40118-setup.exe,也可使用文后附件

0、简单po jie:修改两字节

这部分内容讲述简单po jie程序的方法,因为本文主要是研究自签名license并替换程序中公钥的po jie方法,比较麻烦,纯粹是为了学习目的。如果对这种方法不感兴趣,这部分内容就提供另一种简单的po jie方法:修改 sourceinsight4.exe 二进制文件中的两个字节完成po jie

  • 第一处是 VA=005141A8FA=1135A8,将 74 改为 EB,原因可参考 第 2.2 节
  • 第二处是 VA=00513470FA=112870,将 83 改为 C3,原因可参考 第 3 节
    最后,将文后的附件 si4.lic 放到 C:\ProgramData\Source Insight\4.0 文件夹中即可po jie程序
    Windows逆向学习笔记——Source Insight 4 注册机制研究_第1张图片

1、验证序列号的过程——逆向分析

这部分内容分4个小节:
1.1 节 讲述如何定位到验证序列号的代码
1.2 节 中逆向还原验证序列号格式的函数,并按照格式构造出正式版序列号
1.3 节 中逆向还原本地校验序列号的函数,构造出可通过本地校验的序列号
1.4 节 本地验证序列号成功后,在线验证序列号失败,从而引出 第 2 节 的分析

1.1 定位“Serial Number错误”弹窗代码

安装程序后,打开sourceinsight4.exe程序会看到选择license文件的界面,如下图:
Windows逆向学习笔记——Source Insight 4 注册机制研究_第2张图片
选择第一项“输入serial number”,点击“Next >”继续,显示输入Serial Number的对话框,并且提示 Serial Number 的格式“S4XX-XXXX-XXXX-XXXX”。按照格式输入一个,点击"Next>",会弹出“无效的Serial Number”警告,如下图:
Windows逆向学习笔记——Source Insight 4 注册机制研究_第3张图片
在IDA中搜索弹窗警告中的文本“The serial number …”,找到引用此字符串的地址是 .text:00513A69

分析*.text:00513A69*此位置上下文代码,可以看出 .text:00513A45 call sub_510B50 是Serial Number的验证函数,若验证失败(返回结果0),则会再判断是否是3.x版本的Serail Number,不是则弹出上图中的警告;若验证成功则跳转到 loc_513ACB 继续判断验证结果。代码如下所示:

.text:00513A25                 mov     eax, dword_673488
.text:00513A2A                 push    1               ; int
.text:00513A2C                 lea     ecx, [eax+604h]
.text:00513A32                 push    ecx             ; int
.text:00513A33                 lea     edx, [eax+60Ch]
.text:00513A39                 push    edx             ; int
.text:00513A3A                 add     eax, 608h
.text:00513A3F                 push    eax             ; int
.text:00513A40                 lea     eax, [esp+158h+MultiByteStr]
.text:00513A44                 push    eax             ; char *
.text:00513A45                 call    sub_510B50      ; 验证Serial Number是否正确
.text:00513A4A                 add     esp, 34h
.text:00513A4D                 test    eax, eax        ; eax = 0, 弹出错误窗口并返回
.text:00513A4D                                         ; eax!= 0, 继续验证Serial Number格式
.text:00513A4F                 jnz     short loc_513ACB
.text:00513A51                 lea     ecx, [esp+128h+MultiByteStr]
.text:00513A55                 push    ecx
.text:00513A56                 call    sub_561CB0
.text:00513A5B                 add     esp, 4
.text:00513A5E                 test    eax, eax
.text:00513A60                 jz      short loc_513A69
.text:00513A62                 push    offset aTheSerialNumbe ; "The serial number you entered is for ve"...
.text:00513A67                 jmp     short loc_513A6E
.text:00513A69 ; ---------------------------------------------------------------------------
.text:00513A69
.text:00513A69 loc_513A69:                             ; CODE XREF: sub_5139C0+A0j
.text:00513A69                 push    offset aTheSerialNum_0 ; "The serial number you entered is not co"...
.text:00513A6E
.text:00513A6E loc_513A6E:                             ; CODE XREF: sub_5139C0+A7j
.text:00513A6E                 call    sub_40AC20
.text:00513A73                 add     esp, 4
...                            ...
.text:00513ACA                 retn
.text:00513ACB ; ---------------------------------------------------------------------------
.text:00513ACB
.text:00513ACB loc_513ACB:                             ; CODE XREF: sub_5139C0+8Fj
...                            ...
.text:00513AE1                 cmp     [eax+604h], edx
.text:00513AE7                 jz      short loc_513B0D
.text:00513AE9                 push    offset aTheSerialNum_1 ; "The serial number you entered is for a "...
.text:00513AEE                 call    sub_40AC20
...                            ...
.text:00513B0C                 retn

1.2 Serial Number验证函数 分析

详细分析上面步骤中提到的 sub_510B50 处的序列号验证函数,总结出Serial Number的验证规则如下:
SerailNumber字符串长度必须为19(16个字符加上3个分隔符)
SerailNumber[0]必须等’S’
SerailNumber[1]是’0’-‘9’
SerailNumber[2]等于’T’表示Trial license试用许可,等于’B’表示Beta license测试许可,等于’S’表示Standard license标准许可,等于’U’表示Upgrade license升级许可
SerailNumber[3]等于 ‘G’、‘V’、‘R’ 其中之一
SerailNumber[6]等于 ‘R’、‘G’、‘D’、‘F’ 其中之一
SerialNumber的前12个字符经过函数 .text:00510C6B call sub_510320 转换后得到4个字符,与SerialNumber的最后4个字符必须相同
代码如下所示:

.text:00510B50 ; int __cdecl sub_510B50(char *, int, int, int, int)
.text:00510B50 sub_510B50      proc near               ; CODE XREF: .text:005129C4p
.text:00510B50                                         ; sub_5139C0+85p
.text:00510B50
.text:00510B50 ary4char        = dword ptr -18h
.text:00510B50 szSNTemp        = byte ptr -14h
.text:00510B50 ptr_szSN        = dword ptr  4
.text:00510B50                               
.text:00510B50 ptr_nSN[3]Flag  = dword ptr  8
.text:00510B50 ptr_nLicTypeFlag= dword ptr  0Ch
.text:00510B50 ptr_nVersionFlag= dword ptr  10h
.text:00510B50 arg_10          = dword ptr  14h
.text:00510B50
.text:00510B50                 sub     esp, 18h
.text:00510B53                 push    esi
.text:00510B54                 mov     esi, [esp+1Ch+ptr_szSN]
.text:00510B58                 push    esi             ; char *
.text:00510B59                 call    __strupr
.text:00510B5E                 push    esi             ; char *
.text:00510B5F                 call    _strlen
.text:00510B64                 add     esp, 8
.text:00510B67                 cmp     eax, 13h        ; strlen(ptr_szSN) == 13h
.text:00510B6A                 jnz     loc_510C86
.text:00510B70                 mov     al, '-'
.text:00510B72                 cmp     [esi+4], al     ; ptr_szSN[4] = '-'
.text:00510B75                 jnz     loc_510C86
.text:00510B7B                 cmp     [esi+9], al     ; ptr_szSN[9] = '-'
.text:00510B7E                 jnz     loc_510C86
.text:00510B84                 cmp     [esi+0Eh], al   ; ptr_szSN[14] = '-'
.text:00510B87                 jnz     loc_510C86
.text:00510B8D                 cmp     byte ptr [esi], 'S' ; ptr_szSN[0] = 'S'
.text:00510B90                 jnz     loc_510C86
.text:00510B96                 mov     ecx, [esp+1Ch+arg_10]
.text:00510B9A                 test    ecx, ecx
.text:00510B9C                 jz      short loc_510BB5
.text:00510B9E                 mov     al, [esi+6]
.text:00510BA1                 cmp     al, 'R'         ; ptr_szSN[6] == 'R'
.text:00510BA3                 jz      short loc_510BB5
.text:00510BA5                 cmp     al, 'G'         ; ptr_szSN[6] == 'G'
.text:00510BA7                 jz      short loc_510BB5
.text:00510BA9                 cmp     al, 'D'         ; ptr_szSN[6] == 'D'
.text:00510BAB                 jz      short loc_510BB5
.text:00510BAD                 cmp     al, 'F'         ;

你可能感兴趣的:(Windows逆向,windows,visual,studio)