Crack_Qs 发表于 2015-8-4 13:44:45

Internet Download Manager 算法分析

【文章标题】Internet Download Manager 算法分析
【文章作者】BinGzL
【软件版本】Internet Download Manager v6.23 Build17
【保护方式】序列号
【作者声明】刚刚结束在科锐的学习生活,感谢钱老师以及科锐其他老师的教导。即将入职某公司,入职前分析些东西找找感觉。
【分析过程】
本文不阐述定位算法的过程,通过调试定位如下函数(看官可略过,看下面的分析):
刚进入函数就看到了获取注册信息的部分与初始化一张Key表
获取名字
.text:004FFB31               lea   eax,
.text:004FFB3A               push    32h             ; cchMax
.text:004FFB3E               push    eax             ; lpString
.text:004FFB3F               push    4B0h            ; nIDDlgItem
.text:004FFC4A               call    GetRegUserInfo
获取姓氏
.text:004FFC78               lea   edx,
.text:004FFC7E               push    32h             ; cchMax
.text:004FFC80               push    edx             ; lpString
.text:004FFC81               push    413h            ; nIDDlgItem
.text:004FFC88               call    GetRegUserInfo
获取EMail
.text:004FFC9F               lea   ecx,
.text:004FFCA5               push    32h             ; cchMax
.text:004FFCA7               push    ecx             ; lpString
.text:004FFCA8               push    4A5h            ; nIDDlgItem
.text:004FFCAF               call    GetRegUserInfo
获取序列号
.text:004FFCC7               lea   eax,
.text:004FFCCD               push    32h             ; cchMax
.text:004FFCCF               push    eax             ; lpString
.text:004FFCD0               push    4AAh            ; nIDDlgItem
.text:004FFCD7               call    GetRegUserInfo

.text:005E30A4 ; int __stdcall GetRegUserInfo(int nIDDlgItem, LPSTR lpString, int cchMax)
.text:005E30A4 GetRegUserInfoproc near               ; CODE XREF: IsRegister+13Ap
.text:005E30A4                                       ; IsRegister+178p ...
.text:005E30A4
.text:005E30A4 nIDDlgItem      = dword ptr8
.text:005E30A4 lpString      = dword ptr0Ch
.text:005E30A4 cchMax          = dword ptr10h
.text:005E30A4
.text:005E30A4               push    ebp
.text:005E30A5               mov   ebp, esp
.text:005E30A7               mov   eax,
.text:005E30AA               test    eax, eax
.text:005E30AC               jnz   short loc_5E30C2
.text:005E30AE               push        ; cchMax
.text:005E30B1               push    ; lpString
.text:005E30B4               push    ; nIDDlgItem
.text:005E30B7               push    dword ptr ; hDlg
.text:005E30BA               call    ds:GetDlgItemTextA
.text:005E30C0               jmp   short loc_5E30D2
.text:005E30C2 ; ---------------------------------------------------------------------------
.text:005E30C2
.text:005E30C2 loc_5E30C2:                           ; CODE XREF: GetRegUserInfo+8j
.text:005E30C2               push   
.text:005E30C5               mov   edx,
.text:005E30C7               mov   ecx, eax
.text:005E30C9               push   
.text:005E30CC               push   
.text:005E30CF               call    dword ptr
.text:005E30D2
.text:005E30D2 loc_5E30D2:                           ; CODE XREF: GetRegUserInfo+1Cj
.text:005E30D2               pop   ebp
.text:005E30D3               retn    0Ch
.text:005E30D3 GetRegUserInfoendp

Key表内容为:
char g_KeyTable[] =
{
        0x32, 0x59, 0x4f, 0x50, 0x42, 0x33,
        0x41, 0x51, 0x43, 0x56, 0x55, 0x58,
        0x4d, 0x4e, 0x52, 0x53,        0x39, 0x37,
        0x57, 0x45, 0x30, 0x49, 0x5a, 0x44,
        0x34, 0x4b, 0x4c, 0x46, 0x47, 0x48,
        0x4a, 0x38, 0x31, 0x36, 0x35, 0x54
};

检查序列号是否为空
.text:004FFCF1               mov   dl, ' '         ; 0x20 == ' '
.text:004FFCF3               cmp   , dl
.text:004FFCF9               jnz   short loc_4FFD57 ;

序列号转换与检查
.text:004FFDAD               lea   edx,
.text:004FFDB3               push    edx             ; char *
.text:004FFDB4               call    __strupr      ; 序列号转换大写
.text:004FFDB9               lea   edi,
.text:004FFDBF               or      ecx, 0FFFFFFFFh
.text:004FFDC2               xor   eax, eax
.text:004FFDC4               add   esp, 4
.text:004FFDC7               repne scasb
.text:004FFDC9               not   ecx
.text:004FFDCB               dec   ecx
.text:004FFDCC               cmp   ecx, 23         ; 比较序列号是否为23位
.text:004FFDCF               jnz   short loc_4FFD69
.text:004FFDD1               mov   cl,
.text:004FFDD4               mov   byte ptr , al ; bSerialNumLog == FALSE
.text:004FFDD7               mov   al, 2Dh
.text:004FFDD9               cmp   cl, al          ; 比较序列号第6位是否为'-'(0x2d)
.text:004FFDDB               jnz   short loc_4FFDE7 ; bSerialNumLog == TRUE
.text:004FFDDD               cmp   , al ; 比较序列号第12位是否为'-'(0x2d)
.text:004FFDE0               jnz   short loc_4FFDE7 ; bSerialNumLog == TRUE
.text:004FFDE2               cmp   , al ; 比较序列号第18位是否为'-'(0x2d)
.text:004FFDE5               jz      short loc_4FFDEB
由此可以确定系列号的格式为XXXXX-XXXXX-XXXXX-XXXXX,接下来又把4段系列号分别拷贝出来
.text:004FFDEB               lea   eax,
.text:004FFDF1               push    5               ; size_t
.text:004FFDF3               lea   ecx,
.text:004FFDF6               push    eax             ; char *
.text:004FFDF7               push    ecx             ; char *
.text:004FFDF8               call    _strncpy      ; 获取0-4位的序列号
.text:004FFDFD               lea   edx,
.text:004FFE00               push    5               ; size_t
.text:004FFE02               lea   eax,
.text:004FFE05               push    edx             ; char *
.text:004FFE06               push    eax             ; char *
.text:004FFE07               call    _strncpy      ; 获取6-10位序列号
.text:004FFE0C               lea   ecx,
.text:004FFE0F               push    5               ; size_t
.text:004FFE11               lea   edx,
.text:004FFE14               push    ecx             ; char *
.text:004FFE15               push    edx             ; char *
.text:004FFE16               call    _strncpy      ; 获取12-16位序列号
.text:004FFE1B               lea   eax,
.text:004FFE1E               push    5               ; size_t
.text:004FFE20               lea   ecx,
.text:004FFE23               push    eax             ; char *
.text:004FFE24               push    ecx             ; char *
.text:004FFE25               call    _strncpy      ; 获取18-22位序列号
.text:004FFE2A               xor   edi, edi
.text:004FFE2C               add   esp, 30h
.text:004FFE2F               mov   , 0 ; 为拷贝出来的每段加'\0'
.text:004FFE33               mov   , 0
.text:004FFE37               mov   , 0
.text:004FFE3B               mov   , 0 ;

算法的准备工作就算完成了,接下来出现了四段一样的算法,如下
.text:004FFE3F               mov   , edi
.text:004FFE42               xor   esi, esi
.text:004FFE44
.text:004FFE44 loc_4FFE44:                           ; CODE XREF: IsRegister+362j
.text:004FFE44               cmp   esi, 5
.text:004FFE47               jge   short loc_4FFE7B ; nData = 0
.text:004FFE49               mov   dl,
.text:004FFE4D               or      ecx, 0FFFFFFFFh
.text:004FFE50               xor   eax, eax
.text:004FFE52
.text:004FFE52 loc_4FFE52:                           ; CODE XREF: IsRegister+365j
.text:004FFE52               cmp   eax, 36         ; KeyTable Len
.text:004FFE55               jge   short loc_4FFE61 ;
.text:004FFE55                                       ; ;
.text:004FFE57               cmp   g_szKeyTable, dl
.text:004FFE5D               jnz   short loc_4FFE74
.text:004FFE5F               mov   ecx, eax      ; nIndex = j
.text:004FFE61
.text:004FFE61 loc_4FFE61:                           ; CODE XREF: IsRegister+345j
.text:004FFE61               cmp   ecx, 0FFFFFFFFh
.text:004FFE64               jz      short loc_4FFE77
.text:004FFE66               lea   edx,
.text:004FFE69               add   ecx, edi
.text:004FFE6B               inc   esi
.text:004FFE6C               lea   edi, ; nData = nIndex + dwResult0_4 + (dwResult0_4 * 9) * 4;
.text:004FFE6F               mov   , edi ; dwResult = nData
.text:004FFE72               jmp   short loc_4FFE44
.text:004FFE74 ; ---------------------------------------------------------------------------
.text:004FFE74
.text:004FFE74 loc_4FFE74:                           ; CODE XREF: IsRegister+34Dj
.text:004FFE74               inc   eax
.text:004FFE75               jmp   short loc_4FFE52 ; KeyTable Len
.text:004FFE77 ; ---------------------------------------------------------------------------
.text:004FFE77
.text:004FFE77 loc_4FFE77:                           ; CODE XREF: IsRegister+354j
.text:004FFE77               mov   byte ptr , 1
分析过后得出如下代码:
int CIDMKeyGenDlg::GetCalcResult(char *pData)
{
        int i = 0, j = 0;
        int nIndex = 0;
        int nData = 0;

        while (i < 5)
        {
                for (j = 0; j < 36; j++)
                {
                        if (g_KeyTable == pData)
                        {
                                nIndex = j;
                                nData = nIndex + nData + (nData * 9) * 4;
                                i++;
                                break;
                        }
                }
        }
        return nData;
}

接下来在得到4段序列号计算出的值后,分别有对四个值做了校验
第一段
.text:004FFF42               mov   ecx,
.text:004FFF45               mov   esi, 43
.text:004FFF4A               mov   eax, ecx
.text:004FFF4C               cdq
.text:004FFF4D               idiv    esi
.text:004FFF4F               test    edx, edx
.text:004FFF51               jnz   short loc_4FFF57
第二段
.text:004FFF5B               mov   ecx, dword ptr
.text:004FFF5E               mov   esi, 23
.text:004FFF63               mov   eax, ecx
.text:004FFF65               cdq
.text:004FFF66               idiv    esi
.text:004FFF68               test    edx, edx
.text:004FFF6A               jnz   short loc_4FFF70
第三段
.text:004FFF74               mov   eax, ebx
.text:004FFF76               mov   ecx, 17
.text:004FFF7B               cdq
.text:004FFF7C               idiv    ecx
.text:004FFF7E               test    edx, edx
.text:004FFF80               jnz   short loc_4FFF86
第四段
.text:004FFF8A               mov   eax, edi
.text:004FFF8C               mov   ecx, 53
.text:004FFF91               cdq
.text:004FFF92               idiv    ecx
.text:004FFF94               test    edx, edx
.text:004FFF96               jnz   short loc_4FFFA3

剩下的就是保存注册信息的代码了,由此可以了解软件注册的验证流程为4段计算的值都可以整除一个值才可以注册。本以为到此结束....第二天用的时候打开弹出了让我心碎的提示

再次分析启动验证,发现是有网络验证,看来是不能够愉快的KeyGen了,这KeyGen自然也就是然并卵了。通杀补丁可以去飘云阁找飘哥的那份补丁。

昔邪 发表于 2015-8-4 15:55:10

该软件我已经在吾爱上面破解发布了 6.23.17.2

飘云 发表于 2015-8-4 16:22:29

不错了!
我那个没更新了,只适合6.1x

wkxq 发表于 2015-8-4 22:24:22

崇拜算法高手

wkxq 发表于 2015-8-4 22:24:46

本帖最后由 wkxq 于 2015-8-4 22:26 编辑

因网速问题,不好意思点重复了,请管理员删除此回复

menglv 发表于 2015-8-5 07:55:23

现在的idm似乎是正确的sn会网络验证,然并卵。还是用爆破吧!

menglv 发表于 2015-8-5 07:57:37

昔邪 发表于 2015-8-4 15:55
该软件我已经在吾爱上面破解发布了 6.23.17.2

其实这个软件并没有你想象的复杂,有兴趣可以看看我的优雅补丁,支持最新版的更新,只需要修改主程序的几处而已!

small-q 发表于 2015-8-5 08:50:02

一直用老漂的补丁,不用天天更新就下载而以

Crack_Qs 发表于 2015-8-5 09:51:33

飘云 发表于 2015-8-4 16:22
不错了!
我那个没更新了,只适合6.1x

你的补丁支持我这个版本

beijingren 发表于 2015-8-8 19:25:16

技术上来讲,不觉得这个然并卵,挺好的分析思路
页: [1] 2
查看完整版本: Internet Download Manager 算法分析