首页
社区
课程
招聘
[原创]休闲麻将 P-CODE 浅析
发表于: 2007-3-31 20:18 19897

[原创]休闲麻将 P-CODE 浅析

2007-3-31 20:18
19897
【文章作者】GoOdLeiSuRe
【分析时间】2007年3月30日
【分析说明】本人很菜,完全入门水准,恳请指正,谢谢。

【软件名称】休闲麻将 3.4
【软件大小】4.43MB
【下载地址】http://zj1.51.net/mj.htm
【软件限制】这是一个共享软件(有30次使用及每次7局限制),注册费:30元,注册后将无任何使用限制。
【注册类型】机器码 + 用户名 -> 注册码,网络验证
【破解过程】
主程序:Mj.exe
PEiD检查:ASPack 2.12 -> Alexey Solodovnikov
脱壳:用AspackDie直接脱
PEiD再检查:Microsoft Visual Basic 5.0 / 6.0
编译方式:用OllyDBG加载,感觉是P-CODE,用WKTVBDebugger加载,果然是P-CODE

//加载后停于此
0049A850: 00 LargeBos
//一路F8瞧瞧
0049A852: 00 LargeBos
0049A854: 4B OnErrorGoto Next
0049A857: 00 LargeBos
0049A859: 04 FLdRfVar 0070FB56h
0049A85C: 04 FLdRfVar 0070FB58h
0049A85F: 05 ImpAdLdRf
0049A862: 24 NewIfNullPr 0041CEA8
0049A865: 0D VCallHresult CVBApp::get_App
0049A86A: 08 FLdPr
0049A86D: 0D VCallHresult get__ipropPrevInstanceAPP
0049A872: 6B FLdI2
0049A875: 1A FFree1Ad
0049A878: 1C BranchF 0049A87F (Jump )
0049A87B: 00 LargeBos
0049A87D: FC Lead1/End
0049A87F: 00 LargeBos
//读取安装目录吧?
0049A881: 1B LitStr: 'SetupDir'
0049A884: 43 FStStrCopy
0049A87B: 00 LargeBos
0049A87D: FC Lead1/End
0049A87F: 00 LargeBos
0049A881: 1B LitStr: 'SetupDir'
0049A884: 43 FStStrCopy
0049A887: 04 FLdRfVar 0070FB48h
//注册表字符串,说不定用户名与注册码也会储存在这儿
0049A88A: 1B LitStr: 'SoftWare\NetMJ\Infomation'
0049A88D: 43 FStStrCopy
0049A890: 04 FLdRfVar 0070FB4Ch
0049A893: F5 LitI4: -> 80000002h -2147483646
0049A898: 59 PopTmpLdAdStr
//读取注册表“SoftWare\NetMJ\Infomation”,获取“SetupDir”值
0049A89B: 0B ImpAdCallI2 modPubTools!0044C5C4h
0049A8A0: 31 FStStr
……
//F5运行


点击:Form Manager
在窗口下拉列表中看到了重要窗口:frmUserReg
点击:Command
在弹出窗口选择:cmdOK
点击:BPX,进行中断

接着返回主程序,输入一些注册信息,一但“确定”就会中断:
0044485C: 04 FLdRfVar 0070F378h
0044485F: 21 FLdPrThis 004FC52Ch
00444860: 0F VCallAd frmUserReg.txtUserName
00444863: 19 FStAdFunc 0070F37C
00444866: 08 FLdPr
00444869: 0D VCallHresult get__ipropTEXTEDIT
0044486E: 6C ILdRf 00000000h
00444871: 0B ImpAdCallI2 rtcTrimBstr on address 660E6AC5h
//用户名
00444876: FD Lead2/PopTmpLdAdStr
0044487A: 1B LitStr: 'RegName'
0044487D: 43 FStStrCopy
00444880: 04 FLdRfVar 0070F36Ch
00444883: 1B LitStr: 'SoftWare\NetMJ\Infomation'
00444886: 43 FStStrCopy
00444889: 04 FLdRfVar 0070F370h
0044488C: F5 LitI4: -> 80000002h -2147483646
00444891: 59 PopTmpLdAdStr
00444894: 0A ImpAdCallFPR4 modPubTools!0044507Ch
00444899: 32 FFreeStr
004448A4: 1A FFree1Ad
004448A7: 04 FLdRfVar 0070F378h
004448AA: 21 FLdPrThis 004FC52Ch
004448AB: 0F VCallAd frmUserReg.txtPassword
004448AE: 19 FStAdFunc
004448B1: 08 FLdPr
004448B4: 0D VCallHresult get__ipropTEXTEDIT
004448B9: 6C ILdRf 00000000h
004448BC: 0B ImpAdCallI2 rtcTrimBstr on address 660E6AC5h
//注册码
004448C1: FD Lead2/PopTmpLdAdStr
004448C5: 1B LitStr: 'RegCode'
004448C8: 43 FStStrCopy
004448CB: 04 FLdRfVar 0070F36Ch
004448CE: 1B LitStr: 'SoftWare\NetMJ\Infomation'
004448D1: 43 FStStrCopy
004448D4: 04 FLdRfVar 0070F370h
004448D7: F5 LitI4: -> 80000002h -2147483646
004448DC: 59 PopTmpLdAdStr
004448DF: 0A ImpAdCallFPR4 modPubTools!0044507Ch
004448E4: 32 FFreeStr


很明显,注册信息存储于注册表项:SoftWare\NetMJ\Infomation
RegName 用户名
RegCode 注册码

F5,主程序要求退出

重新加载,并由以上信息“ImpAdCallI2 modPubTools!0044C5C4h”找出调用注册信息的位置

//用户名 在此使用:GoOdLeiSuRe
00449928: 23 FStStrNoPop -> 'GoOdLeiSuRe'
0044992B: 0B ImpAdCallI2 rtcLowerCaseBstr on address 660E6A2Dh
00449930: 31 FStStr -> 'goodleisure'
00449933: 32 FFreeStr
0044993C: 1B LitStr: 'regcode'
0044993F: 43 FStStrCopy
00449942: 04 FLdRfVar 0070F690h
00449945: 1B LitStr: 'SoftWare\NetMJ\Infomation'
00449948: 43 FStStrCopy
0044994B: 04 FLdRfVar 0070F694h
0044994E: F5 LitI4: -> 80000002h -2147483646
00449953: 59 PopTmpLdAdStr
00449956: 0B ImpAdCallI2 modPubTools!0044C5C4h
//注册码 在此使用:7878787878
0044995B: 31 FStStr -> '7878787878'
0044995E: 32 FFreeStr
00449965: 05 ImpAdLdRf
00449968: F4 LitI2_Byte: -> 1h 1
0044996A: FC Lead1/FnUBound
0044996C: F5 LitI4: -> 1h 1
00449971: AA AddI4
00449972: 71 FStR4
00449975: 6C ILdRf 004F08F8h
//用户名长度
00449978: 4A FnLenStr 004F08F4h , 11 chars
00449979: F5 LitI4: -> 1h 1
0044997E: DB GtI4
0044997F: 6C ILdRf 004F0E44h
//注册码长度
00449982: 4A FnLenStr 004F0E40h , 10 chars
00449983: F5 LitI4: -> Ah 10
//比较
00449988: C7 EqI4
00449989: C4 AndI4
0044998A: 1C BranchF 00449A03
0044998D: 6C ILdRf 004F0E44h
//反置注册码 StrReverse()
00449990: 0B ImpAdCallI2 rtcStrReverse on address 660F7DF1h
00449995: 31 FStStr 004F1590h to 0070F7A4h -> '8787878787'
00449998: F5 LitI4: -> 0h 0
0044999D: 04 FLdRfVar 0070F69Ch
004499A0: 05 ImpAdLdRf
004499A3: F4 LitI2_Byte: -> 1h 1
004499A5: FC Lead1/FnUBound
004499A7: FE Lead3/ForI4:
004499AD: 6C ILdRf 00000003h
004499B0: 05 ImpAdLdRf
004499B3: 9E Ary1LdI4
//注册码长度
004499B4: 4A FnLenStr 004E5594h , 10 chars
004499B5: F5 LitI4: -> Ah 10
//比较
004499BA: C7 EqI4
004499BB: 1C BranchF 004499FB 
004499BE: 1B LitStr: '听'
//取其7位长度
004499C1: F5 LitI4: -> 7h 7
004499C6: 6C ILdRf 00000000h
004499C9: 05 ImpAdLdRf
004499CC: 9E Ary1LdI4
004499CD: 0B ImpAdCallI2 rtcRightCharBstr on address 660E6362h
004499D2: 23 FStStrNoPop
 -> '8888889'
 -> '3925743'
004499D5: 2A ConcatStr
004499D6: 31 FStStr
 -> 'zjm8888889'
 -> 'zjm3925743'
004499D9: 2F FFree1Str 004F82B0h
004499DC: 6C ILdRf 004F1590h
004499DF: 04 FLdRfVar 0070F694h
004499E2: 04 FLdRfVar 0070F6A8h
004499E5: 04 FLdRfVar 0070F6A0h
//关键处
004499E8: 10 ThisVCallHresult 0043EF68->0043EF68
004499ED: 6C ILdRf 00000000h
//字符串比较
004499F0: 30 EqStr
004499F2: 2F FFree1Str
004499F5: 1C BranchF 004499FB (Jump ?
004499F8: 1E Branch 00449A03
004499FB: 04 FLdRfVar 0070F69Ch
//循环一次
004499FE: 66 NextI4: jump to 004499AD
00449A03: 6C ILdRf 00000000h
00449A06: 05 ImpAdLdRf
00449A09: F4 LitI2_Byte: -> 1h 1
00449A0B: FC Lead1/FnUBound
00449A0D: D6 LeI4
00449A0E: 1C BranchF 00449A50
00449A11: F4 LitI2_Byte: -> 0h 0
00449A13: 21 FLdPrThis 004E5EF8h
00449A14: 0F VCallAd frmGameMain.mnuReg
00449A17: 19 FStAdFunc
00449A1A: 08 FLdPr
00449A1D: 0D VCallHresult put__ipropVISIBLEMENU


关键处
0043EE68: FF Lead4/ZeroRetVal
0043EE6A: 80 ILdI4
//用户名长度
0043EE6D: 4A FnLenStr
0043EE6E: F5 LitI4: -> 7h 7
0043EE73: DB GtI4
//10>7?
0043EE74: 1C BranchF 0043EE8A
0043EE77: F5 LitI4: -> 7h 7
0043EE7C: 80 ILdI4
//取右边7位:goodleisure
0043EE7F: 0B ImpAdCallI2 rtcRightCharBstr on address 660E6362h
0043EE84: 31 FStStr -> 'leisure'
0043EE87: 1E Branch 0043EE9
0043EE8A: 80 ILdI4
0043EE8D: 43 FStStrCopy
0043EE90: F5 LitI4: -> 1h 1
0043EE95: 6C ILdRf 00000000h
//取左边1位:leisure
0043EE98: 0B ImpAdCallI2 rtcLeftCharBstr on address 660E625Eh
0043EE9D: 31 FStStr -> 'l'
0043EEA0: F5 LitI4: -> 0h 0
0043EEA5: F5 LitI4: -> FFFFFFFFh -1
0043EEAA: F5 LitI4: -> 1h 1
0043EEAF: F5 LitI4: -> 0h 0
0043EEB4: 6C ILdRf 004E2EBCh
0043EEB7: 6C ILdRf 004F0E44h
//去除字符“l”:leisure
0043EEBA: 0B ImpAdCallI2 rtcReplace on address 660F7E44h
0043EEBF: 31 FStStr 004F2CA4h to 0070F6C4h -> eisure
0043EEC2: 6C ILdRf 004E2EBCh
0043EEC5: F5 LitI4: -> 0h 0
//比较字符串,是否为空?
//以前版本存在同字符漏洞。
0043EECA: 30 EqStr
0043EECC: 1C BranchF 0043EED5
0043EECF: FF Lead4/ExitProcCbHresult
0043EED5: 80 ILdI4
//zjm8888889
0043EED8: 6C ILdRf 004F0E44h
0043EEDB: 2A ConcatStr
0043EEDC: 31 FStStr 004E5EB4h to 0070F6C4h -> zjm8888889leisure
0043EEDF: F5 LitI4: -> 0h 0
0043EEE4: 43 FStStrCopy
0043EEE7: F5 LitI4: -> 1h 1
0043EEEC: 04 FLdRfVar 0070F5C8h
0043EEEF: 6C ILdRf 004F2CA4h
0043EEF2: 4A FnLenStr -> 17 char
//FOR 循环,字符串长
0043EEF3: FE Lead3/ForI4:
0043EEF9: 6C ILdRf 00000000h
0043EEFC: 28 LitVarI2 1h , 1
0043EF01: 6C ILdRf 00000001h
//zjm8888889leisure
0043EF04: 6C ILdRf 004E5EB4h
0043EF07: 0B ImpAdCallI2 rtcMidCharBstr on address 660E64A6h
0043EF0C: 23 FStStrNoPop -> 逐个字符(z,j,m,...)
//各字符ASC()码
0043EF0F: 0B ImpAdCallI2 rtcAnsiValueBstr on address 660E657Bh
0043EF14: E7 CI4UI1
//与上一循环而得的商值相加
0043EF15: AA AddI4
//ABS()
0043EF16: BC FnAbsI4
//STR()
0043EF17: 71 FStR4
0043EF1A: 2F FFree1Str
0043EF1D: 35 FFree1Var
0043EF20: 6C ILdRf 00000000h
//上述求得的值
0043EF23: 6C ILdRf 0000007Ah
0043EF26: F5 LitI4: -> Ah 10
//与10求余
0043EF2B: C2 ModI4
//STR()
0043EF2C: FE CStrI4
0043EF2E: 23 FStStrNoPop -> 余值字符串
0043EF31: 2A ConcatStr
0043EF32: 31 FStStr
0043EF35: 2F FFree1Str
0043EF38: 6C ILdRf 0000007Ah
0043EF3B: F5 LitI4: -> Ah 10
//与10相除的商
0043EF40: C0 IDvI4
//STR()
0043EF41: 71 FStR4
0043EF44: 04 FLdRfVar 0070F5C8h
//Next 循环
0043EF47: 66 NextI4: jump to 0043EEF9
0043EF4C: F5 LitI4: -> Ah 10
0043EF51: 6C ILdRf 004F2CFCh
//取右边10位长:2234266963 -> 实际上反置过来就是需要的注册码了
0043EF54: 0B ImpAdCallI2 rtcRightCharBstr on address 660E6362h
0043EF59: 31 FStStr
0043EF5C: 6C ILdRf 004F2CFCh


【算法分析】
1,用户名长度要大于2位,转化为小写;
2,注册码长度为10位;
3,zjm + 机器码右7位 + 用户名右7位
4,逐个取字符,求ASCII码,与10除,余数转化为字符,商值与下一字符的ASCII码相加
5,余数字符串反置即为注册码

【网络验证】
软件在连网的状态下,会进行验证(用Iris捕获):
HTTP://zj1.51.net/cgi%2Dbin/mjlink.cgi?work=update&rgn=用户名&hid=XXXXXXX&mid=机器码右7位&mid0=YYYYYYY&mid1=&ver=312

返回ckerror则清除注册表内的注册码,返回ckok则验证正确
缺少用户名等信息不全,会返回一些升级信息
具体分析代码就省略了。

(参考)避开网络通验证,通常可修改hosts文件(位于WINDOWS\system32\drivers\etc),添加:
127.0.0.1    zj1.51.net

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 7
支持
分享
最新回复 (19)
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
2
非常好,
我没用过VBVKTDEBUG(一直运行不起来),以前爆破过休闲麻将v3.2.275,因为P-CODE的缘故,用OD非常吃力。
今天看到你的破文,如此清晰
2007-3-31 21:21
0
雪    币: 817
活跃值: (1927)
能力值: ( LV12,RANK:2670 )
在线值:
发帖
回帖
粉丝
3
网络验证直接跳过,不检测则OK了
2007-3-31 21:21
0
雪    币: 144
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
是不是WKT断不了启动的NAG呢 :(
2007-3-31 22:25
0
雪    币: 144
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
你把WKT那DLL放在sys32没有啊 :)
2007-3-31 22:36
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
6
oh,Thank you,
好像提示要替换system32下的某个dll,为了系统稳定,我就放弃了
2007-4-1 11:15
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
支持,楼主强人
2007-4-1 16:20
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
要是用注册文件就晕了
2007-4-1 16:22
0
雪    币: 405
活跃值: (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
9
厉害厉害。修改host能通过网络验证啊~~原来如此,我试试看哦
2007-4-1 18:14
0
雪    币: 203
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
Running under win NT/2000,Version:5.1
我在调试的时候显示这个提示,怎么解决?
2007-4-1 19:21
0
雪    币: 136
活跃值: (105)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
11
又学习一招简单的爆破网络验证哈哈
2007-4-1 21:09
0
雪    币: 237
活跃值: (175)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
12
是替换"imagehlp.dll"吧?担心的话,忽略就可以了。
2007-4-1 21:16
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
楼主是不是说只要HOST改一下就可以了通过了还是要修其它的??
2007-4-14 22:38
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
比如我正确注册信息验证码申请的数据为这个 /aa/default.aspx?koulingID=test6792&jiamiID=SDLFSDLFQQPDEEEEQQYVLFYVYVLFQQYVLFYVQQPDQQQQXHPDYVEEGEYVSDXHEEQQGEYVLFSDLF&mimaID=1235dbew  服务器为WWW.XXX.COM  那么在我本地要怎么样正行设置,才能变成本地验证,,, 是不在HOST改成27.0.0.1   WWW.XXX.COM 那要本地服务的根目录下要怎样建文件和文件内容的代码是什么, 高手请指教,
2007-4-14 22:45
0
雪    币: 180
活跃值: (59)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
我这里看楼主文章怎么会这样,好像重叠了
上传的附件:
2007-4-15 09:22
0
雪    币: 289
活跃值: (368)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
怎么会有文字重叠?
2007-4-15 10:35
0
雪    币: 178
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
牛啊~~~~~
2007-4-15 12:41
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
完全不懂,这段怎么解,能说详细点?怎么找?和调出?

重新加载,并由以上信息“ImpAdCallI2 modPubTools!0044C5C4h”找出调用注册信息的位置
2007-4-16 10:41
0
雪    币: 237
活跃值: (175)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
19
相当于告诉你: 拦截信息框用 BPX MessageBoxA
2007-4-18 20:36
0
雪    币: 237
活跃值: (175)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
20
仅供参考:用这种方式,可以编个ASP或其支持的动态交互页面转一下。至于代码:response.redirect("...Google搜搜吧...")
2007-4-18 20:44
0
游客
登录 | 注册 方可回帖
返回
//