【文章标题】: 第一次破解pb程序的历程
【文章作者】: monking
【软件名称】: ××××许可证管理系统
【软件大小】: 18.8M
【下载地址】: 自己搜索下载
【加壳方式】: 无
【保护方式】: 无
【编写语言】: pb
【使用工具】: od,PBKiller,ue
【操作平台】: windows
【作者声明】: 本文纯属学习探索,请勿用于非法用途之类的
--------------------------------------------------------------------------------
【详细过程】
记得上学的时候课本就告诉我们,程序语言的翻译方式有两种,一个是编译,一个是解释。像,basic就是解释性语言。
而具体解释跟编译有什么区别,自己却在现实中却没有感性的接触过。前两天,朋友让看一下一个软件的注册算法。于是
乎安装,然后用od载入。
跟踪了半天,发现程序老在pbvm80.dll的空间里面打转转,本来想找magic jmp,然后爆破,却怎么也找不到。发现程序
一直在pbvm80.dll的一段代码里反复执行。晕过之余,发现原来pbvm80.dll是system32下的一个dll文件,按照以前破解解
释性语言程序的思路分析,magic jmp肯定在程序自己的代码空间,而不是pbvm80.dll。而这里,一直在非程序代码的空间
里面打转转。有点不知所措了。无奈之下,在网上找到了关于pbvm80.dll文件的信息,原来这个文件跟powerbuilder的程序
有关。而pb程序又是解释执行的。这才想起了,曾经课本告诉自己的理论知识,潜意识觉得这个软件跟以前那些调试过的软
件有某种不同,而这些不同自己却还没有碰到过。
于是在看雪里面找了lzqgj的《pb程序调试初探》(http://bbs.pediy.com/showthread.php?t=44277),拜读之后,才知
道一般解释性程序要反编译,有可能从中能得到源代码,从而可以大大缩减劳动力。恍然大悟。更让我对编写这些反编译工
具的前辈们佩服犹如滔滔江水。。。。,^_^。
之后用pbkiller反编译软件安装文件夹下的所有pbd文件,并分析。在fs_public.pbd->w_regedit->cb_1->Events->clicked()
函数中找到如下代码:
+-----------------------------------------------------
string ls_filefullname
string ls_filename
string ls_department
string ls_decryptname
string ls_departmentid
long ll_departmentid
ls_departmentid = trim(parent.sle_4.text)
if ((isnull(ls_departmentid)) or (ls_departmentid = "")) then
messagebox("错误","请您输入正确的单位ID!")
parent.sle_4.setfocus()
return
end if
ll_departmentid = long(ls_departmentid)
ls_department = trim(parent.sle_1.text)
if ((isnull(ls_department)) or (ls_department = "")) then
messagebox("错误","请您输入正确的单位名称!")
parent.sle_1.setfocus()
return
end if
ls_filefullname = trim(parent.sle_2.text)
if ((isnull(ls_filefullname)) or (ls_filefullname = "")) then
messagebox("错误","请您输入正确的序列号!")
parent.sle_2.setfocus()
return
end if
ls_filefullname = replace(ls_filefullname,15,1,"")
ls_filefullname = replace(ls_filefullname,10,1,"")
ls_filefullname = trim(replace(ls_filefullname,5,1,""))
if len(ls_filefullname) <> 16 then
messagebox("错误","序列号必须为16位!")
parent.sle_2.setfocus()
return
end if
ls_decryptname = parent.mdstring(ls_departmentid,len(ls_departmentid)) //用md5算法加密用户id
ls_decryptname = upper(left(ls_decryptname,16)) //转化为大写
if ls_decryptname <> ls_filefullname then //关键判断语句
messagebox("错误","请您输入正确的序列号!")
parent.sle_2.setfocus()
return
end if
update sys_config SET depart_name =' ' , serial_no =' ' , harddisk_no =' ' Where soft_name ='××××许可证管理信息系统' using sqlca;
/* SQL Parameters List
0-> :ls_department
1-> :ls_filefullname
2-> :ls_departmentid
*/
if sqlca.sqlcode <> 0 then
rollback using sqlca;
messagebox("提示","新用户注册失败,请重新注册!")
parent.sle_2.setfocus()
return
end if
DELETE FROM t_depart WHERE depart_id =0 using sqlca;
/* SQL Parameters List
0-> :ll_departmentid
*/
INSERT INTO t_depart ( depart_id , department_id , depart_name , depart_order ) VALUES ( 0 , 0 , ' ' , 0 ) using sqlca;
/* SQL Parameters List
0-> :ll_departmentid
1-> :ll_departmentid
2-> :ls_department
*/
if sqlca.sqlcode <> 0 then
rollback using sqlca;
messagebox("提示","新用户注册失败,请重新注册!")
return
end if
commit using sqlca;
gb_register = true
messagebox("成功","注册成功,欢迎" + ls_department + "使用××××许可证管理系统!~r~n应用程序需要关闭后重新启动。")
halt
return
+-----------------------------------------------------
注册算法一目了然。pbkiller太强大了。
原来他是将用户id作为参数做md5散列(32位),然后将散列值转为大写。取左16位,作为注册序列号。
最为检验,随便输入了一个id,然后在www.cmd5.com上获取id的32位散列值,改为大写,取左16位,点击注册,
哈哈,注册成功。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
[课程]Linux pwn 探索篇!