【文章标题】: Techra Virtual Programmable Keyboard 1.02算法分析
【文章作者】: qifeon
【软件名称】: Techra Virtual Programmable Keyboard
【下载地址】: http://www.techrasoft.com/index.asp
【保护方式】: 注册码
【编写语言】: 英文
【操作平台】: winxp sp2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
一、分析过程
首先PEID查壳,Borland Delphi 6.0 - 7.0编写,无壳。运行程序,输入“qifeon,123456”,有错误提示"invalid unlock information"。好的,我们就利用最简单而有效的查找字符串的方法。
不要小瞧它哦,不必再去麻烦DeDe先生了。OD载入,插件查找上面的错误提示。
Ultra String Reference, 条目 3004
Address=0056D6B0
Disassembly=mov eax, 0056D7D4
Text String=invalid unlock information!
双击后来到
*******************************************************************************************************************************************************
0056D6A9 .^\E9 2A69E9FF jmp 00403FD8 ; 向上找到跳转
0056D6AE .^ EB F0 jmp short 0056D6A0
0056D6B0 > \B8 D4D75600 mov eax, 0056D7D4 ; invalid unlock information!
0056D6B5 . E8 C66AECFF call 00434180
0056D6BA . 8B83 18030000 mov eax, dword ptr [ebx+318]
0056D6C0 . 8B10 mov edx, dword ptr [eax]
0056D6C2 . FF92 C4000000 call dword ptr [edx+C4]
0056D6C8 > 33C0 xor eax, eax
0056D6CA . 5A pop edx
0056D6CB . 59 pop ecx
0056D6CC . 59 pop ecx
*****************************************************************************************************************************************************
由跳转向上找到注册按钮事件段首
*****************************************************************************************************************************************************
0056D536 . 55 push ebp ; 段首
0056D537 . 68 F8D65600 push 0056D6F8
0056D53C . 64:FF30 push dword ptr fs:[eax]
0056D53F . 64:8920 mov dword ptr fs:[eax], esp
0056D542 . 8D55 F8 lea edx, dword ptr [ebp-8]
0056D545 . 8B83 18030000 mov eax, dword ptr [ebx+318]
0056D54B . E8 7069EEFF call 00453EC0 ; 取用户名长度
0056D550 . 837D F8 00 cmp dword ptr [ebp-8], 0
0056D554 . 74 14 je short 0056D56A ; 用户名为空则跳
0056D556 . 8D55 F4 lea edx, dword ptr [ebp-C]
0056D559 . 8B83 1C030000 mov eax, dword ptr [ebx+31C]
0056D55F . E8 5C69EEFF call 00453EC0 ; 取试炼码长度
0056D564 . 837D F4 00 cmp dword ptr [ebp-C], 0 试炼码是否为空?
0056D568 . 75 1D jnz short 0056D587
0056D56A > B8 0CD75600 mov eax, 0056D70C ; please enter unlock information!
0056D56F . E8 0C6CECFF call 00434180
0056D574 . 8B83 18030000 mov eax, dword ptr [ebx+318]
0056D57A . 8B10 mov edx, dword ptr [eax]
0056D57C . FF92 C4000000 call dword ptr [edx+C4]
0056D582 . E9 41010000 jmp 0056D6C8
0056D587 > 8D55 F0 lea edx, dword ptr [ebp-10]
0056D58A . 8B83 1C030000 mov eax, dword ptr [ebx+31C]
0056D590 . E8 2B69EEFF call 00453EC0
0056D595 . 8B45 F0 mov eax, dword ptr [ebp-10] ; 试炼码放入eax
0056D598 . 50 push eax
0056D599 . 8D55 E8 lea edx, dword ptr [ebp-18]
0056D59C . 8B83 18030000 mov eax, dword ptr [ebx+318]
0056D5A2 . E8 1969EEFF call 00453EC0
0056D5A7 . 8B55 E8 mov edx, dword ptr [ebp-18] ; 用户名放入edx
0056D5AA . 8D4D EC lea ecx, dword ptr [ebp-14]
0056D5AD . A1 74B75800 mov eax, dword ptr [58B774]
0056D5B2 . 8B00 mov eax, dword ptr [eax]
0056D5B4 . E8 D3140000 call 0056EA8C ; 算法call,我们马上进入
0056D5B9 . 8B55 EC mov edx, dword ptr [ebp-14] ; 真正注册码
0056D5BC . 58 pop eax ; 试炼码
0056D5BD . E8 A274E9FF call 00404A64 ; 真正注册码与假码相比较
0056D5C2 . 0F85 E8000000 jnz 0056D6B0 ; 关键跳转
0056D5C8 . 33C0 xor eax, eax
0056D5CA . 55 push ebp
0056D5CB . 68 A9D65600 push 0056D6A9
0056D5D0 . 64:FF30 push dword ptr fs:[eax]
0056D5D3 . 64:8920 mov dword ptr fs:[eax], esp
0056D5D6 . B2 01 mov dl, 1
0056D5D8 . A1 489E4300 mov eax, dword ptr [439E48]
0056D5DD . E8 6AC9ECFF call 00439F4C
0056D5E2 . 8945 FC mov dword ptr [ebp-4], eax
0056D5E5 . BA 02000080 mov edx, 80000002
0056D5EA . 8B45 FC mov eax, dword ptr [ebp-4]
0056D5ED . E8 FAC9ECFF call 00439FEC
0056D5F2 . B1 01 mov cl, 1
0056D5F4 . BA 38D75600 mov edx, 0056D738 ; software\vpk
0056D5F9 . 8B45 FC mov eax, dword ptr [ebp-4]
0056D5FC . E8 2FCBECFF call 0043A130
0056D601 . 8D55 E4 lea edx, dword ptr [ebp-1C]
0056D604 . 8B83 18030000 mov eax, dword ptr [ebx+318]
0056D60A . E8 B168EEFF call 00453EC0
0056D60F . 8B45 E4 mov eax, dword ptr [ebp-1C]
0056D612 . 50 push eax
0056D613 . B9 50D75600 mov ecx, 0056D750 ; registeredto
0056D618 . 33D2 xor edx, edx
0056D61A . 8B45 FC mov eax, dword ptr [ebp-4]
0056D61D . E8 9ECFECFF call 0043A5C0
0056D622 . 8D55 E0 lea edx, dword ptr [ebp-20]
0056D625 . 8B83 1C030000 mov eax, dword ptr [ebx+31C]
0056D62B . E8 9068EEFF call 00453EC0
0056D630 . 8B45 E0 mov eax, dword ptr [ebp-20]
0056D633 . 50 push eax
0056D634 . B9 68D75600 mov ecx, 0056D768 ; unlockcode
0056D639 . 33D2 xor edx, edx
0056D63B . 8B45 FC mov eax, dword ptr [ebp-4]
0056D63E . E8 7DCFECFF call 0043A5C0
0056D643 . A1 74B75800 mov eax, dword ptr [58B774]
0056D648 . 8B00 mov eax, dword ptr [eax]
0056D64A . E8 FD120000 call 0056E94C
0056D64F . 84C0 test al, al
0056D651 . 74 2F je short 0056D682
0056D653 . B8 7CD75600 mov eax, 0056D77C ; software has been successfully unlocked!
0056D658 . E8 236BECFF call 00434180
0056D65D . A1 74B75800 mov eax, dword ptr [58B774]
0056D662 . 8B00 mov eax, dword ptr [eax]
0056D664 . 8B80 28030000 mov eax, dword ptr [eax+328]
0056D66A . 33D2 xor edx, edx
0056D66C . E8 078AEFFF call 00466078
0056D671 . C783 4C020000>mov dword ptr [ebx+24C], 1
0056D67B . E8 3C6AE9FF call 004040BC
0056D680 . EB 46 jmp short 0056D6C8
0056D682 > B8 B0D75600 mov eax, 0056D7B0 ; error unlocking software!
0056D687 . E8 F46AECFF call 00434180
0056D68C . E8 2B6AE9FF call 004040BC
*******************************************************************************************************************************************************
0056D5B4处,进入算法 call 0056EA8C
*********************************************************************************************************************************************8**********
0056EA8C $ 55 push ebp
0056EA8D . 8BEC mov ebp, esp
0056EA8F . 6A 00 push 0
0056EA91 . 6A 00 push 0
0056EA93 . 6A 00 push 0
0056EA95 . 6A 00 push 0
0056EA97 . 6A 00 push 0
0056EA99 . 53 push ebx
0056EA9A . 56 push esi
0056EA9B . 57 push edi
0056EA9C . 8BF9 mov edi, ecx
0056EA9E . 8955 FC mov dword ptr [ebp-4], edx
0056EAA1 . 8B45 FC mov eax, dword ptr [ebp-4]
0056EAA4 . E8 5F60E9FF call 00404B08
0056EAA9 . 33C0 xor eax, eax
0056EAAB . 55 push ebp
0056EAAC . 68 E2EB5600 push 0056EBE2
0056EAB1 . 64:FF30 push dword ptr fs:[eax]
0056EAB4 . 64:8920 mov dword ptr fs:[eax], esp
0056EAB7 . 33C0 xor eax, eax
0056EAB9 . 55 push ebp
0056EABA . 68 B5EB5600 push 0056EBB5
0056EABF . 64:FF30 push dword ptr fs:[eax]
0056EAC2 . 64:8920 mov dword ptr fs:[eax], esp
0056EAC5 . 8D45 F4 lea eax, dword ptr [ebp-C]
0056EAC8 . 8B4D FC mov ecx, dword ptr [ebp-4] ; 用户名
0056EACB . BA F8EB5600 mov edx, 0056EBF8 ; ASCII "TEST123"
0056EAD0 . E8 8F5EE9FF call 00404964 ; 连接固定字符串"TEST123"与用户名,设为link
0056EAD5 . 8B45 F4 mov eax, dword ptr [ebp-C]
0056EAD8 . 8BD7 mov edx, edi
0056EADA . E8 598AECFF call 00437538 ; 把连接后字符串link翻转,设为reverse
0056EADF . 33C0 xor eax, eax
0056EAE1 . 8945 F8 mov dword ptr [ebp-8], eax
0056EAE4 . 8B07 mov eax, dword ptr [edi]
0056EAE6 . E8 2D5EE9FF call 00404918
0056EAEB . 8BF0 mov esi, eax ; 字符串reverse长度设为len放入esi
0056EAED . 85F6 test esi, esi
0056EAEF . 7E 15 jle short 0056EB06
0056EAF1 . BB 01000000 mov ebx, 1 ; ebx=1
0056EAF6 > 8B07 mov eax, dword ptr [edi] ; 字符串reverse放入eax
0056EAF8 . 0FB64418 FF movzx eax, byte ptr [eax+ebx-1] ; 字符串reverse逐位取扩展放入eax
0056EAFD . F7EB imul ebx ; eax=eax*ebx
0056EAFF . 0145 F8 add dword ptr [ebp-8], eax ; [ebp-8]=[ebp-8]+eax,循环最后计算值保存于ebp-8,设为sum
0056EB02 . 43 inc ebx ; ebx增1
0056EB03 . 4E dec esi ; esi减1
0056EB04 .^ 75 F0 jnz short 0056EAF6 ; esi不为0则继续循环
0056EB06 > 8B07 mov eax, dword ptr [edi]
0056EB08 . E8 0B5EE9FF call 00404918
0056EB0D . 8BF0 mov esi, eax
0056EB0F . 85F6 test esi, esi
0056EB11 . 7E 3C jle short 0056EB4F
0056EB13 . BB 01000000 mov ebx, 1
0056EB18 > 8B07 mov eax, dword ptr [edi] ; 字符串reverse放入eax
0056EB1A . 0FB64418 FF movzx eax, byte ptr [eax+ebx-1] ; 字符串reverse逐位取扩展放入eax
0056EB1F . F7EB imul ebx ; eax=eax*ebx
0056EB21 . 83C0 02 add eax, 2 ; eax=eax+2
0056EB24 . 3345 F8 xor eax, dword ptr [ebp-8] ; eax=eax xor sum
0056EB27 . B9 0A000000 mov ecx, 0A ; ecx=0Ah
0056EB2C . 99 cdq ; edx清零
0056EB2D . F7F9 idiv ecx ; eax/ecx 商保存在 eax余数保存于edx
0056EB2F . 8BC2 mov eax, edx
0056EB31 . 8D55 F0 lea edx, dword ptr [ebp-10]
0056EB34 . E8 17A4E9FF call 00408F50 ; 把上面逐位计算的余数16进制数字转换为对应字符
0056EB39 . 8B45 F0 mov eax, dword ptr [ebp-10]
0056EB3C . 8A00 mov al, byte ptr [eax] ; 转换后字符放入al
0056EB3E . 50 push eax
0056EB3F . 8BC7 mov eax, edi
0056EB41 . E8 2A60E9FF call 00404B70
0056EB46 . 5A pop edx ; dl内的值等于上面al数值
0056EB47 . 885418 FF mov byte ptr [eax+ebx-1], dl ; dl值替换字符串reverse内字符
0056EB4B . 43 inc ebx
0056EB4C . 4E dec esi ; esi不为0则继续循环
0056EB4D .^ 75 C9 jnz short 0056EB18
0056EB4F > 8B07 mov eax, dword ptr [edi] ; reverse全部替换后得到字符串设为replace
0056EB51 . E8 C25DE9FF call 00404918
0056EB56 . 8BF0 mov esi, eax ; 字符串replace长度
0056EB58 . 85F6 test esi, esi
0056EB5A . 7E 3D jle short 0056EB99
0056EB5C . BB 01000000 mov ebx, 1
0056EB61 > 8B07 mov eax, dword ptr [edi] ; 字符串replace放入eax
0056EB63 . 0FB64418 FF movzx eax, byte ptr [eax+ebx-1] ; 字符串replace逐位取扩展放入eax
0056EB68 . F7EB imul ebx ; eax值乘以ebx
0056EB6A . 8BD0 mov edx, eax ; 相乘得值由eax放入edx
0056EB6C . C1E0 03 shl eax, 3 ; eax值左移3位
0056EB6F . 2BC2 sub eax, edx ; eax=eax-edx
0056EB71 . B9 0A000000 mov ecx, 0A ; ecx=10
0056EB76 . 99 cdq ; edx清零
0056EB77 . F7F9 idiv ecx ; eax/ecx 商保存在 eax余数保存于edx
0056EB79 . 8BC2 mov eax, edx ; 余数传送给eax
0056EB7B . 8D55 EC lea edx, dword ptr [ebp-14]
0056EB7E . E8 CDA3E9FF call 00408F50 ; 把上面逐位计算的余数16进制数字转换为对应字符
0056EB83 . 8B45 EC mov eax, dword ptr [ebp-14]
0056EB86 . 8A00 mov al, byte ptr [eax] ; 转换后字符放入al
0056EB88 . 50 push eax
0056EB89 . 8BC7 mov eax, edi
0056EB8B . E8 E05FE9FF call 00404B70
0056EB90 . 5A pop edx ; dl内的值等于上面al数值
0056EB91 . 885418 FF mov byte ptr [eax+ebx-1], dl ; dl值替换字符串reverse内字符
0056EB95 . 43 inc ebx
0056EB96 . 4E dec esi
0056EB97 .^ 75 C8 jnz short 0056EB61
0056EB99 > 57 push edi
0056EB9A . 8B07 mov eax, dword ptr [edi] ; replace全部替换后的字符串设为regcode
0056EB9C . B9 06000000 mov ecx, 6 ; ecx=6
0056EBA1 . BA 01000000 mov edx, 1
0056EBA6 . E8 CD5FE9FF call 00404B78 ; 取字符串regcode前6位作为注册码
0056EBAB . 33C0 xor eax, eax
0056EBAD . 5A pop edx
0056EBAE . 59 pop ecx
0056EBAF . 59 pop ecx
0056EBB0 . 64:8910 mov dword ptr fs:[eax], edx
0056EBB3 . EB 0A jmp short 0056EBBF
0056EBB5 .^ E9 6A51E9FF jmp 00403D24
0056EBBA . E8 CD54E9FF call 0040408C
0056EBBF > 33C0 xor eax, eax
0056EBC1 . 5A pop edx
0056EBC2 . 59 pop ecx
0056EBC3 . 59 pop ecx
0056EBC4 . 64:8910 mov dword ptr fs:[eax], edx
0056EBC7 . 68 E9EB5600 push 0056EBE9
0056EBCC > 8D45 EC lea eax, dword ptr [ebp-14]
0056EBCF . BA 03000000 mov edx, 3
0056EBD4 . E8 A35AE9FF call 0040467C
0056EBD9 . 8D45 FC lea eax, dword ptr [ebp-4]
0056EBDC . E8 775AE9FF call 00404658
0056EBE1 . C3 retn
*********************************************************************************************************************************************
二、注册算法总结
算法有些琐碎,经过多次转换。本人尝试描述清楚。
1、固定字符串"TEST123"与用户名name连接得到字符串link;
2、翻转字符串link得到字符串reverse;
3、字符reverse[i]乘以字符串对应位置(i+1)依次相加之和为sum;
4、字符reverse[i]乘以字符串对应位置(i+1),然后加上2,再与sum异或,异或后的值除以10,
余数转化为16进制对应的字符替换掉reverse[i],得到字符串replace;(如0x1转为字符"1")
5、字符replace[i]乘以字符串对应位置(i+1),所得数值左移3位,减去replace[i]*(i+1),再除以10,
余数转化为16进制对应的字符替换掉replace[i],得到字符串regcode;
6、取字符串regcode前6位组成的字符串即为注册码。
*************************************************************************************************************************************************
三、C语言注册机源码
#include "stdio.h"
#include "string.h"
void main()
{
int i,j,k,len,o,p;
static int sum=0;
char regcode[30];
char replace[30];
char reverse[30];
char name[30];
char link[30]="TEST123";
printf("请输入用户名:");
scanf("%s",name);
strcat (link,name);
strrev(link);
strcpy(reverse,link);
len=strlen(reverse);
for (i=0;i<len;i++)
sum=sum+reverse[i]*(i+1);
for (i=0;i<len;i++)
{k=reverse[i]*(i+1)+2 ;
j=k ^ sum;
replace[i]=j % 10+0x30;
}
for (i=0;i<len;i++)
{
o=replace[i]*(i+1);
p=o<< 3;
regcode[i]=(p-o) % 10+0x30;
}
regcode[6]='\0';
printf("注册码是:%s",regcode);
}
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2008年08月09日 16:04:38
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)