软件名称:潍坊长远驾校驾驶员理论模拟考试系统4.2(收费版) 加壳方式:无 运行平台:windows delphi 作者:DevilMayCry(易木马) 工具:OD 、DeDe v3.50.04 内容提示:1、简介 2、运行 3、载入DeDe 4、OD分析 5、算法解读 6、注册机编写 一、简介 潍坊长远驾校驾驶员理论模拟考试系统是一套用于驾驶证理论考试训练的专用软件,先以科学的循序渐近的方法进行各类别的训练,最后以一种仿真考试的形式进行水平测试。该软件的主要特点是能够为您提供真实的考试环境,其电脑小键盘布局与真实考试键盘完全对应,使您平时就能在考试环境中练习,因而能够轻松进入考试状态,在最短的时间内获得最佳的成绩。 二、试运行 下载下来之后是一个安装包,安装之后运行,看看有没有什么能够帮助到我们的。 好了,有用的大概也就这么多吧。 三、载入DeDe 从上面的情况来看,有独立的注册窗体,我们用dede来找到“注册”按键事件。直接原程序拖进Dede. 找到注册的按钮事件入口: [Asm] 纯文本查看 复制代码 004C2128 >/. 55 push ebp ; 注册按钮
004C2129 |. 8BEC mov ebp,esp
004C212B |. 33C9 xor ecx,ecx
四、OD 分析 在OD里转到004C2128位置,下断进行分析,就不截图了: [Asm] 纯文本查看 复制代码 004C2138 |. 68 2E224C00 push 潍坊长远.004C222E
004C213D |. 64:FF30 push dword ptr fs:[eax]
004C2140 |. 64:8920 mov dword ptr fs:[eax],esp
004C2143 |. 8D55 F0 lea edx,[local.4] ; 局部变量4,放假码的
004C2146 |. 8B86 14030000 mov eax,dword ptrds:[esi+0x314] ; EAX放的是Edit_zcm : TEdit
004C214C |. E89B74F8FF call 潍坊长远.004495EC ; GetText(TControl):TCaption;
004C2151 |. 8B45 F0 mov eax,[local.4]
004C2154 |. 8D55 F8 lea edx,[local.2] ;变量2是4 去前后空格的值
004C2157 |. E8 8C6DF4FF call 潍坊长远.00408EE8 ; SysUtils.Trim(AnsiString)
004C215C |. 8B45 F8 mov eax,[local.2]
004C215F |. E8 6829F4FF call 潍坊长远.00404ACC ; 大概是取字符长度
004C2164 |. 83F808 cmp eax,0x8
004C2167 |. 7D 0F jge X潍坊长远.004C2178 ; 小于时出错
004C2169 |. B8 44224C00 moveax,潍坊长远.004C2244; ASCII "注册码格式错误!\r\r请输入8位注册码错误。"
004C216E |. E8 4D0EF7FF call 潍坊长远.00432FC0
004C2173 |. E9 93000000 jmp 潍坊长远.004C220B ; 4C220B是结束位置
004C2178 |> BB 01000000 mov ebx,0x1
004C217D |> 8B45 F8 /mov eax,[local.2]
004C2180 |. 807C18FF 4F |cmp byte ptr ds:[eax+ebx-0x1],0x4F ; 在注册码里面查找注册码,英文字母“o“
004C2185 |. 75 0D |jnz X潍坊长远.004C2194 ;没有就进行下一次循环
004C2187 |. 8D45 F8 |lea eax,[local.2]
004C218A |. E8952BF4FF |call 潍坊长远.00404D24
004C218F |. C64418 FF 30 |mov byte ptrds:[eax+ebx-0x1],0x30 ; 有就在这里用数字“0”不替换掉
004C2194 |> 43 |inc ebx
004C2195 |. 83FB 09 |cmp ebx,0x9
004C2198 |.^ 75 E3 \jnz X潍坊长远.004C217D
004C219A |. 8D55 FC lea edx,[local.1] ; 变量1
004C219D |. 8BC6 mov eax,esi ;这里ESI中放的是控件机器码框的ID号
004C219F |. E800070000 call 潍坊长远.004C28A4 ; 取出机器码放在变量1里面
004C21A4 |. 8D4D F4 leaecx,[local.3] ; 变量3的地址
004C21A7 |. 8B55FC mov edx,[local.1] ; 变量1,机器码
004C21AA |. 8BC6 mov eax,esi
004C21AC |. E8 6F030000 call 潍坊长远.004C2520 ;真注册码计算CALL我们要进去
004C21B1 |. 8B45 F8 mov eax,[local.2] ; 替换后的假码
004C21B4 |. 8B55 F4 mov edx,[local.3] ; 计算后的真假
004C21B7 |. E8 5C2AF4FF call 潍坊长远.00404C18 ; System.@LStrCmp;
004C21BC |. 75 43 jnz X潍坊长远.004C2201 ; 关键跳转
我们到注册码计算的位置去看看,去分析一下,看看算法: [Asm] 纯文本查看 复制代码 004C2520 /$ 55 push ebp 入口
004C2536 |. E8 8127F4FF call 潍坊长远.00404CBC ; System.@LStrAddRef(void;void):Pointer;
004C253B |. 33C0 xor eax,eax ; 机器码
004C253D |. 55 push ebp
004C253E |. 68 06274C00 push 潍坊长远.004C2706
004C2543 |. 64:FF30 push dword ptr fs:[eax]
004C2546 |. 64:8920 mov dword ptr fs:[eax],esp
004C2549 |. 8D45 F8 lea eax,[local.2] ; 变量2
004C254C |. 8B55 FC mov edx,[local.1]
004C254F |. E8 5023F4FFcall潍坊长远.004048A4 ; System.@LStrLAsg
004C2554 |. BE 01000000 mov esi,0x1 ;下面可以看见是对机器进行计算
004C2559 |> 8B45 FC /mov eax,[local.1]
004C255C |. 33DB |xor ebx,ebx
004C255E |. 8A5C30 FF |mov bl,byte ptr ds:[eax+esi-0x1];依次取出每一位的ASCII值
004C2562 |. 83FB 30 |cmp ebx,0x30
004C2565 |. 7C0B |jl X潍坊长远.004C2572
004C2567 |. 83FB 39 |cmp ebx,0x39
004C256A |. 7F 06 |jg X潍坊长远.004C2572 ; 如果是0-9,ASCII+位数+0x11
004C256C |. 8D441E 11 |lea eax,dword ptrds:[esi+ebx+0x11]
004C2570 |. 8BD8 |mov ebx,eax
004C2572 |> 83FB 41 |cmp ebx,0x41
004C2575 |. 7C0F |jl X潍坊长远.004C2586
004C2577 |. B8 5A000000 |mov eax,0x5A ; "Z'
004C257C |. 2BC6 |sub eax,esi ;"z"-位数与位数上的数的ASCII码比较
004C257E |. 3BD8 |cmp ebx,eax
004C2580 |. 7F04 |jg X潍坊长远.004C2586
004C2582 |. 03DE |add ebx,esi ; 就再加一次位数
004C2584 |. EB 16 |jmp X潍坊长远.004C259C
004C2586 |> B8 5A000000 |mov eax,0x5A
004C258B |. 2BC6 |sub eax,esi
004C258D |. 40 |inc eax
004C258E |. 3BD8 |cmp ebx,eax
004C2590 |. 7C0A |jl X潍坊长远.004C259C
004C2592 |. 83FB 5A |cmp ebx,0x5A
004C2595 |. 7F05 |jg X潍坊长远.004C259C
004C2597 |. 83EB 1A |subebx,0x1A
004C259A |. 03DE |add ebx,esi
004C259C |> 8D45 F8 |lea eax,[local.2]
004C259F |. E8 8027F4FF |call 潍坊长远.00404D24
004C25A4 |. 885C30 FF |mov byte ptr ds:[eax+esi-0x1],bl ;把计算的每一位都放回去
004C25A8 |. 46 |inc esi
004C25A9 |. 83FE 05 |cmp esi,0x5 ; ESI每次增长一
004C25AC |.^ 75 AB \jnz X潍坊长远.004C2559 ; 前4位就这样计算结束了
004C25AE |. BE 05000000 mov esi,0x5
到此前四位结束了 [Asm] 纯文本查看 复制代码 004C25B3 |> 8B45 FC /mov eax,[local.1] ; 从第五位开始
004C25B6 |. 33DB |xor ebx,ebx
004C25B8 |. 8A5C30 FF |mov bl,byte ptr ds:[eax+esi-0x1]
004C25BC |. 83FB 30 |cmp ebx,0x30
004C25BF |. 7C0A |jl X潍坊长远.004C25CB ; <0
004C25C1 |. 83FB 37 |cmp ebx,0x37
004C25C4 |. 7F 05 |jg X潍坊长远.004C25CB ; >8
004C25C6 |. 83C3 02 |add ebx,0x2 ; 如果是0-7之间的数字,则加2
004C25C9 |. EB0D |jmp X潍坊长远.004C25D8
004C25CB |> 83FB 38 |cmp ebx,0x38
004C25CE |. 7C08 |jl X潍坊长远.004C25D8
004C25D0 |. 83FB 39 |cmp ebx,0x39
004C25D3 |. 7F03 |jg X潍坊长远.004C25D8 ; 8-9的话直下一步
004C25D5 |. 83EB 08 |sub ebx,0x8 ; 是字母的话或者大的直接减8
004C25D8 |> 83FB 41 |cmp ebx,0x41 ; Switch (cases 41..5A)
004C25DB |. 7C29 |jl X潍坊长远.004C2606 ; "A"
004C25DD |. 83FB 5A |cmpebx,0x5A
004C25E0 |. 7F24 |jg X潍坊长远.004C2606 ; “z”
004C25E2 |. 83EB 41 |sub ebx,0x41
004C25E5 |. 83FB 0A |cmpebx,0xA
004C25E8 |. 7C03 |jl X潍坊长远.004C25ED ; 下面两个字符串也说明了,如果是A-J,则减41,B-Z,则减4B
004C25EA |. 83EB 0A |subebx,0xA ; Cases 4B ('K'),4C ('L'),4D ('M'),4E ('N'),4F ('O'),50 ('P'),51 ('Q'),52 ('R'),53 ('S'),54('T'),55 ('U'),56 ('V'),57 ('W'),58 ('X'),59 ('Y'),5A ('Z') of switch 004C25D8
004C25ED |> 83FB 0A |cmpebx,0xA ; Cases 41 ('A'),42 ('B'),43 ('C'),44 ('D'),45('E'),46 ('F'),47 ('G'),48 ('H'),49 ('I'),4A ('J') of switch 004C25D8
004C25F0 |. 7C 03 |jl X潍坊长远.004C25F5
004C25F2 |. 83EB 0A |sub ebx,0xA ; 显然这样计算的结果是在0-10了
004C25F5 |> 8D45 F8 |lea eax,[local.2] ; 之后的值放在变量中去
004C25F8 |. E8 2727F4FF |call 潍坊长远.00404D24
004C25FD |. 80C330 |add bl,0x30 ; 在这时转换成相应的ASCII码值
004C2600 |. 885C30FF |mov byte ptr ds:[eax+esi-0x1],bl ;放回到我们真注册码保存的位置
004C2604 |. EB 0C |jmp X潍坊长远.004C2612
004C2606 |> 8D45 F8 |lea eax,[local.2] ; Default case of switch 004C25D8
004C2609 |. E8 1627F4FF |call潍坊长远.00404D24 ;如果里面全都是数字,那取相应的位
004C260E |. 885C30FF |mov byte ptrds:[eax+esi-0x1],bl ; 直接放进去就好了
004C2612 |> 46 |inc esi
004C2613 |. 83FE 09 |cmp esi,0x9
004C2616 |.^ 75 9B \jnz X潍坊长远.004C25B3
到此后4位结束了。 [Asm] 纯文本查看 复制代码 004C2618 |. 8D45 F4 lea eax,[local.3]
004C261B |. 8B55 F8 mov edx,[local.2]
004C261E |. E8 8122F4FF call 潍坊长远.004048A4 ;大概是拷贝了一份放在变量3里面了吧
004C2623 |. 8D45 F4 lea eax,[local.3]
004C2626 |. E8 F926F4FF call 潍坊长远.00404D24 ; System.@UniqueStringA(String;String);
004C262B |. 8B55 F8 mov edx,[local.2]
004C262E |. 8A5202 mov dl,byte ptrds:[edx+0x2] ; 变量2的第2位
004C2631 |. 8810 mov byte ptr ds:[eax],dl ; 第0位
004C2633 |. 8D45 F4 lea eax,[local.3]
004C2636 |. E8 E926F4FF call 潍坊长远.00404D24
004C263B |. 8B55 F8 mov edx,[local.2]
004C263E |. 8A5204 mov dl,byte ptrds:[edx+0x4] ; 第四位换第4
004C2641 |. 8850 01 mov byte ptr ds:[eax+0x1],dl ; 换第1
004C2644 |. 8D45 F4 lea eax,[local.3]
004C2647 |. E8 D826F4FF call 潍坊长远.00404D24
004C264C |. 8B55 F8 mov edx,[local.2]
004C264F |. 8A52 07 mov dl,byte ptr ds:[edx+0x7] ; 7
004C2652 |. 8850 02 mov byte ptr ds:[eax+0x2],dl ; 2
004C2655 |. 8D45 F4 lea eax,[local.3]
004C2658 |. E8 C726F4FF call 潍坊长远.00404D24
004C265D |. 8B55 F8 mov edx,[local.2]
004C2660 |. 8A12 mov dl,byte ptr ds:[edx] ; 0换3
004C2662 |. 8850 03 mov byte ptr ds:[eax+0x3],dl
004C2665 |. 8D45 F4 lea eax,[local.3]
004C2668 |. E8 B726F4FF call 潍坊长远.00404D24
004C266D |. 8B55 F8 mov edx,[local.2]
004C2670 |. 8A5203 mov dl,byte ptrds:[edx+0x3] ; 3换4
004C2673 |. 8850 04 mov byte ptr ds:[eax+0x4],dl
004C2676 |. 8D45 F4 lea eax,[local.3]
004C2679 |. E8 A626F4FF call 潍坊长远.00404D24
004C267E |. 8B55 F8 mov edx,[local.2]
004C2681 |. 8A5206 mov dl,byte ptrds:[edx+0x6] ; 6换5
004C2684 |. 8850 05 mov byte ptr ds:[eax+0x5],dl
004C2687 |. 8D45 F4 lea eax,[local.3]
004C268A |. E8 9526F4FF call 潍坊长远.00404D24
004C268F |. 8B55 F8 mov edx,[local.2]
004C2692 |. 8A5201 mov dl,byte ptrds:[edx+0x1] ; 1换6
004C2695 |. 8850 06 mov byte ptr ds:[eax+0x6],dl
004C2698 |. 8D45 F4 lea eax,[local.3]
004C269B |. E8 8426F4FF call 潍坊长远.00404D24
004C26A0 |. 8B55 F8 mov edx,[local.2]
004C26A3 |. 8A52 05 mov dl,byte ptr ds:[edx+0x5] ; 5换7.
004C26A6 |. 8850 07 mov byte ptrds:[eax+0x7],dl
004C26A9 |. BE01000000 mov esi,0x1 ; 上面的注册码进行了进一步调整
上面调整完成后,后面是最后一步了,其它可以不用管他。 [Asm] 纯文本查看 复制代码 004C26AE |> 8B45 F4 /mov eax,[local.3]
004C26B1 |. 807C30FF 4F |cmp byte ptr ds:[eax+esi-0x1],0x4F
004C26B6 |. 75 0D |jnz X潍坊长远.004C26C5
004C26B8 |. 8D45 F4 |lea eax,[local.3]
004C26BB |. E8 6426F4FF |call潍坊长远.00404D24 ; 这里的大概意思是说,处理之后看看是否有字母O
004C26C0 |. C64430 FF 30 |mov byte ptrds:[eax+esi-0x1],0x30 ;如果有则换成数字0
004C26C5 |> 46 |inc esi
004C26C6 |. 83FE 09 |cmp esi,0x9
004C26C9 |.^ 75 E3 \jnz X潍坊长远.004C26AE
004C26CB |. 8D55 F0 lea edx,[local.4]
004C26CE |. 8B45 F4 mov eax,[local.3] ;将变量3中字母转成大写
004C26D1 |. E8 C265F4FF call 潍坊长远.00408C98 ;UpperCase(AnsiString)
004C26D6 |. 8B55 F0 mov edx,[local.4]
004C26D9 |. 8D45 F4 lea eax,[local.3]
004C26DC |. E8 C321F4FF call 潍坊长远.004048A4 ;System.@LStrLAsg
004C26E1 |. 8BC7 mov eax,edi
004C26E3 |. 8B55 F4 mov edx,[local.3]
004C26E6 |. E8 7521F4FF call 潍坊长远.00404860 ; System.@LStrAsg
004C26EB |. 33C0 xor eax,eax
004C26ED |. 5A pop edx
004C26EE |. 59 pop ecx
004C26EF |. 59 pop ecx
004C26F0 |. 64:8910 mov dword ptrfs:[eax],edx
004C26F3 |. 680D274C00 push 潍坊长远.004C270D
004C26F8 |> 8D45 F0 lea eax,[local.4]
004C26FB |. BA 04000000 mov edx,0x4
004C2700 |. E8 2B21F4FF call 潍坊长远.00404830 ; System.@LStrArrayClr
五、算法解读 通过上面的分析,整个注册都在“注册”按钮事件里面处理完成,我们大致总结一下算法(我们试注册的码称假码)。 1、假码处理:注册码必须是8位字符,不包括两端的空格键,不能有英文字母O,如果有则用数字0替换掉了,但对我们没有影响,它会自动替换掉。 2、注册码:先取1-4位处理,5-8位处理,最后就是打乱它们的位置,字符替换。
六、注册机编写 C#注册机原始代码见: [C#] 纯文本查看 复制代码 //一、对机器码的前位的处理
for(;i<4;i++)
{
char k;
//如果是数字
if (Char.IsNumber(MCODE))
{
k = MCODE;
k +=Convert.ToChar( (i+1)*2 +17);
MCODE = k;
}
//其它的我们在这里处理
else
{
k = MCODE;
if (k <= ('Z' -(i+1)))
{
MCODE = Convert.ToChar(k + i + 1);
}
else
{
if (k < ('Z'+1 -(i + 1)))
{
MCODE = k;
}
else
{
if (k > 'Z')
{
MCODE = k;
}
else
{
k = Convert.ToChar((Convert.ToInt16(k)-26+ i+1));
MCODE = k;
} }}}}
//二是、对机器码的后位的处理
/*
30下直接存起来。
30-37 +2 结束
38-39 -8 存起来
40 直接存
41 -41 转ASCII+30存
41-5A 里面值-41
小于存, 如果大于-10 还大于就再减*/
for(; i < 8; i++)
{
if( (MCODE < '0')||(MCODE=='@'))
{
Console.WriteLine(MCODE);
}
else
{
if (MCODE < '8')
{
MCODE = Convert.ToChar((MCODE + 2));
continue;
}
if (MCODE < 'A')
{
MCODE =Convert.ToChar((MCODE + 8));
continue;
}
if (MCODE >= 'A')
{
int K = MCODE - 'A';
if (K < 10)
{
MCODE= Convert.ToChar(K + 48);
}
else
{
if (K < 10)
{
MCODE = Convert.ToChar(K + 48);
}
else
{
K -=10;
MCODE = Convert.ToChar(K + 48);
}}}}}
//三是、换位,成型!
KEYWORD[0] = MCODE[2];
KEYWORD[1] = MCODE[4];
KEYWORD[2] = MCODE[7];
KEYWORD[3] = MCODE[0];
KEYWORD[4] = MCODE[3];
KEYWORD[5] = MCODE[6];
KEYWORD[6] = MCODE[1];
KEYWORD[7] = MCODE[5];
stringmsg=null;
for(i = 0; i < 8; i++)
{
msg +=KEYWORD.ToString();
}
this.textBox_reg.Text= msg;
}
原代码见附件: 如有什么不对,希望大家指正,后面跟贴子 |