前往Shuct.Net首页

Shudepb PB反编译专家长时间以来,为业内同类软件事实上的唯一选择.细节,彰显专业.态度,决定品质.

关于shudepb的搜索

用PBNI实现软件注册授权控制 - 淡定的日志 - 网易博客 网易 新闻 微博 邮箱 相册 阅读 有道 摄影 爱拍 优惠券 云笔记 闪电邮 手机邮 印像派 网易识字 更多 博客 手机博客 博客搬家 博客VIP服务 LiveWriter写博 word写博 邮件写博 短信写博 群博客 博客油菜地 博客话题 博客热点 博客圈子 找朋友 发现 小组 风格 网易真人搭配社区iStyle 把最美的记录工具,装进你的口袋 >> 把最美的记录工具,装进你的口袋 >> 把最美的记录工具,装进你的口袋 >> 创建博客 登录 加关注 显示下一条 | 关闭 温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》 | 关闭 快乐成长 记录身边的事情,留下美好的回忆! 导航 首页 日志 相册 音乐 收藏 博友 关于我 日志 用PBNI实现软件注册授权控制 2010-11-22 17:43:18| 分类: pb | 标签: |举报 |字号大中小 订阅 自从PB的程序可以被pbkiller和shudepb反编译以来,程序的安全性,软件的注册授权控制就存在很大的风险,这些核心代码被轻易的暴露出来,从而导致程序很容易被破解,损害软件开发者的利益。因此有人把这部分核心代码,采用VC或Dephi进行重写,并编译为dll的方式给pb的程序调用,以免注册部分的代码被反编译,以防止软件被破解,而不是采用PBNI的方式,其实这样做也是不安全的。下面将通过实例,演示采用dll来进行软件注册控制的不安全性。 首先,使用vc6开发一个TestA的动态连接库工程,这个库文件包含两个函数,CheckKey和Add, CheckKey用于判断输入的字符串,是否等于12345678,相等则返回TRUE,否则返回False, Add函数用于返回两个数相加的结果。代码很简单,如下: BOOL WINAPI CheckKey(LPCSTR key){ if(strcmp(key,"12345678")==0) return TRUE; else return FALSE;}int WINAPI Add(int a, int b){ return a+b; } 编译生成TestA.dll文件。然后用PB9新建一个应用程序,并把TestA.dll文件拷贝到这个程序目录下面。 增加一个w_main窗口,在窗口的Local External Function中定义以下两个API函数 Function boolean CheckKey(string key) Library "TestA.dll"Function int Add(int a ,int b ) Library "TestA.dll" 在窗口中增加两个按扭,分别为CheckKey和Add,其中CheckKey按扭的代码如下: Code Add按钮的代码如下:MessageBox('Add计算',"100+30="+string(Add(100,30))) 运行程序,点击CheckKey按钮,弹出下面两个窗口 点击Add按钮,弹出下面窗口 从以后代码的执行情况看,TestA.DLL的功能被正确调用 下面,我们用pbkiller反编译这个应用生成后的pbd文件,查看w_main窗口的代码,我们可以清楚的看到TestA.dll这个库文件的函数定义,包括函数名称和参数列表。在取得这些信息之后,我们就可以写一个dll文件,来绕开CheckKey这个函数,让其总是返回TRUE,这样就使得注册验证失效了。 还是使用VC6 新建一个TestB的动态连接库的工程,在工程里面增加以下两个函数,其中CheckKey不做任何校验处理,直接返回TRUE,Add函数则调用原来TestA(改名为MyTestA.dll)库文件的函数。Code编译这个dll,然后把原来pb程序目录下的testA.dll文件改名为MyTestA.dll,然后把TestB.dll文件拷到pb程序目录下,并更名为TestA.dll。 运行程序,点击CheckKey按钮后,弹出以下窗口 点击Add按钮后,弹出以下窗口 从上面的程序执行情况看,CheckKey功能已经失效,Add功能与原来的效果一样。 但如果DLL文件中不公开CheckKey函数,而是在调用Add函数的时候,调用CheckKey,则就没办法绕开了. 即然PB程序采用调用DLL文件的方式来进行软件注册授权控制,很容易被绕开,那么该如何解决这一问题呢? 从PB9开始,增加了PBNI功能,可以直接采用VC来编写可视和不可视的组件给PB的应用程序调用,以实现PB应用功能的扩展.采用这种技术架构,可以非常方便的把原来的VC中的功能,封装为PB的可视对象或不可视对象,给PB的应用程序使用,而不需要在程序中定义各种API函数.而且由于PBNI编译后的PBD文件,并不是使用PB的代码指令,用pbkiller和shudepb都无法对期进行反编译,可以有效的保护软件系统核心部分代码的安全. 下面,我们采用VC6来开发一个PBNI组件,用于封装上一篇文件中所实现的CheckKey和Add函数功能.(如果是PB9,则建议采用VC6作为开发环境,如果是PB10以上版本,则建议采用VS2003作为开发环境.) 配置开发环境 首先,按照帮助文件的说明,配置VC6的开发环境,以便使用PBNI的应用向导,以及向开发环境增加PBNI的头文件和库文件的目录. 1.把C:\Program Files\Sybase\PowerBuilder 9.0\SDK\PBNI\wizards\pbext.awx文件拷到C:\Program Files\Microsoft Visual Studio\COMMON\MSDev98\Bin\IDE目录,以便在VC6中可以使用PBNI应用程序向导. 2.打开VC6,选择工具---选择---目录,增加以下选项. C:\Program Files\Sybase\PowerBuilder 9.0\SDK\PBNI\include C:\Program Files\Sybase\PowerBuilder 9.0\SDK\PBNI\Lib新建一个PBNI工程 1.文件---新建---工程,选择PBNI Extension App Wizard,输入工程名称,选择工程的保存路径,按确定. 2.输入对象名称,n_cst_service,由于VC6的向导只能增加不可视对象,所以该对象最好生成的是不可视对象组件. 3.按完成,向导出自动生成PBNI所需要的各种全局函数,并增加了n_cst_Service这个不可视对象的定义,以及相对应的VC类对象.向导会为n_cst_Service增加SampleMethod1和SampleMethod2两个函数,这两个函数没什么意义,需要把它改成需要的CheckKey的Add函数.实现对象功能 1.打开PBX_GetDescription函数,定义生成PB对象的描述定义.向导生成的n_cst_service对象的代码如下:Code 把SmpleMethod1和SampleMethod2删除掉,并增加CheckKey和Add函数的定义,n_cst_service的描述定义最后为: Code 2.打开n_cst_service.h文件,修改n_cst_service对应的vc类的定义,删除SampleMethod1和SampleMethod2函数的定义,并增加ChcekKey和Add函数的定义,最后代码如下Code 3.打开n_cst_service.cpp文件,同样删除向导生成的函数,并增加CheckKey和Add函数的功能,最后生成的代码如下: Code 4.编译程序,生成pbx文件. 5.用pbx2pbd90程序,生成pb应用程序使用的pbd文件. pbx2pbd90 {dir}\PBNI_Test.pbd {dir}\PBNI_Test.PBX引用程序 1.把PBNI_Test.PBX和PBNI_Test.PBD拷贝到pb程序应用的目录下,用pb9打开应用程序,,在程序的库文件列表中增中上面生成的PBD文件. 2.打开w_main窗口,CheckKey按钮的代码更改为:Code Add按钮的代码更改为:n_cst_service n_servicen_service = Create n_cst_service MessageBox('Add计算',"100+30="+string(n_service.Add(100,30)))Destroy n_service 3.运行程序,点击CheckKey按钮,弹出下面两个窗口 点击Add按钮,弹出下面窗口. 4.使用pbkiller打开上面生成的pbd文件,显示错误信息,不能被反编译. 后注 使用PBNI可以防止代码被pbkiller和shudepb反编译,也可以防止直接采用dll的方式,被直接绕开的情况,相对要安全一点.但这种安全也是相对的,所以一般还需要在程序增加对这个pbd文件进行验证,如根据文件的MD5值,确定该文件没有被修改或被替换. 评论这张 转发至微博 转发至微博 阅读(861)| 评论(0) | 分享到: 喜欢 推荐 0人 | 转载 历史上的今天 最近读者 热度 评论 this.p={ m:2, b:2, id:'fks_094066085087088067085094083095081095082064081080', blogTitle:'用PBNI实现软件注册授权控制', blogAbstract:' 自从PB的程序可以被', blogTag:'', blogUrl:'blog/static/5933562010102254318898', isPublished:1, istop:false, type:0, modifyTime:0, publishTime:1290418998898, permalink:'blog/static/5933562010102254318898', commentCount:0, mainCommentCount:0, recommendCount:0, bsrk:-100, publisherId:0, recomBlogHome:false, currentRecomBlog:false, attachmentsFileIds:[], vote:{}, groupInfo:{}, friendstatus:'none', followstatus:'unFollow', pubSucc:'', visitorProvince:'', visitorCity:'', visitorNewUser:false, postAddInfo:{}, mset:'000', mcon:'', srk:-100, remindgoodnightblog:false, isBlackVisitor:false, isShowYodaoAd:false, hostIntro:'每个人都可以有巨大的雄心及高远的梦想,区别在于有没有能力实现这些梦想。当梦想成真的时候,会否在成功的台阶上更知进取?当梦境破灭、无力取胜、无能力转败为胜时,会否被套在自命不凡的枷锁里?是否跌进万念俱灭无所期待的沮丧之中?再有学识再成功的人,也要抵御命运? ', hmcon:'1', selfRecomBlogCount:'0', lofter_single:'' } {list a as x} {if !!x} {if x.visitorName==visitor.userName} {else} {/if} {if x.moveFrom=='wap'} {elseif x.moveFrom=='iphone'} {elseif x.moveFrom=='android'} {elseif x.moveFrom=='mobile'} {/if} ${fn(x.visitorNickname,8)|escape} {/if} {/list} {if !!a} ${fn(a.nickname,8)|escape} ${a.selfIntro|escape}{if great260}${suplement}{/if} {/if} {list a as x} {if !!x} ${fn(x.title,26)|escape} {/if} {/list} 推荐过这篇日志的人: {list a as x} {if !!x} ${fn(x.recommenderNickname,6)|escape} {/if} {/list} {if !!b&&b.length>0} 他们还推荐了: {list b as y} {if !!y} ·${y.recommendBlogTitle|escape} {/if} {/list} {/if} 转载记录: {list d as x} · ${x.referBlogTitle|escape} ${x.referUserName|escape} {/list} {list a as x} {if !!x} ${x.title|default:""|escape} {/if} {/list} {list a as x} {if !!x} ${x.title|default:""|escape} {/if} {/list} {list a as x} {if !!x} ${x.blogTile|default:""|escape} {/if} {/list} {list a as x} {if x_index>4}{break}{/if} {if !!x} ${fn1(x.title,60)|escape}${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')} {/if} {/list} {list a as x} {if !!x} ${fn(x.title,26)|escape} {/if} {/list} {if !!(blogDetail.preBlogPermalink)} ${blogDetail.preBlogTitle|escape} {/if} {if !!(blogDetail.nextBlogPermalink)} ${blogDetail.nextBlogTitle|escape} {/if} {list a as x} {if !!x} {if x.publisherUsername==visitor.userName} {else} {/if} ${fn(x.publisherNickname,8)|escape} {/if} {/list} 被推荐日志 最新日志 该作者的其他文章 博主推荐 随机阅读 首页推荐 更多>> {list a as x} {if !!x} ${x.nickName|escape} 投票给 {var first_option = true;} {list x.voteDetailList as voteToOption} {if voteToOption==1} {if first_option==false},{/if} “${b[voteToOption_index]}” {/if} {/list} {if (x.role!="-1") },“我是${c[x.role]}” {/if} ${fn1(x.voteTime)} {if x.userName==''}{/if} {/if} {/list} 页脚 公司简介 - 联系方法 - 招聘信息 - 客户服务 - 隐私政策 - 博客风格 - 手机博客 - VIP博客 - 订阅此博客 网易公司版权所有 ©1997-2014 帮助 ${u} {list wl as x} ${x.g} {list x.l as y} ${y.n} {/list} {/list} {if defined('wl')} {list wl as x}${x.n}{/list} {/if}