首页
社区
课程
招聘
[旧帖] [原创]休闲麻将3.4版本破解--Ollydbg挑战P-CODE程序实战篇 0.00雪花
发表于: 2009-8-18 23:04 3186

[旧帖] [原创]休闲麻将3.4版本破解--Ollydbg挑战P-CODE程序实战篇 0.00雪花

2009-8-18 23:04
3186
目标程序:休闲麻将3.4版本
时间:2009.8.18
工具:OLLydbg,peid0.94,lordpe,ImportREC_fix
面向对象:爱好破解的菜鸟朋友们

写在前面的话:
目标程序是妈妈在家无聊时玩的一个麻将游戏,由P-CODE编写,即VB中的伪代码。
用Ollydbg破解这种语言的程序非常的痛苦,有一定破解基础的朋友可以先行用
Ollydbg破解下程序(其他工具破解,参考看雪论坛精华9:休闲麻将P-CODE浅析)。
而我由于刚开始并不知道P-CODE,硬是用Ollydbg花了3天时间来研究它,此中苦乐
非爱好破解的菜鸟朋友无法理解。。。。

第一步:
用peid0.94查壳。ASPack 2.12 用ESP定律手动脱壳。
介于是个简单壳,我就说下自己所理解的ESP定律,手动脱壳过程不再详细描述。
问题:ESP定律下硬件访问断点的原因以及为什么可以到程序的入口?
首先大家应该明白程序要运行必须要在特定的环境下,一些压缩壳为了不破坏环境,
让程序能够正常运行,将这些环境经行了保护,故当程序运行并访问环境时,Ollydbg
帮我们断下来,然后单步走即可到达OEP(程序入口)。。

第二步:
脱壳之后发现程序是Microsoft Visual Basic 5.0 / 6.0编写的。
试运行程序知道为重启验证,然后搜索注册表,发现了之前用户信息。。。
于是下注册表的断点(至于为什么下这个断点是测试出来的!)
    bp RegCloseKey
F9运行(不过在这之前请确定用户名跟假码存在于注册表)
同时注意寄存器窗口跟堆栈窗口,然后F9一路狂飙下去,
直到寄存器窗口出现你的假码:
    EAX 77DA6BF0 ADVAPI32.RegCloseKey;
      ECX 00000035
      EDX 0040247C unpack.0040247C
      EBX 00165244 UNICODE "1234567890" ;你之前输入的假码
    ESP 0012F6E8
      EBP 0012F7EC
      ESI 0044CC61 unpack.0044CC61
      EDI 0012F6F0
      EIP 77DA6BF0 ADVAPI32.RegCloseKey
此时F8单步走,到达msvbvm60的领空,哎,也怪我孤陋寡闻竟不知道P-CODE。
害我花了半天时间研究为什么不回到程序的领空。。。。
单步走,因为感觉一直在循环,于是我在刚进入的位置下了断点F2,然后又在
其他两处下了F2断点(又一个偷懒的办法,没办法F8手都按疼了)
    733B5434   msvbvm60   始终               CALL DWORD PTR DS:[734A0E7C]
    7348F7F3   msvbvm60   始终               CALL EAX
    7348F996   msvbvm60   始终               CALL msvbvm60.__vbaStrCat
这些断点我是取“寄存器窗口或堆栈窗口出现重要数据时候”时的位置,大家可以在
第一次单步走的时候注意下然后自己下断点,因为本人接触破解才两个多月,黑鹰
算法分析的教程我还没来得及学,所以没想过搞什么算法,也就不必单步跑下去了。
下好断点后,直接按F9,注意寄存器窗口与堆栈窗口,当堆栈出现停止按F9
   0012F718   001501BC  UNICODE "2808222223138415"
   0012F71C   0000000A
   ……
   0012F748   00000010
   0012F74C   001501BC  UNICODE "2808222223138415"
   0012F750   0000000B
   0012F754   00000073
   0012F758   001503A4  UNICODE "zjm8888889search"
   0012F75C   00000011
为什么这个什么时候停,你一直按着F9,又如何知道这个时候停?
呵呵,大家注意到字符的长度没有,两串字符串长度一样。
在有机器码出现算注册码的程序中,一般注册码跟机器码相同位数,
当然肯定还有另外了,这里说的是一般情况,也就是当字符串相同长度
停下来观看一下比较好,当然这些是因为我们偷懒下好断点按F9的缘故。
F8单步走几步,发现寄存器窗口出现了10位字符串:
   EAX 001506F4 UNICODE "2223138415"
我们试运行程序的时候,可以发现注册码为10位,所以这10位字符串应该
引起大家的足够重视。继续F8单步走,在堆栈窗口中发现
   0012F7FC   00167454  UNICODE "2223138415"
   0012F800   001669C4  UNICODE "0987654321"
我们输入的假码反置于之前得到的10位字符串出现在一起
在下方不远处又发现了
   0012F828   00167454  UNICODE "2223138415"
   0012F82C   80000002
   0012F830   00000000
   0012F834   00165244  UNICODE "zjm8888889"
   0012F838   001669C4  UNICODE "0987654321"
   0012F83C   00165DF4  UNICODE "search"
于是推断注册码为2223138415的反置 5148313222
至于如何推断出来的,大家可以试着去尝试,同时注意我们输入的假码
已经被反置了。哎,当时输入10个1的时候根本没发现被倒置,害我把几个
出现的10位字符串试了又试,而且,继续单步走,后面又会出现几个10位
字符串。因为已经得到注册码了,所以后面也就不继续了。

第三步:
爆破或者做内存注册机尝试了很多次,结果:失败!!!。
最后在仔细研究看雪论坛精华上相关的文章后,摸清楚了这个程序的算法。
但因为编程水平,没能写出算法注册机。下面将领悟到的算法简单阐述下:
休闲麻将3.4版本算法分析:(用户名不小于2位,注册码为10位)

首先输入用户名得到注册字符串
zjm+机器码后7位+用户名(大于7位的取后七位)
第一步:取第一个字符串z的ASCII值/10得到商与余数
第二步:将上一步得到的商加上第二个字符串j的ASCII值除10得到商与余数。
第三步:将上一步得到的商加上第三个字符串m的ASCII值除10得到商与余数。
第四步:将上一步得到的商加上第四个字符串(机器码)的ASCII值除10得到商与余数。
……
第十步:将上一步得到的商加上第十个字符串(机器码)的ASCII值除10得到商与余数。
第十一步:将上一步得到的商加上第十一个字符串(用户名)的ASCII值除10得到商与余数。
……
最后一步:将上一步得到的商加上最后一个个字符串(用户名)的ASCII值除10得到商与余数。

然后将每一步得到余数合在一起,组成一串12位到17位的数据(根据用户名的长短而定)
取后面的10位数字,反置即可得到注册码。实例计算我就不写了,留着给读者自己去实践,这
样也可以让读者对算法多一些理解,能够做到触类旁通,举一反三。

总结:
首先要感谢黑鹰基地的三人行或者称之为天草,感谢你让我进入破解的大门。其次还要感谢看雪
论坛,在我屡次碰壁不得结果差不多想要放弃时,看雪论坛精华9里这篇类似的破解文章出现在我
面前,这个发现使疲惫不堪的我又充满了破解的斗志。因为学习破解的时间不长,根本不知道何
为P-CODE,也不会使用WKTVBDebugger,更别说看懂此文章中出现的那些诡异的代码。并且
由于在追踪注册码的过程中出现过很多类似注册码的假码,使我屡次以为成功却遭失败,我都差点
以为程序是不是出错了,还好通过论坛此文章让我了解到注册码长啥样,为后来寻找真正的注册码提
供了方向。在查找相关资料了解了P-CODE编译的软件后,我明白了为什么每次返回到用户代码都会
落到msvbvm60领空。总的来说,这次破解让我收获颇多,从遇到问题分析问题到解决问题的过程
中,我进一步提升了处理问题的能力,更重要的是激起了学习的兴趣。因此我希望加入看雪论坛这个
大家庭,与更多的破解爱好者交流技术。

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 20
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
算法分析在本人另一篇原创文章中已经阐述此处不再啰嗦。没看的朋友可以看下:
http://bbs.pediy.com/showthread.php?t=96041(破解休闲麻将3.4版本
--Ollydbg挑战P-CODE程序实战篇)

这是本人学破解两个多月来第一次编写算法注册机,虽然不怎么样,但是也应该算是
完成品吧,使用的语言8086汇编语言。⊙﹏⊙b汗,其他语言不会。。。。
最后希望看雪论坛能给我个邀请码。

算法注册机使用说明:
用户需在程序中按要求输入注册信息

字符串规则:zjm+机器码的后七位+用户名

注意:用户名须大于2位,超过7位取后七位

例如:你的机器码为:3148313222,你想注册的用户名为:search

那么你应该输入:zjm8313222search 输完之后按回车即可!

8086汇编语言编写的算法注册机源代码:
;******************************************************
;程序:休闲麻将3.4版本算法注册机
;作者:search
;程序由8086汇编语言编写
;日期:2008-8-19日凌晨
;******************************************************
data segment
  head db " Please input the 12-17 bit character string!!!",0ah,0dh
       db " After finish ,press the 'enter' key to continue...",0ah,0dh
       db 0ah,0dh,"character string :",'$'
  msg1 db " This character string is less than 12 bit!",'$'
  msg2 db " This character string is more than 17 bit!", '$'
  msg3 db " The 10 bit regeist's code is :",'$'
  bye  db " please press any key to quit!!",'$'
  store db 20 dup (?)
  regcode db 20 dup (?)
data ends
code segment
  assume ds:data,cs:code
start:
   mov si,0       ;si指针赋初值0
   mov ax,data
   mov ds,ax
   lea dx,head   
   call displays          ;调用显示字符串子程序
input:                      ;开始输入字符串
  cmp si,17              ;比较输入的字符串是否大于17位
  jle  continue_input    ;小于等于17位跳转
  call enter                  ;调用回车换行子程序
  call enter
   lea dx, msg2
   call displays
   jmp exit
continue_input:
   mov ah,01h   
   int 21h        
   cmp al,0dh             ;判断输入的字符是否回车
  je finish_input        ;是回车则跳转到输入完成
  mov store[si],al     ;把输入的字符保存到存储器
  inc si         
   jmp input
finish_input:
    mov store[si],24h   ;给输入的字符串加$符号
   cmp si,12               ;比较输入的字符串是否小于12位
   jge right                ;大于等于12位跳转
   call enter
    call enter
    lea dx,msg1        
    call displays
    jmp exit
right:
    dec si
    mov di,si
    xor si,si
    xor bx,bx
    call enter
    call enter
    lea dx,msg3
    call displays
  output:
    xor ax,ax
    mov al,store[si]        ;取一位输入的字符串,
    cmp al,24h              ;比较是否为$
   je continue_output  ;是则结束
  add al,bh                 ;字符串的ASCII值加上一次运算的商
  mov bl,0ah              ;把10赋值给bl
   div bl                      ;al除以10,商放在al中,余数放在ah中
  mov bh,al              ;al商送给bh保存
  add ah,30h            ;ah加上30h,装化为数字的ASCII值
  mov regcode[di],ah  ;把运算好字符串保存到存储器
  dec di
   inc si
   jmp output
continue_output:        ;开始输入正确的注册码
xor di,di
finish_output:
    cmp di,10                ;判断是否输出了10位注册码
  jge exit                    ;大于等于11(10-0+1=11)位时,离开
  mov dl,regcode[di]  ;把一位注册码传送到dl寄存器中
  mov ah,02h             ;调用系统2号功能输出注册码
  int 21h
   inc di
   jmp finish_output
exit:                              ;结束离开
   call enter
    call enter
    lea dx,bye
    call displays
    mov ah,08h         ;8号系统功能,输入无回显,起到暂停作用
   int 21h
    mov ah,4ch         ;退出Dos
    int 21h
displays proc near     ;显示字符串的子程序
   mov ah,09h
    int 21h
    ret
displays endp
enter proc near        ;显示回车换行子程序
   mov dl,0dh
    mov ah,02h
    int 21h
    mov dl,0ah
    mov ah,02h
    int 21h
    ret
enter endp
code ends
     end start         ;代码结束
2009-8-19 04:57
0
雪    币: 20
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
各位版主大大 这些代码都是俺一点一点写出来的啊 没有功劳也有苦劳啊 给个邀请码吧。。。
2009-8-19 16:24
0
雪    币: 20
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这个破解目标绝对值得大家去试试,别看我写的简单。此中苦乐还需要大家去体会啊。。。
2009-8-19 16:29
0
雪    币: 164
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
:-)  支持一个
2009-8-19 16:52
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
6

休闲麻将NETMJ V2.5BUILD160 2004年3月 周军开发
内存补丁制作过程 XX于2004年8月10日

猛地一看,以为照镜子
2009-8-19 22:43
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
7
顺带说一句,很多时候内存/堆栈中看到的类注册码也许是黑名单比照
2009-8-19 22:48
0
雪    币: 20
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
破解绝对是独立完成 如果之前有看到同类的文章 我也不会发布了。。。谢谢指出问题。
2009-8-25 21:54
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
支持一下,多谢分享!
2009-8-25 23:32
0
雪    币: 50
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
学习中,感谢楼主分享,目前水平有限,对楼主的分析只是学习,无法提出意见
2009-8-26 10:54
0
游客
登录 | 注册 方可回帖
返回
//