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自然也就是然并卵了。通杀补丁可以去飘云阁找飘哥的那份补丁。
该软件我已经在吾爱上面破解发布了 6.23.17.2 不错了!
我那个没更新了,只适合6.1x
崇拜算法高手 本帖最后由 wkxq 于 2015-8-4 22:26 编辑
因网速问题,不好意思点重复了,请管理员删除此回复
现在的idm似乎是正确的sn会网络验证,然并卵。还是用爆破吧! 昔邪 发表于 2015-8-4 15:55
该软件我已经在吾爱上面破解发布了 6.23.17.2
其实这个软件并没有你想象的复杂,有兴趣可以看看我的优雅补丁,支持最新版的更新,只需要修改主程序的几处而已!
一直用老漂的补丁,不用天天更新就下载而以 飘云 发表于 2015-8-4 16:22
不错了!
我那个没更新了,只适合6.1x
你的补丁支持我这个版本 技术上来讲,不觉得这个然并卵,挺好的分析思路
页:
[1]
2