佳宜人事工资管理软件算法分析
【文章标题】: 佳宜人事工资管理软件算法分析【软件名称】: 佳宜人事工资管理软件
【使用工具】: 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日
smile1110 发表于 2015-11-6 15:40
俺想学习第一种编写注册机的方法,可不可以教教俺,怎么调用这个函数呢
这个函数在上边push两个参数,一个是固定的注册码地址,一个是机器码地址,然后返回真码的地址,并且两个参数被从堆栈中清除,这样差不多可以判定此函数为stdcall,参数、返回值也都明白了,下面就是编程调用了,声明一下猜测函数原型,加载dll获取函数地址,调用就可以了 苏紫方璇 发表于 2015-11-6 19:12
这个函数在上边push两个参数,一个是固定的注册码地址,一个是机器码地址,然后返回真码的地址,并且两个 ...
哦 等俺以后学会c语言再来看这句话 嘻嘻 有分析是最好不过的,感谢了 算了,我不想多少什么了,膜拜大神,已加分,求回血,求热心 吃饭睡觉打豆豆 发表于 2015-11-4 11:49
算了,我不想多少什么了,膜拜大神,已加分,求回血,求热心
CB呢,CB呢???肿么可以这样~~~{:301_971:} 原先我还不会做注册机,觉得很难,看完之后感觉好像还是很难{:301_978:} 谢谢分享 俺想学习第一种编写注册机的方法,可不可以教教俺,怎么调用这个函数呢 谢谢,学习了
页:
[1]
2