苏紫方璇 发表于 2015-11-4 11:05

佳宜人事工资管理软件算法分析

【文章标题】: 佳宜人事工资管理软件算法分析
【软件名称】: 佳宜人事工资管理软件
【使用工具】: OD,ExeinfoPE,IDR (Interactive Delphi Reconstructor)
【工具下载】: 爱盘啥都有
--------------------------------------------------------------------------------
【首先说明】
昨天看到@oo74521 发了一个内存注册机
佳宜人事工资管理软件(注册机)
http://www.52pojie.cn/thread-428125-1-1.html
(出处: 吾爱破解论坛)
我发现这个软件能追到码,并且比较简单,就想逆个算法试试。。。。于是就有了此文。
此文为逆算法的分析,就不说如何找到关键点了吧,有兴趣的可以试试,十分的简单。
【详细过程】
首先先查壳,发现时delphi编写的程序,拖入IDR生成map文件辅助分析。
拖入od,用插件加载map文件,用脚本下按钮事件断点或者断apiMessageBoxA寻找关键点
在这里发现程序把机器码当做参数调用dll生成注册码。

所以跟进去看一下。

这个dll也是delphi编写的,所以同理,拖入idr生成map文件辅助分析。
然后单步跟下去。
00399024 >/$55            push ebp
00399025|.8BEC          mov ebp,esp
00399027|.B9 06000000   mov ecx,0x6
0039902C|>6A 00         /push 0x0
0039902E|.6A 00         |push 0x0
00399030|.49            |dec ecx
00399031|.^ 75 F9         \jnz short PunUnitL.0039902C
00399033|.53            push ebx
00399034|.56            push esi
00399035|.33C0          xor eax,eax
00399037|.55            push ebp
00399038|.68 F2913900   push PunUnitL.003991F2
0039903D|.64:FF30       push dword ptr fs:
00399040|.64:8920       mov dword ptr fs:,esp
00399043|.8D45 EC       lea eax,
00399046|.E8 65B5F8FF   call <PunUnitL.System.@LStrClr>
0039904B|.8D45 F0       lea eax,
0039904E|.8B55 08       mov edx,
00399051|.E8 4AB7F8FF   call <PunUnitL.System.@LStrFromPChar>
00399056|.8B45 F0       mov eax,
00399059|.E8 0AB8F8FF   call <PunUnitL.System.@LStrLen>
0039905E|.8BF0          mov esi,eax
00399060|.85F6          test esi,esi
00399062|.7E 26         jle short PunUnitL.0039908A            ;判断机器码长度不是0
00399064|.BB 01000000   mov ebx,0x1
00399069|>8D4D E8       /lea ecx,
0039906C|.8B45 F0       |mov eax,
0039906F|.0FB64418 FF   |movzx eax,byte ptr ds:
00399074|.33D2          |xor edx,edx
00399076|.E8 F905F9FF   |call <PunUnitL.SysUtils.IntToHex>       ;字符串转Ascii字串
0039907B|.8B55 E8       |mov edx,
0039907E|.8D45 FC       |lea eax,
00399081|.E8 EAB7F8FF   |call <PunUnitL.System.@LStrCat>         ;字符串连接起来
00399086|.43            |inc ebx
00399087|.4E            |dec esi
00399088|.^ 75 DF         \jnz short PunUnitL.00399069
0039908A|>8B45 FC       mov eax,
0039908D|.E8 D6B7F8FF   call <PunUnitL.System.@LStrLen>
00399092|.8BF0          mov esi,eax
00399094|.85F6          test esi,esi
00399096|.7E 2C         jle short PunUnitL.003990C4            ;判断生成的长度是否为空
00399098|.BB 01000000   mov ebx,0x1
0039909D|>8B45 FC       /mov eax,
003990A0|.E8 C3B7F8FF   |call <PunUnitL.System.@LStrLen>
003990A5|.2BC3          |sub eax,ebx
003990A7|.8B55 FC       |mov edx,
003990AA|.8A1402      |mov dl,byte ptr ds:
003990AD|.8D45 E4       |lea eax,
003990B0|.E8 DBB6F8FF   |call <PunUnitL.System.@LStrFromChar>
003990B5|.8B55 E4       |mov edx,
003990B8|.8D45 F8       |lea eax,
003990BB|.E8 B0B7F8FF   |call <PunUnitL.System.@LStrCat>
003990C0|.43            |inc ebx
003990C1|.4E            |dec esi
003990C2|.^ 75 D9         \jnz short PunUnitL.0039909D             ;字符串反向处理
003990C4|>8D45 FC       lea eax,
003990C7|.50            push eax
003990C8|.B9 04000000   mov ecx,0x4
003990CD|.BA 01000000   mov edx,0x1
003990D2|.8B45 F8       mov eax,
003990D5|.E8 E6B9F8FF   call <PunUnitL.System.@LStrCopy>         ;取字符串1-4位,记为StrA
003990DA|.8D45 F8       lea eax,
003990DD|.50            push eax
003990DE|.B9 04000000   mov ecx,0x4
003990E3|.BA 05000000   mov edx,0x5
003990E8|.8B45 F8       mov eax,
003990EB|.E8 D0B9F8FF   call <PunUnitL.System.@LStrCopy>         ;取字符串5-8位,记为StrB
003990F0|.8B45 FC       mov eax,
003990F3|.E8 70B7F8FF   call <PunUnitL.System.@LStrLen>
003990F8|.83F8 04       cmp eax,0x4
003990FB|.7D 2F         jge short PunUnitL.0039912C
003990FD|.8B45 FC       mov eax,
00399100|.E8 63B7F8FF   call <PunUnitL.System.@LStrLen>
00399105|.8BD8          mov ebx,eax
00399107|.83FB 03       cmp ebx,0x3
0039910A|.7F 20         jg short PunUnitL.0039912C
0039910C|>8D4D E0       /lea ecx,
0039910F|.8BC3          |mov eax,ebx
00399111|.C1E0 02       |shl eax,0x2
00399114|.33D2          |xor edx,edx
00399116|.E8 5905F9FF   |call <PunUnitL.SysUtils.IntToHex>
0039911B|.8B55 E0       |mov edx,
0039911E|.8D45 FC       |lea eax,
00399121|.E8 4AB7F8FF   |call <PunUnitL.System.@LStrCat>
00399126|.43            |inc ebx
00399127|.83FB 04       |cmp ebx,0x4
0039912A|.^ 75 E0         \jnz short PunUnitL.0039910C
0039912C|>8B45 F8       mov eax,
0039912F|.E8 34B7F8FF   call <PunUnitL.System.@LStrLen>
00399134|.83F8 04       cmp eax,0x4
00399137|.7D 2F         jge short PunUnitL.00399168
00399139|.8B45 F8       mov eax,
0039913C|.E8 27B7F8FF   call <PunUnitL.System.@LStrLen>
00399141|.8BD8          mov ebx,eax
00399143|.83FB 03       cmp ebx,0x3
00399146|.7F 20         jg short PunUnitL.00399168
00399148|>8D4D DC       /lea ecx,
0039914B|.8BC3          |mov eax,ebx
0039914D|.C1E0 02       |shl eax,0x2
00399150|.33D2          |xor edx,edx
00399152|.E8 1D05F9FF   |call <PunUnitL.SysUtils.IntToHex>
00399157|.8B55 DC       |mov edx,
0039915A|.8D45 F8       |lea eax,
0039915D|.E8 0EB7F8FF   |call <PunUnitL.System.@LStrCat>
00399162|.43            |inc ebx
00399163|.83FB 04       |cmp ebx,0x4
00399166|.^ 75 E0         \jnz short PunUnitL.00399148
00399168|>8D45 D8       lea eax,
0039916B|.8B55 0C       mov edx,                        ;jyHRMman.005EED64
0039916E|.E8 2DB6F8FF   call <PunUnitL.System.@LStrFromPChar>
00399173|.8B45 D8       mov eax,                     ;出现读取特定注册码CRS5-J9E8
00399176|.8D55 F4       lea edx,
00399179|.E8 DE03F9FF   call <PunUnitL.SysUtils.Trim>
0039917E|.8D45 D4       lea eax,
00399181|.50            push eax
00399182|.B9 04000000   mov ecx,0x4
00399187|.BA 01000000   mov edx,0x1
0039918C|.8B45 F4       mov eax,
0039918F|.E8 2CB9F8FF   call <PunUnitL.System.@LStrCopy>         ;取特定注册码1-4位,记为CodA
00399194|.FF75 D4       push
00399197|.68 0C923900   push PunUnitL.0039920C                   ;UNICODE "-"
0039919C|.FF75 FC       push
0039919F|.8D45 D0       lea eax,
003991A2|.50            push eax
003991A3|.B9 05000000   mov ecx,0x5
003991A8|.BA 05000000   mov edx,0x5
003991AD|.8B45 F4       mov eax,
003991B0|.E8 0BB9F8FF   call <PunUnitL.System.@LStrCopy>         ;取特定注册码5-9位,记为CodB
003991B5|.FF75 D0       push
003991B8|.68 0C923900   push PunUnitL.0039920C                   ;UNICODE "-"
003991BD|.FF75 F8       push
003991C0|.8D45 EC       lea eax,
003991C3|.BA 06000000   mov edx,0x6
003991C8|.E8 5BB7F8FF   call <PunUnitL.System.@LStrCatN>         ;拼接字符CodA,-,StrA,CodB,-,StrB
003991CD|.8B45 EC       mov eax,
003991D0|.E8 8BB8F8FF   call <PunUnitL.System.@LStrToPChar>
003991D5|.8BD8          mov ebx,eax
003991D7|.33C0          xor eax,eax
003991D9|.5A            pop edx                                  ;PunUnitL.003991F9
003991DA|.59            pop ecx                                  ;PunUnitL.003991F9
003991DB|.59            pop ecx                                  ;PunUnitL.003991F9
003991DC|.64:8910       mov dword ptr fs:,edx
003991DF|.68 F9913900   push PunUnitL.003991F9
003991E4|>8D45 D0       lea eax,
003991E7|.BA 0C000000   mov edx,0xC
003991EC|.E8 E3B3F8FF   call <PunUnitL.System.@LStrArrayClr>
003991F1\.C3            retn
总结一下,注册码="CRS5" + "-"+取1-4位(反向(转ascii值(机器码)))+"-J9E8"+"-"+取5-8位(反向(转ascii值(机器码)))
这样就可以写算法注册机了,算法注册机可以有两种写法,
第一种,直接调用这个dll的函数,输入机器码,函数返回就是注册码了。
第二种,自己实现上面的算法即可。

附粗略代码:
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

typedef char *(WINAPI *pGetRegPass)(char *Mac, char *Code);

void AscStr(char *Mac, char *Asc)
{
        char ch;
        inti = 0;
        for (i = 0; i < strlen(Mac);i++)
        {
                sprintf(ch, "%02X", Mac);
                strcat(Asc, ch);
        }
}
void swapStr(char *Str)
{
        char tmp = {0};
        int i = 0,a=0;
        for (i = strlen(Str) - 1; i >= 0; i--)
        {
                tmp = Str;
        }
        strcpy(Str, tmp);
}
int main()
{
        char Mac = {0};
        char Code = {0};
        printf("请输入机器码:");
        scanf("%s", Mac);
        printf("第一种方法\n\n");
        pGetRegPass GetRegPass = (pGetRegPass)GetProcAddress(LoadLibraryA("PunUnitLib.dll"), "GetRegPass");
        char *a;
        a = GetRegPass(Mac, "CRS5-J9E8");
        printf("%s\n\n", a);

        printf("第二种方法\n\n");
        AscStr(Mac, Code);
        swapStr(Code);
        char Zhuce;
        char tmp = {0};
        strcpy(Zhuce, "CRS5-");
        memcpy(tmp, Code, 4);
        strcat(Zhuce, tmp);
        strcat(Zhuce, "-J9E8-");
        memcpy(tmp, &Code, 4);
        strcat(Zhuce, tmp);
        printf("%s\n", Zhuce);

        system("pause");
        return 0;
}


--------------------------------------------------------------------------------
【版权声明】: 本文原创于吾爱破解,转载请注明作者并保持文章的完整,谢谢!

                                                               2015年11月04日


苏紫方璇 发表于 2015-11-6 19:12

smile1110 发表于 2015-11-6 15:40
俺想学习第一种编写注册机的方法,可不可以教教俺,怎么调用这个函数呢

这个函数在上边push两个参数,一个是固定的注册码地址,一个是机器码地址,然后返回真码的地址,并且两个参数被从堆栈中清除,这样差不多可以判定此函数为stdcall,参数、返回值也都明白了,下面就是编程调用了,声明一下猜测函数原型,加载dll获取函数地址,调用就可以了

smile1110 发表于 2015-11-6 19:15

苏紫方璇 发表于 2015-11-6 19:12
这个函数在上边push两个参数,一个是固定的注册码地址,一个是机器码地址,然后返回真码的地址,并且两个 ...

哦 等俺以后学会c语言再来看这句话 嘻嘻

Monitor 发表于 2015-11-4 11:32

有分析是最好不过的,感谢了

吃饭睡觉打豆豆 发表于 2015-11-4 11:49

算了,我不想多少什么了,膜拜大神,已加分,求回血,求热心

吃饭睡觉打豆豆 发表于 2015-11-4 12:01

吃饭睡觉打豆豆 发表于 2015-11-4 11:49
算了,我不想多少什么了,膜拜大神,已加分,求回血,求热心

CB呢,CB呢???肿么可以这样~~~{:301_971:}

小朋友呢 发表于 2015-11-4 13:09

原先我还不会做注册机,觉得很难,看完之后感觉好像还是很难{:301_978:}

LEG 发表于 2015-11-6 02:07

谢谢分享

smile1110 发表于 2015-11-6 15:40

俺想学习第一种编写注册机的方法,可不可以教教俺,怎么调用这个函数呢

永远向前看 发表于 2015-11-11 14:02

谢谢,学习了
页: [1] 2
查看完整版本: 佳宜人事工资管理软件算法分析