首页
社区
课程
招聘
[旧帖] [原创]一个入门级的CrackMe分析(适合新手)业余版 与高手Petnt文参考阅读 0.00雪花
发表于: 2008-1-29 23:22 3934

[旧帖] [原创]一个入门级的CrackMe分析(适合新手)业余版 与高手Petnt文参考阅读 0.00雪花

2008-1-29 23:22
3934
【文章标题】: 一个入门级的CrackMe分析(适合新手)业余版
【文章作者】: NBA2005
【作者QQ号】: 382309369
【软件名称】: Crack me之 zugo.exe
【软件大小】: 28KB
【下载地址】: http://bbs.pediy.com/showthread.php?t=58867
【加壳方式】: 无
【保护方式】: 无
【编写语言】: Microsoft Visual C++ 6.0
【使用工具】: Ollydbg
【操作平台】: WIN2000
【软件介绍】: 新兵论坛的毕业生练手用的
【作者声明】: 只是想借这个简单的CRACK ME介绍一下破解的基本思想、流程和初学破解的人要了解的细节。不到之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  天下黑客出我辈
  一入破解岁月催
  天下软件俱免费
  我等都要喝北风
  
     前些日子,我上网玩一个小游戏,却发现网站已经关闭。听说是亏损被迫倒闭的。一位软件编写者在网上对我痛骂:就是你们的存在,弄的软件业发展艰难。我无语,因为这网站的许多FLASH我确实破解过。但我恪守破解的操守:破解但不传播,不一赢利为目的。有感一首小小打油诗,与同道共勉。做为第一课,我认为首先要学会尊重软件作者付出的辛勤的劳动。
  
     MM求破解。好为难啊。刚刚正义凛然地说了一通大道理,却知法犯法。这在法律上要罪加一等的。临机一动,我教你破解吧,很简单的。首先,把MM喜欢听的电脑音乐暂停,然后打开OD。讲了一通F7和F8的区别,然后亲自示范。我按、按、按...怪了,F7和F8没反应。狠狠心,按F9,呼,一下就到结束了。我的汗哗哗地流啊,恰似一江春水向东流。丢不起这个人啊。赶快检查电脑键盘,好的,与网上佳丽三千聊得是浓情蜜意。回到OLLYDBG,F7和F8还是毫无反应。F7和F8啊,你快动起来啊,兄弟我求你了。等等,F7和F8...MM喜欢听的电脑音乐播放器里好象也有快捷键F7和F8。快速关掉音乐播放器。好了,不流汗的感觉就一个字:爽。破解第二课:注意破解的环境。尽量关掉不必要的应用软件,特别是支持F1-F12功能的软件。许多破解的朋友喜欢听音乐或看小电影,边破解。我就经常在破解过程中碰到这类的小麻烦。有一个英汉小词典居然还支持F4功能,让我脱壳真麻烦、真麻烦。高手常常嘴上一句:根据经验。这就是经验。
  
     破解要有效率,必须要踩点。知己知彼,百战不怠。我的踩点一是要了解有无壳和编程语言,二要了解编程者安全上的缺陷。踩点的目的是寻找一个理想的程序切入点。最庸俗的方法就是试运行要破解的程序。双击zugo.exe,是最常见的注册对话框。试着输入三类信息:英文字母、数字和汉字。我的习惯是输入三个字符。Serials提示:masukkan at least 5 huruf。什么鸟语言?不知道,但我是聪明的富而莫死(你也猜得懂我说的是啥意思吧)。我一输入用户名,它就出来,at least 5还认得。最少五个,可能是最少五个字符?猜的对不对呢?把masukkan at least 5 huruf消去,试验输入六个字符123456。哈哈,我是聪明的富而莫死(你也猜得懂我说的是啥意思吧)。masukkan at least 5 huruf不出现了。出了另一个对话框,又是一串天书般提示,就认识BAD boy!猜是坏消息,在破解中估计是注册失败之类的意思。高手常常嘴上一句:根据经验。这就是经验。啥经验?破解的精华。啥破解高手,说白了就是靠猜。根据种种可疑的提示和线索来猜。学破解的最高境界就是学程序的编程核心思想,然后反过来猜作者的编程思路。光猜还不够,还要多次一步步地实验,来验证自己的猜想,这是一个艰辛的过程。破解第三课,也是破解的精华:猜+试验。一般人我不告诉他。菜鸟的问题:从程序开头一步步按F8能不能破解?能。我乘飞机到意大利能不能?走路到罗马行不行?
  
     好,踩点有了结果:
     1.用户名字符类型:中英文不限,数字可以。
     2.用户名字符条件:at least 5。
     3.用户名对错的提示:猜是Bad boy!的对话框。以后就要试验去证实我们的猜想对OR错。
  
     破解正式开始。OD打开zugo.exe,停在这:
  
  00401283 >/$  55            push    ebp
  00401284  |.  8BEC          mov     ebp, esp
  00401286  |.  6A FF         push    -1
  00401288  |.  68 C0404000   push    004040C0
  0040128D  |.  68 6C1E4000   push    00401E6C      ;  SE 处理程序安装
  00401292  |.  64:A1 0000000>mov     eax, dword ptr fs:[0]
  
     Bad boy!是字符串,先试试字符串查找。这是破解前辈的法宝,打遍魔教无敌手。菜鸟的问题:好象我们是魔教?呸呸呸,我们是圣教,记住了。鼠标右键于汇编代码处,点查找。这有两种选择:OD自带的所有参考文本字串和字符插件FIND   ASCII。一查找,有Bad Boy、Good Boy、at least 5和messageboxa。我认识的和猜想重要的就这些。为什么?猜的。分别点三处信息,选反汇编窗口中跟随,分别看到:
  第一处:
  004010FB  |.  >push    00405098                         ;  ASCII "Good Boy!"
  00401100  |.  >push    0040507C                         ;  ASCII "Terima kasih kerana mencuba"
  
  .........
  第二处:
  00401107  |> \>push    00405070                         ;  ASCII "Bad Boy!"
  0040110C  |.  >push    0040504C                         ;  ASCII "Tidak tepat, sila cuba sekali lagi"
  
  .........
  第三处:
  00401114  |.  >call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
     “等等,”菜鸟来劲了。
  “我来到第一处:
  004010FB  |.  >push    00405098                         ;  ASCII "Good Boy!"
  00401100  |.  >push    0040507C                         ;  ASCII "Terima kasih kerana mencuba"”
  不会是再查找一遍字符串吧?再开始第二处吧?
  
  当然不是。许多新手看着高手们的破文就是做不下去,其中最主要的原因就是对OD的使用上不熟练,对一些细节的问题不会处理。这总被高手以一句根据经验蒙过去了。啥经验,不就多吃了两年盐嘛。可笑的是许多破解高手也是老实地反复查找字符串。呵呵,又一位走路到罗马。
      解决的方案很简单。查找的字符串窗口不要关掉。菜鸟:“我选反汇编窗口中跟随,怎么关。别蒙我了。”我是说你需要反复使用的窗口不要关掉,比如内存窗口、堆栈窗口或函数窗口等等。选窗口(W)的最下面,就是窗口集合,需要看哪个窗口就点哪个。点文本字符串参考位于...,回到可爱的字符串窗口,继续。
  
      破解第四课:细节决定成败。适用范围:菜鸟家族。当然不是我圣教了。
  
  004010DC  |.  >|mov     dword ptr [ebp+C], ecx
  004010DF  |.  >|cmp     eax, ebx
  004010E1  |.^ >\jl      short 004010CC
  004010E3  |>  >push    dword ptr [ebp+14]
  004010E6  |.  >call    00401278
  004010EB  |.  >pop     ecx
  004010EC  |.  >mov     ecx, dword ptr [ebp+C]
  004010EF  |.  >push    0
  004010F1  |.  >xor     ecx, 0A9F9FA
  004010F7  |.  >cmp     ecx, eax
  004010F9  |.  >jnz     short 00401107
  004010FB  |.  >push    00405098                         ;  ASCII "Good Boy!"
  00401100  |.  >push    0040507C                         ;  ASCII "Terima kasih kerana mencuba"
  00401105  |.  >jmp     short 00401111
  00401107  |>  >push    00405070                         ;  ASCII "Bad Boy!"
  0040110C  |.  >push    0040504C                         ;  ASCII "Tidak tepat, sila cuba sekali lagi"
  00401111  |>  >push    dword ptr [ebp+8]                ; |hOwner
  00401114  |.  >call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
  
     OK,虽然很简单,但也不容易。然后我们到了破解的关键环节:程序流程。看了上面的程序汇编代码,你需要在程序流程的基本知识的基础上有目的地猜。不然你就走路去罗马吧。破解的关键环节:程序流程,是破解的最最基本的知识。如果你不懂,那你就撒泡尿照照你自己吧,该干啥干啥。可以说,程序流程的研判贯穿了我们破解的始终。我们可以不懂函数的种种返回值,可以不懂啥SEH异常,但不能不懂程序流程。我猜程序流程如下:
  004010E3  |>  >push    dword ptr [ebp+14]    用户名赋值
  004010E6  |.  >call    00401278              对用户名处理
  ......................
  004010F7  |.  >cmp     ecx, eax              比较这两值。
  004010F9  |.  >jnz     short 00401107        程序流程两分支:对和错
  对:
  004010FB  |.  >push    00405098                         ;  ASCII "Good Boy!"
  00401100  |.  >push    0040507C                         ;  ASCII "Terima kasih kerana mencuba"
  00401105  |.  >jmp     short 00401111        返回程序主干
  错:
  00401107  |>  >push    00405070                         ;  ASCII "Bad Boy!"
  0040110C  |.  >push    0040504C                         ;  ASCII "Tidak tepat, sila cuba sekali lagi"
  00401111  |>  >push    dword ptr [ebp+8]                ; |hOwner
  00401114  |.  >call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
   \MessageBoxA猜是信息框。
      我们来验证。点004010E3  |>  >push    dword ptr [ebp+14] ,按F2设断点。运行F9,出现对话框,输入
  NAMA:  abcde
   SERIALS:123456
      破解老手都知道:输入连续的信息。这又是一个破解的细节。细节决定成败和效率。这样做的好处是:在猜算法时,比较直观和容易理解。用户名和序列号的位数尽量不要一样,这又是一个破解的细节。理由:有些程序的算法会拿用户名和序列号的位数反复做文章,降低猜的难度。韩国的魔兽为什么那么拽?NBA的篮球为什么那么漂亮?细节。这些细节都在破解高手的一句经验里。
    我们继续。点OK。停在断处,看信息窗口:
  堆栈 ss:[0012FBE4]=001367A0, (ASCII "123456")
   跳转来自 004010CA
     
      这验证了我们对004010E3  |>  >push    dword ptr [ebp+14]的猜想,就是用户名赋值。
      004010F9  |.  >jnz     short 00401107        程序流程两分支:对和错   
      这一句怎么验证?双击,改为
      004010F9  |.  >jz     short 00401107  
      即jnz >jz   
      运行F9,出现GOOD  BOY!
  
      重新调试,CTRL+F2,程序自动改回004010F9  |.  >jnz
         出现错误提示:BAD BOY!
      我们的猜想又得到了验证。我是聪明的富而莫死(你也猜得懂我说的是啥意思吧)。
      
  
      菜鸟又来了,“还有一句没交代呢”:
      004010E6  |.  >call    00401278              对用户名处理
      别急,慢慢来。让我喝口茶,列位看官给个掌声。哗哗哗哗哗哗哗,好热烈!
      
      重新调试,CTRL+F2。菜鸟:又重新来啊? 破解第五课:耐心是破解的利器。
      F7进入call    00401278  
      
  
  00401278  /$  >push    dword ptr [esp+4]
  0040127C  |.  >call    004011ED                F8粗过,再猜它的作用。以后需要还要进入细跟。
  00401281  |.  >pop     ecx
  00401282  \.  >retn    这一句时,寄存器窗口出现:ECX  001367A0 ASCII “123456”
  猜是ECX=123456
      
      回到程序主干。F7到004010F7  |.  >cmp     ecx, eax
      其中ECX的值由下算出:004010F1  |.  >xor     ecx, 0A9F9FA
      根据汇编知识猜:0A9F9FA取或值=ECX。但EAX的值呢?看来我们对下句的理解猜错了。
  004010E3  |>  >push    dword ptr [ebp+14]    用户名赋值
  004010E6  |.  >call    00401278              对用户名处理
      对CALL的判断和跟踪、反复试验,贯穿了具体破解过程的始终。这个CALL似乎不是我们要找的关键CALL。只好再向上看:
  
  004010A7  |.  >mov     esi, dword ptr [<&USER32.GetDlgI>; |USER32.GetDlgItemTextA
  004010AD  |.  >push    dword ptr [ebp+10]               ; |Buffer
  004010B0  |.  >push    3E8                              ; |ControlID = 3E8 (1000.)
  004010B5  |.  >push    dword ptr [ebp+8]                ; |hWnd
  004010B8  |.  >call    esi                              ; \GetDlgItemTextA
  004010BA  |.  >push    dword ptr [ebp-4]                ; /Count
  004010BD  |.  >push    dword ptr [ebp+14]               ; |Buffer
  004010C0  |.  >push    edi                              ; |ControlID => 3EA (1002.)
  004010C1  |.  >push    dword ptr [ebp+8]                ; |hWnd
  004010C4  |.  >call    esi                              ; \GetDlgItemTextA
  004010C6  |.  >xor     eax, eax
  004010C8  |.  >test    ebx, ebx
  004010CA  |.  >jle     short 004010E3
  004010CC  |>  >/mov     ecx, dword ptr [ebp+10]
  004010CF  |.  >|mov     edx, dword ptr [ebp+C]
  004010D2  |.  >|add     edx, ebx
  004010D4  |.  >|movsx   ecx, byte ptr [eax+ecx]
  004010D8  |.  >|imul    ecx, edx
  004010DB  |.  >|inc     eax
  004010DC  |.  >|mov     dword ptr [ebp+C], ecx
  004010DF  |.  >|cmp     eax, ebx
  004010E1  |.^ >\jl      short 004010CC
  004010E3  |>  >push    dword ptr [ebp+14]
  004010E6  |.  >call    00401278                 不是关键CALL,排除。
  004010EB  |.  >pop     ecx
  004010EC  |.  >mov     ecx, dword ptr [ebp+C]
  004010EF  |.  >push    0
  004010F1  |.  >xor     ecx, 0A9F9FA
  004010F7  |.  >cmp     ecx, eax
  004010F9      >jnz     short 00401107
  004010FB  |.  >push    00405098                         ;  ASCII "Good Boy!"
  00401100  |.  >push    0040507C                         ;  ASCII "Terima kasih kerana mencuba"
  00401105  |.  >jmp     short 00401111
  00401107  |>  >push    00405070                         ;  ASCII "Bad Boy!"
  0040110C  |.  >push    0040504C                         ;  ASCII "Tidak tepat, sila cuba sekali lagi"
  00401111  |>  >push    dword ptr [ebp+8]                ; |hOwner
  00401114  |.  >call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
  
      没有发现可疑的关键CALL,
  004010A7  |.  >mov     esi, dword ptr [<&USER32.GetDlgI>; |USER32.GetDlgItemTextA
  004010AD  |.  >push    dword ptr [ebp+10]               ; |Buffer
  004010B0  |.  >push    3E8                              ; |ControlID = 3E8 (1000.)
  004010B5  |.  >push    dword ptr [ebp+8]                ; |hWnd
  004010B8  |.  >call    esi                              ; \GetDlgItemTextA
  004010BA  |.  >push    dword ptr [ebp-4]                ; /Count
  004010BD  |.  >push    dword ptr [ebp+14]               ; |Buffer
  004010C0  |.  >push    edi                              ; |ControlID => 3EA (1002.)
  004010C1  |.  >push    dword ptr [ebp+8]                ; |hWnd
  004010C4  |.  >call    esi                              ; \GetDlgItemTextA
  以上猜是出现我们输入用户名和序列的窗口,断在004010A7  重新运行验证。
  004010C8  |.  >test    ebx, ebx
  004010CA  |.  >jle     short 004010E3
  小于=at least,又是在输入用户名和序列的窗口后,你猜呢?
  对了,EBX是用户名的位数,设断此处,输入用户名不同长度验证。
  
     了不起,我们不懂什么编程,但光靠猜和耐心,反复地试验和验证,推理并证实了几乎所有语句的含义。问题来了,关键的CALL在哪呢?根据消息的顺序和程序的常见流程,用户名的位数的判断优先于用户名的处理。
  
     004010E6  |.  >call    00401278                 不是关键CALL,排除。
     这个结论是错误的,我们走了弯路。但更坚定了关键CALL的位置。仔细回忆,啊,被帅哥遗忘的CALL:
  
  00401278  /$  >push    dword ptr [esp+4]
   0040127C  |.  >call    004011ED                F8粗过,再猜它的作用。以后需要还要进入细跟。
  00401281  |.  >pop     ecx
   00401282  \.  >retn    这一句时,寄存器窗口出现:ECX  001367A0 ASCII “123456”
  猜是ECX=123456
  
    0040127C  |.  >call    004011ED               关键CALL里的关键CALL
  
    关键CALL里的关键CALL是破解的家常便饭,考验的是我们的耐心。破解老手根据经验,坚信我们一开始CALL就是关键的判
  断,跟到这,粗过一遍,就能断定这就是关键的CALL。因为到00401281  |.  >pop     ecx;  001367C0时,堆栈窗口出现
  了两个123456,我们很容易猜到这个CALL对123456做过处理,然后pop     ecx。这符合一般编程的逻辑。
  
    重新调试,CTRA+F2,停在:
  0040127C  |.  >call    004011ED               关键CALL里的关键CALL
    F7进入CALL。先不运行,向下看一遍程序,老手很容易猜出了大致的程序流程,在几个可疑处做上标签,方便以后逐步地
  验证。新手就先走步到罗马吧。以后赚了美金再做飞机。高手Petnt已经给出算法了,我就不献丑了。读者可自行验证,走步
  去意大利。等等,我的程序运行到哪了?按“*”就知道了。
  
    菜尿来了,“你还没教怎么暴力破解呢!”菜尿就是尿多,哪这么多问题。破解第六课:笑对高手骂。打是疼,骂是恨铁不成钢。高手的耐心都用在破解里了。我的耐心也就只此一回,谢绝FAQ。

    爆破的方法就是程序改向,根据程序流程分两种情况:
    程序流程一:
    判断对----》分支
    判断错
    程序继续
    ......
    爆破方法:
    将判断改JMP。这又有一个细节,为什么不改向呢?
    JZ--》JNZ或JNZ--JZ呢?
    与JMP有什么区别呢?这个问题留给你。
  
    程序流程二:
    判断错----》分支
    判断对
    程序继续
    ......
    爆破方法:将判断或关键CALL  NOP掉。别再问了,再问我尿你。
  
  
    脱壳碰壁
    爬格好累
    好心菜鸟
    给点安慰
  
    啥安慰?猜
    啥安慰?你自己不会试试吗
    啥安慰?耐心地试试
    啥安慰?细节,看我两手的动作
    啥安慰?你找骂呀?
   
    对了,笑对高手骂。
    对对,鼓掌................................................................................
  
  
  
    我是谁?我是聪明的富而莫死(你也猜得懂我说的是啥意思吧)。记住了,我是NBA2005!牛皮不是猜的!
  
  天下黑客出我辈
  一入破解岁月催
  天下软件俱免费
  我等都要喝北风
  
  歌声中,NBA2005乘雕飞去!
   
  
  
--------------------------------------------------------------------------------
【经验总结】
  
  天下黑客出我辈
  一入破解岁月催
  天下软件俱免费
  我等都要喝北风
  
  做为第一课,我认为首先要学会尊重软件作者付出的辛勤的劳动。
  破解第二课:注意破解的环境。尽量关掉不必要的应用软件,特别是支持F1-F12功能的软件。
  破解第三课,也是破解的精华:猜+试验。
  
  破解的精华。啥破解高手,说白了就是靠猜。
  根据种种可疑的提示和线索来猜。学破解的最高境界就是学程序的编程核心思想,然后反过来猜作者
  的编程思路。
  光猜还不够,还要多次一步步地实验,来验证自己的猜想,这是一个艰辛的过程。
  
  踩点一是要了解有无壳和编程语言。
  二要了解编程者安全上的缺陷。
  踩点的目的是寻找一个理想的程序切入点。最庸俗的方法就是试运行要破解的程序。
  
  最庸俗的方法就是试运行要破解的程序。
  试试字符串查找。这是破解前辈的法宝,打遍魔教无敌手。
  
  多个窗口的切换:
  选窗口(W)的最下面,就是窗口集合,需要看哪个窗口
  就点哪个。
  
  破解第四课:细节决定成败。适用范围:菜鸟家族。
  破解老手都知道:输入连续的信息。这又是一个破解的细节。细节决定成败和效率。细节都在破解高手的一句经验里。
  破解第五课:耐心是破解的利器。
  对CALL的判断和跟踪、反复试验,贯穿了具体破解过程的始终。
  我们不懂什么编程,但光靠猜和耐心,反复地试验和验证,推理并证实了几乎所有语句的含义。
  关键CALL里的关键CALL是破解的家常便饭,考验的是我们的耐心。破解老手根据经验粗过一遍,就能断定关键的CALL。
  按“*”的含义。
  
  跟踪关键CALL时,注意寄存器和堆栈窗口的变化有助于帮助我们猜得有理有据。

  爆破的方法就是程序改向,根据程序流程分两种情况:将判断或关键CALL改JMP或NOP掉。
  
  
  天下黑客出我辈
  一入破解岁月催
  天下软件俱免费
  我等都要喝北风
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于NBA2005, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2008年01月29日 下午 10:49:09

[课程]Android-CTF解题方法汇总!

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 423
活跃值: (11)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
2
欲与CCDEBUGer一比高!
呵呵,牛皮嘛,谁不会吹啊!

CCDEBUGer是谁?
OllyDB入门教程.chm的作者。
严重鄙视剽窃别人作品的人
2008-1-29 23:29
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
来学习学习。。。。。。。。
2008-1-30 00:07
0
雪    币: 164
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
哈哈,有意思,我看的可是很仔细哦!
2008-1-31 10:03
0
游客
登录 | 注册 方可回帖
返回
//