【软件名称】Editplus 2.20 Build 284
【原创作者】forever[RCT]
【目标语言】VC
【保护方式】注册码
【保护级别】难
【使用工具】PEiD,ollydgb,ida
【目标简介】 EditPlus 是 Internet 时代的 32 位文本编辑程序,HTML 编辑及程序员的Windows 平台编辑器。它可以充分的替换记事本,它也提供网页作家及程序设计师许多强悍的功能。对于 HTML、CSS、PHP、ASP、Perl、C/C++、Java、JavaScript 及 VBScript的语法突显。当然,它也可以在自定义语法文件后扩充其他的程序语言。嵌合网页浏览器作 HTML 页的预览,及 FTP 命令做本地文件上传到 FTP 服务器。其他功能还包含 HTML 工具栏、用户工具、列号、标尺、URL 突显。自动完成、剪贴文本、行列选择、强大的搜索与替换、多重撤消/重做、拼写检测、自定义键盘快捷键、以及更多。
【下载地址】http://www1.skycn.com/soft/3640.html
【正文】
这个软件的算法并不难,难的是如果把分散在各处的验证找全。我看了一下前面的分析,对比这个版本变化不大。在看雪精华4里有篇夜月的分析应该算是比较全的了。夜月所提到的那个核心算法其实就是C函数sprintf。我这篇分析大体也是这个思路。所以找到的仍然是对前10位注册码的验证。那么还有必要写这篇分析吗?我是这样想的:既然程序是用C语言来编写的,当然也能把算法用C语言还原回去。因此下面的分析是用C语言描述的。
这篇分析可能没找到全部的验证,如果你在使用中有什么新的发现,请告诉我。我不胜感激!
在ida里跟踪sprintf函数:
来到下面:
这个图片有点小,让我们放大它:
好了。数数,共有22处引用sprintf这个函数的。这22处不是每一处都是判断注册码的。在分别查看过后整理如下:
地址 判断注册码第几位
41DAF0 7
42E490 10
477EE0 8
483E80 11
4872E0 5
4876F0 1,2,3,4
4A427E 9
下面就分别看看每一处:
第1处:
.text:0041DAF0 sub_41DAF0 proc near
.text:0041DAF0 var_20 = dword ptr -20h
.text:0041DAF0 var_1C = dword ptr -1Ch
.text:0041DAF0 var_18 = dword ptr -18h
.text:0041DAF0 var_C = dword ptr -0Ch
.text:0041DAF0 var_4 = dword ptr -4
.text:0041DAF0
.text:0041DAF0 push 0FFFFFFFFh
.text:0041DAF2 push offset unknown_libname_635
.text:0041DAF7 mov eax, large fs:0
.text:0041DAFD push eax
.text:0041DAFE mov large fs:0, esp
.text:0041DB05 sub esp, 14h
.text:0041DB08 push ebp
.text:0041DB09 push esi
.text:0041DB0A mov esi, ecx
.text:0041DB0C push edi
.text:0041DB0D mov [esp+2Ch+var_20], esi
.text:0041DB11 mov dword ptr [esi], offset off_4FBA60
.text:0041DB17 mov dword_52E9D8, 0
.text:0041DB21 mov eax, [esi+2B8h]
.text:0041DB27 mov [esp+2Ch+var_4], 0Bh
.text:0041DB2F mov cx, [eax]
.text:0041DB32 cmp cx, 7D0h
.text:0041DB37 ja short loc_41DB4A
.text:0041DB39 jnz loc_41DBE5
.text:0041DB3F cmp word ptr [eax+2], 2
.text:0041DB44 jbe loc_41DBE5
.text:0041DB4A
.text:0041DB4A loc_41DB4A:
.text:0041DB4A mov ax, [eax+4]
.text:0041DB4E cmp ax, 1
.text:0041DB52 jz short loc_41DB5E
.text:0041DB54 cmp ax, 2
.text:0041DB58 jnz loc_41DBE5
.text:0041DB5E
.text:0041DB5E loc_41DB5E:
.text:0041DB5E mov eax, [esi+2B0h]
.text:0041DB64 mov ebp, [eax] //取用户名
.text:0041DB66 mov edi, [ebp-8] //长度小于等于0则跳
.text:0041DB69 test edi, edi
.text:0041DB6B jle short loc_41DBE5
.text:0041DB6D xor eax, eax
.text:0041DB6F mov ecx, 1 //初值1
.text:0041DB74 test edi, edi
.text:0041DB76 jle short loc_41DB84
.text:0041DB78
.text:0041DB78 loc_41DB78:
.text:0041DB78 xor edx, edx
.text:0041DB7A mov dl, [eax+ebp]
.text:0041DB7D add ecx, edx //用户名ASCII值累加
.text:0041DB7F inc eax
.text:0041DB80 cmp eax, edi
.text:0041DB82 jl short loc_41DB78
.text:0041DB84
.text:0041DB84 loc_41DB84:
.text:0041DB84 add ecx, 17h //加上23
.text:0041DB87 mov eax, 2AAAAAABh
.text:0041DB8C imul ecx //除以6
.text:0041DB8E mov eax, edx
.text:0041DB90 shr eax, 1Fh
.text:0041DB93 lea eax, [edx+eax+3] //加上3
.text:0041DB97 lea ecx, ds:0[eax*8] //乘以7
.text:0041DB9E sub ecx, eax
.text:0041DBA0 and ecx, 8000000Fh //模16
.text:0041DBA6 jns short loc_41DBAD
.text:0041DBA8 dec ecx
.text:0041DBA9 or ecx, 0FFFFFFF0h
.text:0041DBAC inc ecx
.text:0041DBAD
.text:0041DBAD loc_41DBAD:
.text:0041DBAD push ecx
.text:0041DBAE lea edx, [esp+30h+var_18]
.text:0041DBB2 push offset off_523498 ;'%1X'
.text:0041DBB7 push edx
.text:0041DBB8 call _sprintf //转换成字符串
.text:0041DBBD mov eax, [esi+2B4h]
.text:0041DBC3 add esp, 0Ch
.text:0041DBC6 mov eax, [eax] //取注册码
.text:0041DBC8 cmp dword ptr [eax-8], 7 //长度小于7则跳
.text:0041DBCC jl short loc_41DBD9
.text:0041DBCE mov al, [eax+6] //取注册码第7个字节
.text:0041DBD1 mov cl, byte ptr [esp+2Ch+var_18] //取上面字符串的第1个字节
.text:0041DBD5 cmp al, cl //比较
.text:0041DBD7 jz short loc_41DBE5
.text:0041DBD9
.text:0041DBD9 loc_41DBD9:
.text:0041DBD9 mov ecx, [esi+2BCh]
.text:0041DBDF mov dword ptr [ecx], 1 //比较失败置标志
.text:0041DBE5
.text:0041DBE5 loc_41DBE5:
这一段逆向如下:
int fun1(char *name,char *code)
{
int sum,i;
char buf[12];
if(strlen(name) <= 0)return 0;
sum = 1;
for(i = 0; i < strlen(name); i++)sum += name[i];
sum = ((sum + 23) / 6 + 3) * 7 % 16;
sprintf(buf,"%1X",sum);
if(strlen(code) < 7)return 0;
if(code[6] != buf[0])return 0;
else return 1;
}
第2处:
.text:0042E490 sub_42E490 proc near
.text:0042E490
.text:0042E490 var_20 = dword ptr -20h
.text:0042E490 var_1C = dword ptr -1Ch
.text:0042E490 var_18 = dword ptr -18h
.text:0042E490 var_C = dword ptr -0Ch
.text:0042E490 var_4 = dword ptr -4
.text:0042E490
.text:0042E490 push 0FFFFFFFFh
.text:0042E492 push offset unknown_libname_698
.text:0042E497 mov eax, large fs:0
.text:0042E49D push eax
.text:0042E49E mov large fs:0, esp
.text:0042E4A5 sub esp, 14h
.text:0042E4A8 push ebp
.text:0042E4A9 push esi
.text:0042E4AA mov esi, ecx
.text:0042E4AC push edi
.text:0042E4AD mov [esp+2Ch+var_20], esi
.text:0042E4B1 mov dword ptr [esi], offset off_4FC678
.text:0042E4B7 mov [esp+2Ch+var_4], 16h
.text:0042E4BF call sub_431350
.text:0042E4C4 mov eax, [esi+484h]
.text:0042E4CA mov cx, [eax]
.text:0042E4CD cmp cx, 7D0h
.text:0042E4D2 ja short loc_42E4E5
.text:0042E4D4 jnz loc_42E57C
.text:0042E4DA cmp word ptr [eax+2], 6
.text:0042E4DF jbe loc_42E57C
.text:0042E4E5
.text:0042E4E5 loc_42E4E5:
.text:0042E4E5 mov ax, [eax+4]
.text:0042E4E9 cmp ax, 3
.text:0042E4ED jz short loc_42E4F9
.text:0042E4EF cmp ax, 4
.text:0042E4F3 jnz loc_42E57C
.text:0042E4F9
.text:0042E4F9 loc_42E4F9:
.text:0042E4F9 cmp dword_52EAE4, 4E4h
.text:0042E503 jnz short loc_42E57C
.text:0042E505 mov eax, [esi+47Ch]
.text:0042E50B mov ebp, [eax] //取用户名
.text:0042E50D mov edi, [ebp-8]
.text:0042E510 test edi, edi
.text:0042E512 jle short loc_42E57C //长度小于等于0则跳
.text:0042E514 xor eax, eax
.text:0042E516 mov ecx, 1 //初值1
.text:0042E51B test edi, edi
.text:0042E51D jle short loc_42E52B
.text:0042E51F
.text:0042E51F loc_42E51F:
.text:0042E51F xor edx, edx
.text:0042E521 mov dl, [eax+ebp]
.text:0042E524 add ecx, edx //用户名ASCII值累加
.text:0042E526 inc eax
.text:0042E527 cmp eax, edi
.text:0042E529 jl short loc_42E51F
.text:0042E52B
.text:0042E52B loc_42E52B:
.text:0042E52B lea eax, [ecx+ecx*2+27h] //乘以3加上39
.text:0042E52F cdq
.text:0042E530 and edx, 7
.text:0042E533 add eax, edx
.text:0042E535 sar eax, 3 //除以8
.text:0042E538 and eax, 8000000Fh //模16
.text:0042E53D jns short loc_42E544
.text:0042E53F dec eax
.text:0042E540 or eax, 0FFFFFFF0h
.text:0042E543 inc eax
.text:0042E544
.text:0042E544 loc_42E544:
.text:0042E544 push eax
.text:0042E545 lea eax, [esp+30h+var_18]
.text:0042E549 push offset off_523498 ; "%1X"
.text:0042E54E push eax
.text:0042E54F call _sprintf //转换成字符串
.text:0042E554 mov ecx, [esi+480h]
.text:0042E55A add esp, 0Ch
.text:0042E55D mov eax, [ecx] //取注册码
.text:0042E55F cmp dword ptr [eax-8], 10
.text:0042E563 jl short loc_42E570 //长度小于10则跳
.text:0042E565 mov al, [eax+9] //取注册码第10个字节
.text:0042E568 mov cl, byte ptr [esp+2Ch+var_18] //取字符串第1个字节
.text:0042E56C cmp al, cl //比较
.text:0042E56E jz short loc_42E57C
.text:0042E570
.text:0042E570 loc_42E570:
.text:0042E570 mov edx, [esi+488h]
.text:0042E576 mov dword ptr [edx], 1 //不等则置标志
.text:0042E57C
.text:0042E57C loc_42E57C:
这一段逆向如下:
int fun2(char *name,char *code)
{
int sum,i;
char buf[12];
if(strlen(name) <= 0)return 0;
sum = 1;
for(i = 0; i < strlen(name); i++)sum += name[i];
sum = (sum * 3 + 39) / 8 % 16;
sprintf(buf,"%1X",sum);
if(strlen(code) < 10)return 0;
if(code[9] != buf[0])return 0;
else return 1;
}
第3处:
.text:00477EE0 sub_477EE0 proc near
.text:00477EE0
.text:00477EE0 var_20 = dword ptr -20h
.text:00477EE0 var_1C = dword ptr -1Ch
.text:00477EE0 var_18 = dword ptr -18h
.text:00477EE0 var_C = dword ptr -0Ch
.text:00477EE0 var_4 = dword ptr -4
.text:00477EE0
.text:00477EE0 push 0FFFFFFFFh
.text:00477EE2 push offset unknown_libname_852
.text:00477EE7 mov eax, large fs:0
.text:00477EED push eax
.text:00477EEE mov large fs:0, esp
.text:00477EF5 sub esp, 14h
.text:00477EF8 push ebp
.text:00477EF9 push esi
.text:00477EFA mov esi, ecx
.text:00477EFC push edi
.text:00477EFD mov [esp+2Ch+var_20], esi
.text:00477F01 mov dword ptr [esi], offset off_4FF988
.text:00477F07 mov eax, [esi+384h]
.text:00477F0D mov [esp+2Ch+var_4], 1
.text:00477F15 push eax
.text:00477F16 call sub_4CDB37
.text:00477F1B mov eax, [esi+78h]
.text:00477F1E push eax
.text:00477F1F call sub_4CDB37
.text:00477F24 mov eax, [esi+37Ch]
.text:00477F2A add esp, 8
.text:00477F2D mov cx, [eax]
.text:00477F30 cmp cx, 7D0h
.text:00477F35 ja short loc_477F48
.text:00477F37 jnz loc_477FD7
.text:00477F3D cmp word ptr [eax+2], 3
.text:00477F42 jbe loc_477FD7
.text:00477F48
.text:00477F48 loc_477F48:
.text:00477F48 mov ax, [eax+4]
.text:00477F4C cmp ax, 3
.text:00477F50 jz short loc_477F58
.text:00477F52 cmp ax, 4
.text:00477F56 jnz short loc_477FD7
.text:00477F58
.text:00477F58 loc_477F58:
.text:00477F58 mov eax, [esi+374h]
.text:00477F5E mov ebp, [eax] //取注册码
.text:00477F60 mov edi, [ebp-8]
.text:00477F63 test edi, edi
.text:00477F65 jle short loc_477FD7 //长度小于等于0则跳
.text:00477F67 xor eax, eax
.text:00477F69 mov ecx, 1 //初值1
.text:00477F6E test edi, edi
.text:00477F70 jle short loc_477F7E
.text:00477F72
.text:00477F72 loc_477F72:
.text:00477F72 xor edx, edx
.text:00477F74 mov dl, [eax+ebp]
.text:00477F77 add ecx, edx //用户名ASCII值累加
.text:00477F79 inc eax
.text:00477F7A cmp eax, edi
.text:00477F7C jl short loc_477F72
.text:00477F7E
.text:00477F7E loc_477F7E:
.text:00477F7E lea ecx, [ecx+ecx*2+13h] //乘以3加上19
.text:00477F82 mov eax, 38E38E39h
.text:00477F87 imul ecx //除以9
.text:00477F89 sar edx, 1
.text:00477F8B mov eax, edx
.text:00477F8D shr eax, 1Fh
.text:00477F90 add edx, eax
.text:00477F92 and edx, 8000000Fh //模16
.text:00477F98 jns short loc_477F9F
.text:00477F9A dec edx
.text:00477F9B or edx, 0FFFFFFF0h
.text:00477F9E inc edx
.text:00477F9F
.text:00477F9F loc_477F9F:
.text:00477F9F push edx
.text:00477FA0 lea ecx, [esp+30h+var_18]
.text:00477FA4 push offset off_523498 ; "%1X"
.text:00477FA9 push ecx
.text:00477FAA call _sprintf //转换成字符串
.text:00477FAF mov edx, [esi+378h]
.text:00477FB5 add esp, 0Ch
.text:00477FB8 mov eax, [edx] //取注册码
.text:00477FBA cmp dword ptr [eax-8], 8
.text:00477FBE jl short loc_477FCB //长度小于8则跳
.text:00477FC0 mov al, [eax+7] //取注册码第8个字节
.text:00477FC3 mov cl, byte ptr [esp+2Ch+var_18] //取字符串第1个字节
.text:00477FC7 cmp al, cl //比较
.text:00477FC9 jz short loc_477FD7
.text:00477FCB
.text:00477FCB loc_477FCB:
.text:00477FCB mov eax, [esi+380h]
.text:00477FD1 mov dword ptr [eax], 1 //比较失败则置标志
.text:00477FD7
.text:00477FD7 loc_477FD7:
这一段逆向如下:
int fun3(char *name,char *code)
{
int sum,i;
char buf[12];
if(strlen(name) <= 0)return 0;
sum = 1;
for(i = 0; i < strlen(name); i++)sum += name[i];
sum = (sum * 3 + 19) / 9 % 16;
sprintf(buf,"%1X",sum);
if(strlen(code) < 8)return 0;
if(code[7] != buf[0])return 0;
else return 1;
}
第4处:
.text:00483E80 sub_483E80 proc near
.text:00483E80
.text:00483E80 var_1C = dword ptr -1Ch
.text:00483E80 var_18 = dword ptr -18h
.text:00483E80 var_C = dword ptr -0Ch
.text:00483E80 var_4 = dword ptr -4
.text:00483E80
.text:00483E80 push 0FFFFFFFFh
.text:00483E82 push offset unknown_libname_908
.text:00483E87 mov eax, large fs:0
.text:00483E8D push eax
.text:00483E8E mov large fs:0, esp
.text:00483E95 sub esp, 10h
.text:00483E98 push ebp
.text:00483E99 push esi
.text:00483E9A mov esi, ecx
.text:00483E9C mov [esp+24h+var_1C], esi
.text:00483EA0 mov dword ptr [esi], offset off_500FE0
.text:00483EA6 mov eax, [esi+258h]
.text:00483EAC mov [esp+24h+var_4], 4
.text:00483EB4 mov cx, [eax]
.text:00483EB7 cmp cx, 7D0h
.text:00483EBC ja short loc_483ECF
.text:00483EBE jnz loc_483F74
.text:00483EC4 cmp word ptr [eax+2], 5
.text:00483EC9 jbe loc_483F74
.text:00483ECF
.text:00483ECF loc_483ECF:
.text:00483ECF mov ax, [eax+4]
.text:00483ED3 cmp ax, 1
.text:00483ED7 jz short loc_483EE3
.text:00483ED9 cmp ax, 2
.text:00483EDD jnz loc_483F74
.text:00483EE3
.text:00483EE3 loc_483EE3:
.text:00483EE3 cmp dword_52EAE4, 3B5h
.text:00483EED jnz loc_483F74
.text:00483EF3 mov eax, [esi+250h]
.text:00483EF9 mov ebp, [eax] //取用户名
.text:00483EFB mov ecx, [ebp-8]
.text:00483EFE test ecx, ecx //长度小于等于0则跳
.text:00483F00 jle short loc_483F74
.text:00483F02 xor eax, eax
.text:00483F04 push edi
.text:00483F05 test ecx, ecx
.text:00483F07 mov edi, 1 //初值1
.text:00483F0C jle short loc_483F1A
.text:00483F0E
.text:00483F0E loc_483F0E:
.text:00483F0E xor edx, edx
.text:00483F10 mov dl, [eax+ebp]
.text:00483F13 add edi, edx //用户名ASCII值累加
.text:00483F15 inc eax
.text:00483F16 cmp eax, ecx
.text:00483F18 jl short loc_483F0E
.text:00483F1A
.text:00483F1A loc_483F1A:
.text:00483F1A lea ecx, [edi+0Ah] //加上10
.text:00483F1D mov eax, 55555556h
.text:00483F22 imul ecx //除以3
.text:00483F24 mov eax, edx
.text:00483F26 shr eax, 1Fh
.text:00483F29 add edx, eax
.text:00483F2B shl edx, 3 //乘以8
.text:00483F2E and edx, 8000000Fh //模16
.text:00483F34 jns short loc_483F3B
.text:00483F36 dec edx
.text:00483F37 or edx, 0FFFFFFF0h
.text:00483F3A inc edx
.text:00483F3B
.text:00483F3B loc_483F3B:
.text:00483F3B push edx
.text:00483F3C lea ecx, [esp+2Ch+var_18]
.text:00483F40 push offset off_523498 ; "%1X"
.text:00483F45 push ecx
.text:00483F46 call _sprintf //转换成字符串
.text:00483F4B mov edx, [esi+254h]
.text:00483F51 add esp, 0Ch
.text:00483F54 mov eax, [edx] //取注册码
.text:00483F56 pop edi
.text:00483F57 cmp dword ptr [eax-8], 11
.text:00483F5B jl short loc_483F68 //长度小于11则跳
.text:00483F5D mov al, [eax+0Ah] //取注册码第11个字节
.text:00483F60 mov cl, byte ptr [esp+24h+var_18] //取字符串第1个字节
.text:00483F64 cmp al, cl //比较
.text:00483F66 jz short loc_483F74
.text:00483F68
.text:00483F68 loc_483F68:
.text:00483F68 mov eax, [esi+25Ch]
.text:00483F6E mov dword ptr [eax], 1 //比较失败则置标志
.text:00483F74
.text:00483F74 loc_483F74:
这一段逆向如下:
int fun4(char *name,char *code)
{
int sum,i;
char buf[12];
if(strlen(name) <= 0)return 0;
sum = 1;
for(i = 0; i < strlen(name); i++)sum += name[i];
sum = (sum + 10) / 3 * 8 % 16;
sprintf(buf,"%1X",sum);
if(strlen(code) < 11)return 0;
if(code[10] != buf[0])return 0;
else return 1;
}
第5处:
.text:004872E0 sub_4872E0 proc near
.text:004872E0
.text:004872E0 var_1C = dword ptr -1Ch
.text:004872E0 var_18 = dword ptr -18h
.text:004872E0 var_C = dword ptr -0Ch
.text:004872E0 var_4 = dword ptr -4
.text:004872E0
.text:004872E0 push 0FFFFFFFFh
.text:004872E2 push offset unknown_libname_914
.text:004872E7 mov eax, large fs:0
.text:004872ED push eax
.text:004872EE mov large fs:0, esp
.text:004872F5 sub esp, 10h
.text:004872F8 push ebp
.text:004872F9 push esi
.text:004872FA push edi
.text:004872FB mov edi, ecx
.text:004872FD mov [esp+28h+var_1C], edi
.text:00487301 mov dword ptr [edi], offset off_5012A0
.text:00487307 mov eax, [edi+0D8h]
.text:0048730D mov [esp+28h+var_4], 1
.text:00487315 mov ebp, [eax] //取用户名
.text:00487317 mov esi, [ebp-8]
.text:0048731A test esi, esi
.text:0048731C jle short loc_48738E //长度小于等于0则跳
.text:0048731E xor eax, eax
.text:00487320 mov ecx, 1 //初值1
.text:00487325 test esi, esi
.text:00487327 jle short loc_487335
.text:00487329
.text:00487329 loc_487329:
.text:00487329 xor edx, edx
.text:0048732B mov dl, [eax+ebp]
.text:0048732E add ecx, edx //用户名ASCII值累加
.text:00487330 inc eax
.text:00487331 cmp eax, esi
.text:00487333 jl short loc_487329
.text:00487335
.text:00487335 loc_487335:
.text:00487335 lea ecx, [ecx+ecx*8+0Ah] //乘以9加上10
.text:00487339 mov eax, 55555556h
.text:0048733E imul ecx //除以3
.text:00487340 mov eax, edx
.text:00487342 shr eax, 1Fh
.text:00487345 lea ecx, [edx+eax+24h] //加上36
.text:00487349 and ecx, 8000000Fh //模16
.text:0048734F jns short loc_487356
.text:00487351 dec ecx
.text:00487352 or ecx, 0FFFFFFF0h
.text:00487355 inc ecx
.text:00487356
.text:00487356 loc_487356:
.text:00487356 push ecx
.text:00487357 lea edx, [esp+2Ch+var_18]
.text:0048735B push offset off_523498 ; "%1X"
.text:00487360 push edx
.text:00487361 call _sprintf //转换成字符串
.text:00487366 mov eax, [edi+0DCh]
.text:0048736C add esp, 0Ch
.text:0048736F mov eax, [eax] //取注册码
.text:00487371 cmp dword ptr [eax-8], 5
.text:00487375 jl short loc_487382 //长度小于5则跳
.text:00487377 mov al, [eax+4] //取注册码第5个字节
.text:0048737A mov cl, byte ptr [esp+28h+var_18] //取字符串第1个字节
.text:0048737E cmp al, cl //比较
.text:00487380 jz short loc_48738E
.text:00487382
.text:00487382 loc_487382:
.text:00487382 mov ecx, [edi+0E4h]
.text:00487388 mov dword ptr [ecx], 1 //不等则置标志
.text:0048738E
.text:0048738E loc_48738E:
这一段逆向如下:
int fun5(char *name,char *code)
{
int sum,i;
char buf[12];
if(strlen(name) <= 0)return 0;
sum = 1;
for(i = 0; i < strlen(name); i++)sum += name[i];
sum = ((sum * 9 + 10) / 3 + 36) % 16;
sprintf(buf,"%1X",sum);
if(strlen(code) < 5)return 0;
if(code[4] != buf[0])return 0;
else return 1;
}
第6处:
.text:004876F0 fun_4876F0 proc near
.text:004876F0
.text:004876F0 var_C = dword ptr -0Ch
.text:004876F0 arg_0_name = dword ptr 4
.text:004876F0 arg_4_code = dword ptr 8
.text:004876F0
.text:004876F0 sub esp, 0Ch
.text:004876F3 or ecx, 0FFFFFFFFh
.text:004876F6 xor eax, eax
.text:004876F8 push esi
.text:004876F9 mov esi, [esp+10h+arg_0_name]
.text:004876FD push edi
.text:004876FE mov edi, esi
.text:00487700 repne scasb
.text:00487702 not ecx
.text:00487704 dec ecx
.text:00487705 mov edi, ecx
.text:00487707 jnz short loc_48770F ; 用户名长度不为0则跳
.text:00487709 pop edi
.text:0048770A pop esi
.text:0048770B add esp, 0Ch
.text:0048770E retn
.text:0048770F loc_48770F:
.text:0048770F call InitTable1_487650 //初始化CRC16表
.text:00487714 push edi ; 长度
.text:00487715 push esi ; 用户名
.text:00487716 push 0
.text:00487718 call XorTable1_4876A0 //对用户名计算CRC16
.text:0048771D add esp, 0Ch
.text:00487720 and eax, 0FFFFh
.text:00487725 push eax
.text:00487726 lea eax, [esp+18h+var_C]
.text:0048772A push offset a02x_0 ; "%02X"
.text:0048772F push eax
.text:00487730 call _sprintf //CRC16结果转成字符串
.text:00487735 mov esi, [esp+20h+arg_4_code]
.text:00487739 mov al, byte ptr [esp+20h+var_C]
.text:0048773D add esp, 0Ch
.text:00487740 mov cl, [esi+2]
.text:00487743 lea edx, [esi+2]
.text:00487746 cmp cl, al //注册码第3个字节和字符串第1个字节比较
.text:00487748 jz short loc_487752
.text:0048774A pop edi
.text:0048774B xor eax, eax
.text:0048774D pop esi
.text:0048774E add esp, 0Ch
.text:00487751 retn
.text:00487752 loc_487752:
.text:00487752 mov al, [esi+3]
.text:00487755 mov cl, byte ptr [esp+14h+var_C+1]
.text:00487759 cmp al, cl //注册码第4个字节和字符串第2个字节比较
.text:0048775B jz short loc_487765
.text:0048775D pop edi
.text:0048775E xor eax, eax
.text:00487760 pop esi
.text:00487761 add esp, 0Ch
.text:00487764 retn
.text:00487765 loc_487765:
.text:00487765 mov edi, esi ; 注册码
.text:00487767 or ecx, 0FFFFFFFFh
.text:0048776A xor eax, eax
.text:0048776C repne scasb
.text:0048776E not ecx
.text:00487770 add ecx, -3
.text:00487773 push ecx ; len
.text:00487774 push edx ; &RegCode[2]
.text:00487775 push eax ; 0
.text:00487776 call XorTable1_4876A0 //对注册码第3个字节开始计算CRC16
.text:0048777B add esp, 0Ch
.text:0048777E and eax, 0FFFFh
.text:00487783 lea ecx, [esp+14h+var_C]
.text:00487787 push eax
.text:00487788 push offset a02x_0 ; "%02X"
.text:0048778D push ecx
.text:0048778E call _sprintf //CRC16结果转成字符串
.text:00487793 mov dl, [esi]
.text:00487795 mov al, byte ptr [esp+20h+var_C]
.text:00487799 add esp, 0Ch
.text:0048779C cmp dl, al //注册码第1个字节和字符串第1个字节比较
.text:0048779E jz short loc_4877A8
.text:004877A0 pop edi
.text:004877A1 xor eax, eax
.text:004877A3 pop esi
.text:004877A4 add esp, 0Ch
.text:004877A7 retn
.text:004877A8 loc_4877A8:
.text:004877A8 mov cl, [esi+1]
.text:004877AB mov dl, byte ptr [esp+14h+var_C+1]
.text:004877AF xor eax, eax
.text:004877B1 cmp cl, dl //注册码第2个字节和字符串第2个字节比较
.text:004877B3 pop edi
.text:004877B4 pop esi
.text:004877B5 setz al
.text:004877B8 add esp, 0Ch
.text:004877BB retn
.text:004877BB fun_4876F0 endp
这一段也是在注册对话框部分验证的。这一段逆向如下:
int fun6(char *name,char *code)
{
int sum,i;
char buf[12];
short int tmp;
tmp = crc16(name,strlen(name);
tmp = tmp & 0xffff;
sprintf(buf,"%02X",tmp);
if(code[2] != buf[0])return 0;
if(code[3] != buf[1])return 0;
tmp = crc16(&code[2],strlen(code)-2);
tmp = tmp & 0xffff;
sprintf(buf,"%02X",tmp);
if(code[0] != buf[0])return 0;
if(code[1] != buf[1])return 0;
return 1;
}
第7处:
.text:004A4220 sub_4A4220 proc near
.text:004A4220
.text:004A4220 var_1C = dword ptr -1Ch
.text:004A4220 var_18 = dword ptr -18h
.text:004A4220 var_C = dword ptr -0Ch
.text:004A4220 var_4 = dword ptr -4
.text:004A4220
.text:004A4220 push 0FFFFFFFFh
.text:004A4222 push offset unknown_libname_1063
.text:004A4227 mov eax, large fs:0
.text:004A422D push eax
.text:004A422E mov large fs:0, esp
.text:004A4235 sub esp, 10h
.text:004A4238 push ebp
.text:004A4239 push esi
.text:004A423A mov esi, ecx
.text:004A423C push edi
.text:004A423D mov [esp+28h+var_1C], esi
.text:004A4241 mov dword ptr [esi], offset off_503E48
.text:004A4247 mov eax, [esi+2D4h]
.text:004A424D mov [esp+28h+var_4], 0Ch
.text:004A4255 mov cx, [eax]
.text:004A4258 cmp cx, 7D0h
.text:004A425D ja short loc_4A4270
.text:004A425F jnz loc_4A42FF
.text:004A4265 cmp word ptr [eax+2], 4
.text:004A426A jbe loc_4A42FF
.text:004A4270
.text:004A4270 loc_4A4270:
.text:004A4270 mov ax, [eax+4]
.text:004A4274 cmp ax, 5
.text:004A4278 jz short loc_4A4280
.text:004A427A cmp ax, 6
.text:004A427E jnz short loc_4A42FF
.text:004A4280
.text:004A4280 loc_4A4280:
.text:004A4280 mov eax, [esi+2CCh]
.text:004A4286 mov ebp, [eax] //取用户名
.text:004A4288 mov edi, [ebp-8]
.text:004A428B test edi, edi
.text:004A428D jle short loc_4A42FF //长度小于等于0则跳
.text:004A428F xor eax, eax
.text:004A4291 mov ecx, 1 //初值1
.text:004A4296 test edi, edi
.text:004A4298 jle short loc_4A42A6
.text:004A429A
.text:004A429A loc_4A429A:
.text:004A429A xor edx, edx
.text:004A429C mov dl, [eax+ebp]
.text:004A429F add ecx, edx //用户名ASCII值累加
.text:004A42A1 inc eax
.text:004A42A2 cmp eax, edi
.text:004A42A4 jl short loc_4A429A
.text:004A42A6
.text:004A42A6 loc_4A42A6:
.text:004A42A6 lea ecx, [ecx+ecx*4+0Bh] //乘以5加11
.text:004A42AA mov eax, 66666667h
.text:004A42AF imul ecx //除以5
.text:004A42B1 sar edx, 1
.text:004A42B3 mov eax, edx
.text:004A42B5 shr eax, 1Fh
.text:004A42B8 add edx, eax
.text:004A42BA and edx, 8000000Fh //模16
.text:004A42C0 jns short loc_4A42C7
.text:004A42C2 dec edx
.text:004A42C3 or edx, 0FFFFFFF0h
.text:004A42C6 inc edx
.text:004A42C7
.text:004A42C7 loc_4A42C7:
.text:004A42C7 push edx
.text:004A42C8 lea ecx, [esp+2Ch+var_18]
.text:004A42CC push offset off_523498 ; "%1X"
.text:004A42D1 push ecx
.text:004A42D2 call _sprintf //转换成字符串
.text:004A42D7 mov edx, [esi+2D0h]
.text:004A42DD add esp, 0Ch
.text:004A42E0 mov eax, [edx] //取注册码
.text:004A42E2 cmp dword ptr [eax-8], 9
.text:004A42E6 jl short loc_4A42F3 //长度小于9则跳
.text:004A42E8 mov al, [eax+8] //取第9个字节
.text:004A42EB mov cl, byte ptr [esp+28h+var_18] //取字符串第1个字节
.text:004A42EF cmp al, cl //比较
.text:004A42F1 jz short loc_4A42FF
.text:004A42F3
.text:004A42F3 loc_4A42F3:
.text:004A42F3 mov eax, [esi+2D8h]
.text:004A42F9 mov dword ptr [eax], 1 //不等则置标志
.text:004A42FF
.text:004A42FF loc_4A42FF:
这一段逆向如下:
int fun7(char *name,char *code)
{
int sum,i;
char buf[12];
if(strlen(name) <= 0)return 0;
sum = 1;
for(i = 0; i < strlen(name); i++)sum += name[i];
sum = (sum * 5 + 11) / 5 % 16;
sprintf(buf,"%1X",sum);
if(strlen(code) < 9)return 0;
if(code[8] != buf[0])return 0;
else return 1;
}
最后附上crc16的c源代码:
short int crc16table[] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
short int crc16(char *p,int len)
{
int i;
short int tmp = 0,tmp1;
if(len <= 0)return 0;
for(i = 0; i < len; i ++)
{
tmp = crc16table[(tmp & 0xff) ^ p[i]] ^ ((tmp >> 8) & 0xff);
}
return tmp;
}
这个表是在ollydbg中dump出来的,嘿嘿。
【全文完】
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)