直销业绩考核系统算法分析-PB程序
【文章标题】: 直销业绩考核系统算法分析【文章作者】: caterpilla(惊涛)
【软件名称】: 直销业绩考核系统
【下载地址】: 自己搜索下载
【编写语言】: POWERBUILDER
【使用工具】: UE,PBKILLER,OD
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
这个软件笨鸟我先飞兄弟已经爆破过了,而且应用PBKILLER反编译了软件的源码,他把软件和反编译的代码给了我,我只是在阅读源码后,整理了一下算法,没有深入测试。
从源码开始看起了,呵呵,先贴几个关键的。
1、在系统启动时,应用程序调用检测是否注册的用户对象,判断是否注册、过期、调整过爱期、以及是否手工改过注册等。
global type dotnew from application
。。。。。。。。。
integer rt_chk_value
user_reg myreg
event open;ulong l_handle
ulong lu_class
string ls_name
rt_chk_value = myreg.f_check_reg()
if rt_chk_value = -100 then
messagebox("提示","系统时间有误!")
halt close
end if
if rt_chk_value = -200 then
messagebox("提示","注册码有误!")
halt close
end if
if rt_chk_value = -300 then
messagebox("提示","试用期到,请注册!电话:13336268237 网址:www.zcrj.net")
open(w_wrcode)
return
end if
if rt_chk_value = -400 then
messagebox("提示","系统破坏,请联系开发商!")
return
end if
下面的代码就是USER_REG用户对象,承担检测注册任务。
global type user_reg from n_cst_numerical autoinstantiate
end type
global user_reg user_reg
forward prototypes
public function integer f_check_reg ()//检测是否过期、爱期调整、注册,内部调用f_checkregcode
public function integer f_checkregcode (string reg_code)//关键的检查注册码的部分
public function string f_encode (string source_str)//对注册表信息加密的部分
public function string f_genpuzzle ()
public function string f_genser ()
public function string f_getdisk ()//获取硬盘序列号,与注册码生成有关
public function string f_redreg (string xsxt_key)//读注册表
public function integer f_setreg (string str_num,string str_info)//写注册表
public function string f_swap1 (string str_input)
public function string uf_patchstr (string userstr,integer userlen)
end prototypes
这里面其它的函数都是起迷惑作用的,呵呵。。。。。。。。。。。。。
public function integer f_check_reg ();string ls_right
string ls_wrong
ulong l_handle
ulong lu_class
string ls_name
string ls_disk
string ls_ser
string ls_flag
string ls_day
string ls_num
string ls_ltime
string ls_regflag
string ls_regcode
date ld_d1
date ld_td
integer tsh
integer tshch
integer check_result
ls_right = f_encode(f_redreg("0"))
ls_wrong = f_encode(f_redreg("1"))
if ((ls_right <> "wright") or (ls_wrong <> "wrong")) then//检测软件是否被破坏,手工改过注册表
return -400
end if
ls_regflag = f_redreg("3") //错误标记
if ls_regflag = "err" then
ls_flag = f_encode("90")
ls_day = f_encode("30")
ls_disk = f_encode(f_getdisk())
f_setreg("2",f_encode(f_genser()))
f_setreg("3",ls_flag)
f_setreg("4",f_encode("f7657lo"))
f_setreg("5",ls_day)
f_setreg("6",f_encode("fj;[57lo"))
f_setreg("7",f_encode(string(today())))
f_setreg("8",f_encode("fj57lo"))
return 100
end if
ls_ser = f_encode(f_redreg("2"))
ls_flag = f_encode(f_redreg("3")) //注册表中在HKEY_CURRENT_USER\Software\xsxt\xsxt_3下存放是否注册的标志
ls_day = f_encode(f_redreg("5"))
ls_ltime = f_encode(f_redreg("7"))
ls_regcode = f_encode(f_redreg("9"))
ld_d1 = date(ls_ltime)
ld_td = today()
tsh = daysafter(ld_d1,ld_td)//安装爱期与当前爱期比较
if tsh < 0 then
return -100落后 //若小,说明改过爱期
end if
if ls_flag = "89" then//89这个标记,代表已经注册,继续检测注册码是否合法
check_result = f_checkregcode(ls_regcode)//调用f_checkregcode检查注册码合法性
if check_result = 0 then
return 200 //注册
else
return -200 //注册码不合法
end if
else
tshch = integer(ls_day) - tsh//代表已过期
if tshch <= 0 then
f_setreg("5","00")
f_setreg("7",f_encode(string(today())))
return -300
else
ls_day = f_encode(uf_patchstr(string(tshch),2))
f_setreg("5",ls_day)
f_setreg("7",f_encode(string(today())))
return 300
end if
end if
end function
public function integer f_checkregcode (string reg_code);char alpha//关键部分
string tser
string ls_disk
string ls_disk1
char tmpchr
char tmpchr1
integer i
integer j
ls_disk = f_getdisk()//获取硬盘序列号
ls_disk1 = ""
//下面的ALPHA为明密文转换表,两列相互转化,互为加解密。
alpha = "A"
alpha = "B"
alpha = "C"
alpha = "D"
alpha = "E"
alpha = "F"
alpha = "G"
alpha = "H"
alpha = "I"
alpha = "J"
alpha = "K"
alpha = "L"
alpha = "M"
alpha = "N"
alpha = "O"
alpha = "P"
alpha = "Q"
alpha = "R"
alpha = "S"
alpha = "T"
alpha = "U"
alpha = "V"
alpha = "W"
alpha = "X"
alpha = "Y"
alpha = "Z"
alpha = "0"
alpha = "1"
alpha = "2"
alpha = "3"
alpha = "4"
alpha = "5"
alpha = "6"
alpha = "7"
alpha = "8"
alpha = "9"
alpha = "Z"
alpha = "X"
alpha = "C"
alpha = "V"
alpha = "B"
alpha = "9"
alpha = "M"
alpha = ","
alpha = "."
alpha = "/"
alpha = "7"
alpha = ";"
alpha = "L"
alpha = "8"
alpha = "J"
alpha = "H"
alpha = "6"
alpha = "F"
alpha = "D"
alpha = "S"
alpha = "1"
alpha = "P"
alpha = "O"
alpha = "I"
alpha = "U"
alpha = "Y"
alpha = "E"
alpha = "Q"
alpha = "R"
alpha = "T"
alpha = "W"
alpha = "A"
alpha = "G"
alpha = "]"
alpha = "K"
alpha = "N"
tser = ""
//对从注册表中读出的注册码进行解密
for i = 1 to 16
tmpchr = mid(reg_code,i,1)
for j = 1 to 36
if tmpchr = alpha then//查表,变换,第2列变为第1列,若是想作注册机,需要在此处进行逆运算,1列变2列。
tmpchr1 = alpha
tser = tser + tmpchr1
end if
next
next
ls_disk1 = ""
for i = 1 to 15 step 2//取变换后的注册码的奇数位字符拼接成串
ls_disk1 = ls_disk1 + mid(tser,i,1)
next
if ls_disk1 <> ls_disk then//与硬盘序列号比较
return -1
else
return 0//相等,注册成功
end if
end function
public function string f_encode (string source_str);ulong lu_ll
char lc_char
string ls_rt_str
integer i
integer li_char
for i = 1 to len(trim(source_str))
lc_char = mid(source_str,i,1)
li_char = asc(lc_char)
lu_ll = of_bitwisexor(li_char,100)
ls_rt_str = ls_rt_str + char(lu_ll)
next
return ls_rt_str
end function
public function string f_genpuzzle ();string alpha
string alser
integer i
integer ss
alser = ""
alpha = "A"
alpha = "B"
alpha = "C"
alpha = "D"
alpha = "E"
alpha = "F"
alpha = "G"
alpha = "H"
alpha = "I"
alpha = "J"
alpha = "K"
alpha = "L"
alpha = "M"
alpha = "N"
alpha = "O"
alpha = "P"
alpha = "Q"
alpha = "R"
alpha = "S"
alpha = "T"
alpha = "U"
alpha = "V"
alpha = "W"
alpha = "X"
alpha = "Y"
alpha = "Z"
alpha = "0"
alpha = "1"
alpha = "2"
alpha = "3"
alpha = "4"
alpha = "5"
alpha = "6"
alpha = "7"
alpha = "8"
alpha = "9"
randomize(0)
for i = 1 to 8
ss = rand(36)
alser = alser + alpha
next
return alser
end function
public function string f_genser ();string alser
string tser
char tmpchr
char tmpchr1
integer i
integer j
string ls_mhser
alser = f_getdisk()
alser = f_swap1(alser)
ls_mhser = f_genpuzzle()
ls_mhser = f_swap1(ls_mhser)
tser = left(ls_mhser,4) + left(alser,4) + right(ls_mhser,4) + right(alser,4)
return tser
end function
public function string f_getdisk ();long retval
string sdrv
string str
string str2
string ls_retval
long a
long b
ulong ll_retval
n_cst_numerical ln_1
string ls_format = "0000"
integer li_len
sdrv = "C:\"
str = space(256)
str2 = space(256)
ll_retval = getvolumeinformationa(sdrv,str,256,retval,a,b,str2,256)//调用API,获取硬盘序列号
ls_retval = ln_1.of_hex(retval)//转换为16进制串
if len(ls_retval) > 4 then
li_len = len(ls_retval) - 4
ls_retval = upper(left(ls_format,4 - li_len) + left(ls_retval,li_len) + right(ls_retval,4))//若不足8位,在串前补0
end if
return ls_retval
end function
public function string f_redreg (string xsxt_key);string ls_value
string ls_path
integer li_flag
ls_path = "HKEY_CURRENT_USER\Software\xsxt\xsxt_" + xsxt_key
li_flag = registryget(ls_path,xsxt_key,regstring!,ls_value)
if li_flag = 1 then
return ls_value
else
return "err"
end if
end function
public function integer f_setreg (string str_num,string str_info);string ls_path
integer li_flag
ls_path = "HKEY_CURRENT_USER\Software\xsxt\xsxt_" + str_num
li_flag = registryset(ls_path,str_num,regstring!,str_info)
if li_flag = 1 then
return 0
else
return -1
end if
end function
public function string f_swap1 (string str_input);char alpha
string tser
string alser
char tmpchr
char tmpchr1
integer i
integer j
integer strlen
alpha = "A"
alpha = "B"
alpha = "C"
alpha = "D"
alpha = "E"
alpha = "F"
alpha = "G"
alpha = "H"
alpha = "I"
alpha = "J"
alpha = "K"
alpha = "L"
alpha = "M"
alpha = "N"
alpha = "O"
alpha = "P"
alpha = "Q"
alpha = "R"
alpha = "S"
alpha = "T"
alpha = "U"
alpha = "V"
alpha = "W"
alpha = "X"
alpha = "Y"
alpha = "Z"
alpha = "0"
alpha = "1"
alpha = "2"
alpha = "3"
alpha = "4"
alpha = "5"
alpha = "6"
alpha = "7"
alpha = "8"
alpha = "9"
alpha = "Z"
alpha = "X"
alpha = "C"
alpha = "V"
alpha = "B"
alpha = "9"
alpha = "M"
alpha = ","
alpha = "."
alpha = "/"
alpha = "7"
alpha = ";"
alpha = "L"
alpha = "8"
alpha = "J"
alpha = "H"
alpha = "6"
alpha = "F"
alpha = "D"
alpha = "S"
alpha = "1"
alpha = "P"
alpha = "O"
alpha = "I"
alpha = "U"
alpha = "Y"
alpha = "E"
alpha = "Q"
alpha = "R"
alpha = "T"
alpha = "W"
alpha = "A"
alpha = "G"
alpha = "]"
alpha = "K"
alpha = "N"
tser = ""
alser = trim(str_input)
strlen = len(alser)
for i = 1 to strlen
tmpchr = mid(alser,i,1)
for j = 1 to 36
if tmpchr = alpha then
tmpchr1 = alpha
tser = tser + tmpchr1
end if
next
next
return tser
end function
public function string uf_patchstr (string userstr,integer userlen);integer i
integer strlen
userstr = trim(userstr)
if len(userstr) > userlen then
messagebox("错误","长度错误,无法转换")
return "error"
end if
strlen = userlen - len(userstr)
for i = 1 to strlen
userstr = "0" + userstr
next
return userstr
end function
on user_reg.create
call super::create;
end on
on user_reg.destroy
call super::destroy;
end on
在上面的代码中,关键部分作为注释,现总结一下:
对注册起作用的是f_checkregcode和f_getdisk。
注册码算法为:
1、注册码为16位长度的串,为大写。
2、取出硬盘序列号后,若为8位16进制串,则不变,否则在前补0,拼成8位串。
3、对所得的硬盘序列号串,按f_checkregcode中的明密文转换表,进行变换,变换的结果,分别记入注册表串的奇数位,即1,3,5,7,9,11,13,15的位置。
4、注册码偶数位的字符任意,只要是明密文表中能找到可以了。我在注册机中指定为‘A’。
注册机源码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Strutils;
type
TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
serialnumber: integer;
comlen: DWORD;
flag: DWORD;
str: AnsiString;
alpha: array of char;
i, j: integer;
len: integer;
enstr: array of char;
begin
GetVolumeInformation(Pchar('c:\'), nil, MAX_PATH + 1, @serialnumber, comlen, flag, nil, MAX_PATH + 1);
str := inttohex(serialnumber, 4);
len := length(str);
if (len > 4) then
begin
len := len - 4;
// ls_retval = upper(left(ls_format,4 - li_len) + left(ls_retval,li_len) + right(ls_retval,4))
str := leftstr('0000', 4 - len) + leftstr(str, len) + rightstr(str, 4);
end;
str:=UpperCase(str);
Label1.Caption:=str;
alpha := 'A';
alpha := 'B';
alpha := 'C';
alpha := 'D';
alpha := 'E';
alpha := 'F';
alpha := 'G';
alpha := 'H';
alpha := 'I';
alpha := 'J';
alpha := 'K';
alpha := 'L';
alpha := 'M';
alpha := 'N';
alpha := 'O';
alpha := 'P';
alpha := 'Q';
alpha := 'R';
alpha := 'S';
alpha := 'T';
alpha := 'U';
alpha := 'V';
alpha := 'W';
alpha := 'X';
alpha := 'Y';
alpha := 'Z';
alpha := '0';
alpha := '1';
alpha := '2';
alpha := '3';
alpha := '4';
alpha := '5';
alpha := '6';
alpha := '7';
alpha := '8';
alpha := '9';
alpha := 'Z';
alpha := 'X';
alpha := 'C';
alpha := 'V';
alpha := 'B';
alpha := '9';
alpha := 'M';
alpha := ',';
alpha := '.';
alpha := '/';
alpha := '7';
alpha := ';';
alpha := 'L';
alpha := '8';
alpha := 'J';
alpha := 'H';
alpha := '6';
alpha := 'F';
alpha := 'D';
alpha := 'S';
alpha := '1';
alpha := 'P';
alpha := 'O';
alpha := 'I';
alpha := 'U';
alpha := 'Y';
alpha := 'E';
alpha := 'Q';
alpha := 'R';
alpha := 'T';
alpha := 'W';
alpha := 'A';
alpha := 'G';
alpha := ']';
alpha := 'N';
alpha := 'K';
j := 1;
for i := 1 to 16 do
begin
if i mod 2 <> 0 then
begin
for len := 1 to 36 do
begin
if alpha = str then
begin
enstr := alpha;
break;
end;
end;
inc(j);
end
else
begin
enstr := 'A';
end;
end;
edit1.Text:=enstr;
end;
end.
--------------------------------------------------------------------------------
【经验总结】
这次破解主要在笨鸟我先飞兄弟的基础上做的,他把PBKILLER反编译后的代码给了我,我只是阅读了PB的源码,PB脚本与
BASIC语法类似,兄弟们如果破PB,可以参照BASIC语法来阅读源码。
PBKILLER真的很强,反编译出来的代码可读性很好,呵呵。
--------------------------------------------------------------------------------
【版权声明】: 请保持文章完整及作者信息。
2006年09月04 8:30:32
[ 本帖最后由 caterpilla 于 2006-9-4 10:17 编辑 ] 学习!!支持!!!! 强!!!!!! 看不懂,下来慢慢学 简直是神话。看不懂。。。这么有技术性的文章。得好好收藏! PB方面的教程太少了。 原帖由 xingbing 于 2006-9-4 17:22 发表
PB方面的教程太少了。
PB擅长数据库方面的开发,适合做管理系统。 惊涛兄软件可能在检测注册码的时候还有个地方,我们现在知道他对注册码的奇数位-->转换表-->转换后的八位与硬件码做对比,可是如果我们在偶数位那里随便填入除A或者别的(未测试)数字软件则提示注册错误 原帖由 笨鸟我先飞 于 2006-9-6 08:45 发表
惊涛兄软件可能在检测注册码的时候还有个地方,我们现在知道他对注册码的奇数位-->转换表-->转换后的八位与硬件码做对比,可是如果我们在偶数位那里随便填入除A或者别的(未测试)数字软件则提示注册错误
我试过一些别的字母,在注册机生成后,把偶数位改成其它的字母,当时没提示错误。有没有可能是注册表垃圾信息造成的问题。
页:
[1]