吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8713|回复: 12
收起左侧

[原创] 佳宜人事工资管理软件算法分析

[复制链接]
苏紫方璇 发表于 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文件,用脚本下按钮事件断点或者断api  MessageBoxA寻找关键点
  在这里发现程序把机器码当做参数调用dll生成注册码。
   1.png
  所以跟进去看一下。
   2.png
  这个dll也是delphi编写的,所以同理,拖入idr生成map文件辅助分析。
  然后单步跟下去。
  
[Asm] 纯文本查看 复制代码
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:[eax]
00399040  |.  64:8920       mov dword ptr fs:[eax],esp
00399043  |.  8D45 EC       lea eax,[local.5]
00399046  |.  E8 65B5F8FF   call <PunUnitL.System.@LStrClr>
0039904B  |.  8D45 F0       lea eax,[local.4]
0039904E  |.  8B55 08       mov edx,[arg.1]
00399051  |.  E8 4AB7F8FF   call <PunUnitL.System.@LStrFromPChar>
00399056  |.  8B45 F0       mov eax,[local.4]
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,[local.6]
0039906C  |.  8B45 F0       |mov eax,[local.4]
0039906F  |.  0FB64418 FF   |movzx eax,byte ptr ds:[eax+ebx-0x1]
00399074  |.  33D2          |xor edx,edx
00399076  |.  E8 F905F9FF   |call <PunUnitL.SysUtils.IntToHex>       ;  字符串转Ascii字串
0039907B  |.  8B55 E8       |mov edx,[local.6]
0039907E  |.  8D45 FC       |lea eax,[local.1]
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,[local.1]
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,[local.1]
003990A0  |.  E8 C3B7F8FF   |call <PunUnitL.System.@LStrLen>
003990A5  |.  2BC3          |sub eax,ebx
003990A7  |.  8B55 FC       |mov edx,[local.1]
003990AA  |.  8A1402        |mov dl,byte ptr ds:[edx+eax]
003990AD  |.  8D45 E4       |lea eax,[local.7]
003990B0  |.  E8 DBB6F8FF   |call <PunUnitL.System.@LStrFromChar>
003990B5  |.  8B55 E4       |mov edx,[local.7]
003990B8  |.  8D45 F8       |lea eax,[local.2]
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,[local.1]
003990C7  |.  50            push eax
003990C8  |.  B9 04000000   mov ecx,0x4
003990CD  |.  BA 01000000   mov edx,0x1
003990D2  |.  8B45 F8       mov eax,[local.2]
003990D5  |.  E8 E6B9F8FF   call <PunUnitL.System.@LStrCopy>         ;  取字符串1-4位,记为StrA
003990DA  |.  8D45 F8       lea eax,[local.2]
003990DD  |.  50            push eax
003990DE  |.  B9 04000000   mov ecx,0x4
003990E3  |.  BA 05000000   mov edx,0x5
003990E8  |.  8B45 F8       mov eax,[local.2]
003990EB  |.  E8 D0B9F8FF   call <PunUnitL.System.@LStrCopy>         ;  取字符串5-8位,记为StrB
003990F0  |.  8B45 FC       mov eax,[local.1]
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,[local.1]
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,[local.8]
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,[local.8]
0039911E  |.  8D45 FC       |lea eax,[local.1]
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,[local.2]
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,[local.2]
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,[local.9]
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,[local.9]
0039915A  |.  8D45 F8       |lea eax,[local.2]
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,[local.10]
0039916B  |.  8B55 0C       mov edx,[arg.2]                          ;  jyHRMman.005EED64
0039916E  |.  E8 2DB6F8FF   call <PunUnitL.System.@LStrFromPChar>
00399173  |.  8B45 D8       mov eax,[local.10]                       ;  出现读取特定注册码CRS5-J9E8
00399176  |.  8D55 F4       lea edx,[local.3]
00399179  |.  E8 DE03F9FF   call <PunUnitL.SysUtils.Trim>
0039917E  |.  8D45 D4       lea eax,[local.11]
00399181  |.  50            push eax
00399182  |.  B9 04000000   mov ecx,0x4
00399187  |.  BA 01000000   mov edx,0x1
0039918C  |.  8B45 F4       mov eax,[local.3]
0039918F  |.  E8 2CB9F8FF   call <PunUnitL.System.@LStrCopy>         ;  取特定注册码1-4位,记为CodA
00399194  |.  FF75 D4       push [local.11]
00399197  |.  68 0C923900   push PunUnitL.0039920C                   ;  UNICODE "-"
0039919C  |.  FF75 FC       push [local.1]
0039919F  |.  8D45 D0       lea eax,[local.12]
003991A2  |.  50            push eax
003991A3  |.  B9 05000000   mov ecx,0x5
003991A8  |.  BA 05000000   mov edx,0x5
003991AD  |.  8B45 F4       mov eax,[local.3]
003991B0  |.  E8 0BB9F8FF   call <PunUnitL.System.@LStrCopy>         ;  取特定注册码5-9位,记为CodB
003991B5  |.  FF75 D0       push [local.12]
003991B8  |.  68 0C923900   push PunUnitL.0039920C                   ;  UNICODE "-"
003991BD  |.  FF75 F8       push [local.2]
003991C0  |.  8D45 EC       lea eax,[local.5]
003991C3  |.  BA 06000000   mov edx,0x6
003991C8  |.  E8 5BB7F8FF   call <PunUnitL.System.@LStrCatN>         ;  拼接字符CodA,-,StrA,CodB,-,StrB
003991CD  |.  8B45 EC       mov eax,[local.5]
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:[eax],edx
003991DF  |.  68 F9913900   push PunUnitL.003991F9
003991E4  |>  8D45 D0       lea eax,[local.12]
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的函数,输入机器码,函数返回就是注册码了。
  第二种,自己实现上面的算法即可。

附粗略代码:
[C++] 纯文本查看 复制代码
#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[3];
	int  i = 0;
	for (i = 0; i < strlen(Mac);i++)
	{
		sprintf(ch, "%02X", Mac[i]);
		strcat(Asc, ch);
	}
}
void swapStr(char *Str)
{
	char tmp[122] = {0};
	int i = 0,a=0;
	for (i = strlen(Str) - 1; i >= 0; i--)
	{
		tmp[a++] = Str[i];
	}
	strcpy(Str, tmp);
}
int main()
{
	char Mac[60] = {0};
	char Code[122] = {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[60];
	char tmp[5] = {0};
	strcpy(Zhuce, "CRS5-");
	memcpy(tmp, Code, 4);
	strcat(Zhuce, tmp);
	strcat(Zhuce, "-J9E8-");
	memcpy(tmp, &Code[4], 4);
	strcat(Zhuce, tmp);
	printf("%s\n", Zhuce);

	system("pause");
	return 0;
}

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

                                                               2015年11月04日


点评

膜拜能口算SE Key的大牛  发表于 2015-11-12 12:48

免费评分

参与人数 10威望 +2 热心值 +10 收起 理由
朱朱你堕落了 + 1 算法牛。
haoren + 1 我很赞同!
凉游浅笔深画眉 + 1 我很赞同!
爱飞的猫 + 1 很棒!
Hmily + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
oo74521 + 1 一直很崇拜算算法的大神,
Sound + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
Cizel + 1 算法大牛~
小朋友呢 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
吃饭睡觉打豆豆 + 1 加分的沙发~~

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 苏紫方璇 发表于 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
算了,我不想多少什么了,膜拜大神,已加分,求回血,求热心

免费评分

参与人数 1热心值 +1 收起 理由
苏紫方璇 + 1 豆豆大牛是不想多说、、感谢支持

查看全部评分

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

CB呢,CB呢???肿么可以这样~~~
小朋友呢 发表于 2015-11-4 13:09
原先我还不会做注册机,觉得很难,看完之后感觉好像还是很难
LEG 发表于 2015-11-6 02:07
谢谢分享
smile1110 发表于 2015-11-6 15:40
俺想学习第一种编写注册机的方法,可不可以教教俺,怎么调用这个函数呢
永远向前看 发表于 2015-11-11 14:02
谢谢,学习了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-17 15:52

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表