- UID
- 74208
注册时间2014-3-1
阅读权限30
最后登录1970-1-1
龙战于野
TA的每日心情 | 无聊 2016-10-10 10:27 |
---|
签到天数: 26 天 [LV.4]偶尔看看III
|
【文章标题】Internet Download Manager 算法分析
【文章作者】BinGzL
【软件版本】Internet Download Manager v6.23 Build17
【保护方式】序列号
【作者声明】刚刚结束在科锐的学习生活,感谢钱老师以及科锐其他老师的教导。即将入职某公司,入职前分析些东西找找感觉。
【分析过程】
本文不阐述定位算法的过程,通过调试定位如下函数(看官可略过,看下面的分析):
刚进入函数就看到了获取注册信息的部分与初始化一张Key表
获取名字
- .text:004FFB31 lea eax, [ebp+szName]
- .text:004FFB3A push 32h ; cchMax
- .text:004FFB3E push eax ; lpString
- .text:004FFB3F push 4B0h ; nIDDlgItem
- .text:004FFC4A call GetRegUserInfo
复制代码
获取姓氏
- .text:004FFC78 lea edx, [ebp+szSurName]
- .text:004FFC7E push 32h ; cchMax
- .text:004FFC80 push edx ; lpString
- .text:004FFC81 push 413h ; nIDDlgItem
- .text:004FFC88 call GetRegUserInfo
复制代码
获取EMail
- .text:004FFC9F lea ecx, [ebp+szEmail]
- .text:004FFCA5 push 32h ; cchMax
- .text:004FFCA7 push ecx ; lpString
- .text:004FFCA8 push 4A5h ; nIDDlgItem
- .text:004FFCAF call GetRegUserInfo
复制代码
获取序列号
- .text:004FFCC7 lea eax, [ebp+szSerialNum]
- .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 GetRegUserInfo proc near ; CODE XREF: IsRegister+13Ap
- .text:005E30A4 ; IsRegister+178p ...
- .text:005E30A4
- .text:005E30A4 nIDDlgItem = dword ptr 8
- .text:005E30A4 lpString = dword ptr 0Ch
- .text:005E30A4 cchMax = dword ptr 10h
- .text:005E30A4
- .text:005E30A4 push ebp
- .text:005E30A5 mov ebp, esp
- .text:005E30A7 mov eax, [ecx+34h]
- .text:005E30AA test eax, eax
- .text:005E30AC jnz short loc_5E30C2
- .text:005E30AE push [ebp+cchMax] ; cchMax
- .text:005E30B1 push [ebp+lpString] ; lpString
- .text:005E30B4 push [ebp+nIDDlgItem] ; nIDDlgItem
- .text:005E30B7 push dword ptr [ecx+1Ch] ; 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 [ebp+cchMax]
- .text:005E30C5 mov edx, [eax]
- .text:005E30C7 mov ecx, eax
- .text:005E30C9 push [ebp+lpString]
- .text:005E30CC push [ebp+nIDDlgItem]
- .text:005E30CF call dword ptr [edx+78h]
- .text:005E30D2
- .text:005E30D2 loc_5E30D2: ; CODE XREF: GetRegUserInfo+1Cj
- .text:005E30D2 pop ebp
- .text:005E30D3 retn 0Ch
- .text:005E30D3 GetRegUserInfo endp
复制代码
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 [ebp+szSerialNum], dl
- .text:004FFCF9 jnz short loc_4FFD57 ;
复制代码
序列号转换与检查
- .text:004FFDAD lea edx, [ebp+szSerialNum]
- .text:004FFDB3 push edx ; char *
- .text:004FFDB4 call __strupr ; 序列号转换大写
- .text:004FFDB9 lea edi, [ebp+szSerialNum]
- .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, [ebp+szSerialNum+5]
- .text:004FFDD4 mov byte ptr [ebp+var_14+3], 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 [ebp+szSerialNum+0Bh], al ; 比较序列号第12位是否为'-'(0x2d)
- .text:004FFDE0 jnz short loc_4FFDE7 ; bSerialNumLog == TRUE
- .text:004FFDE2 cmp [ebp+szSerialNum+11h], al ; 比较序列号第18位是否为'-'(0x2d)
- .text:004FFDE5 jz short loc_4FFDEB
复制代码
由此可以确定系列号的格式为XXXXX-XXXXX-XXXXX-XXXXX,接下来又把4段系列号分别拷贝出来
- .text:004FFDEB lea eax, [ebp+szSerialNum]
- .text:004FFDF1 push 5 ; size_t
- .text:004FFDF3 lea ecx, [ebp+szSerialNum_0_4]
- .text:004FFDF6 push eax ; char *
- .text:004FFDF7 push ecx ; char *
- .text:004FFDF8 call _strncpy ; 获取0-4位的序列号
- .text:004FFDFD lea edx, [ebp+szSerialNum+6]
- .text:004FFE00 push 5 ; size_t
- .text:004FFE02 lea eax, [ebp+szSerialNum_6_10]
- .text:004FFE05 push edx ; char *
- .text:004FFE06 push eax ; char *
- .text:004FFE07 call _strncpy ; 获取6-10位序列号
- .text:004FFE0C lea ecx, [ebp+szSerialNum+0Ch]
- .text:004FFE0F push 5 ; size_t
- .text:004FFE11 lea edx, [ebp+szSerialNum_12_16]
- .text:004FFE14 push ecx ; char *
- .text:004FFE15 push edx ; char *
- .text:004FFE16 call _strncpy ; 获取12-16位序列号
- .text:004FFE1B lea eax, [ebp+szSerialNum+12h]
- .text:004FFE1E push 5 ; size_t
- .text:004FFE20 lea ecx, [ebp+szSerialNum_18_22]
- .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 [ebp+szSerialNum_0_4+5], 0 ; 为拷贝出来的每段加'\0'
- .text:004FFE33 mov [ebp+szSerialNum_6_10+5], 0
- .text:004FFE37 mov [ebp+szSerialNum_12_16+5], 0
- .text:004FFE3B mov [ebp+szSerialNum_18_22+5], 0 ;
复制代码
算法的准备工作就算完成了,接下来出现了四段一样的算法,如下
- .text:004FFE3F mov [ebp+dwResult0_4], 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, [ebp+esi+szSerialNum_0_4]
- .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[eax], 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, [edi+edi*8]
- .text:004FFE69 add ecx, edi
- .text:004FFE6B inc esi
- .text:004FFE6C lea edi, [ecx+edx*4] ; nData = nIndex + dwResult0_4 + (dwResult0_4 * 9) * 4;
- .text:004FFE6F mov [ebp+dwResult0_4], 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 [ebp+var_14+3], 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[j] == pData[i])
- {
- nIndex = j;
- nData = nIndex + nData + (nData * 9) * 4;
- i++;
- break;
- }
- }
- }
- return nData;
- }
复制代码
接下来在得到4段序列号计算出的值后,分别有对四个值做了校验
- 第一段
- .text:004FFF42 mov ecx, [ebp+dwResult0_4]
- .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 [ebp+dwResult6_10]
- .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自然也就是然并卵了。通杀补丁可以去飘云阁找飘哥的那份补丁。
|
评分
-
查看全部评分
|