阳光网驿-企业信息化交流平台【DTC零售连锁全渠道解决方案】

 找回密码
 注册

QQ登录

只需一步,快速开始

扫描二维码登录本站

手机号码,快捷登录

手机号码,快捷登录

老司机
查看: 2431|回复: 6

[转帖] 菜鸟学算法<二>

[复制链接]
  • TA的每日心情

    2021-1-19 10:45
  • 签到天数: 172 天

    [LV.7]常住居民III

    发表于 2008-5-22 17:19:50 | 显示全部楼层 |阅读模式
    菜鸟学算法<二>注册流程篇声明:
    1.以下内容都是个人在学习中的一些心得体会,写给新手的,高手飘过
    2.文章难免有疏漏之处,欢迎各位兄弟批评指正
    3.本文原创于UnPacKcN,如转载,请保持文章完整性


    有了第一篇的基础知识学习
    下面我们以AuRRa公司的龙头产品Media-WorkShop为实例来进行第二篇


    学习目标
    1.培养良好的"破解书写习惯"
    2.学会判断程序段代码的功能
    3.学会逆向分析和爆破


    一、培养良好的破解习惯

    1.在指令右侧注释栏填写必要的跟踪注释
    应该着重注释的内容
    (1).寄存器的值(数值/字符串)

    (2).运算表达式
    便于完成将来对算法的总结

    (3).CALL功能
    确定哪些CALL是关键CALL,哪些是无大意义的CALL
    比如:
    A.经过一个CALL后,字符串中的小写字母全部变为大写字母
    这样的CALL,显然没有必要跟进去
    B.又如
    CALL XXXXXXXX
    TEST EAX,EAX
    JE   xxxxxxxx  //跳向注册成功

    这样的CALL一般来说是关键CALL(算法CALL)
    很有必要跟进去探个究竟

    (4).代码段的功能
    确定代码段的功能,以便从全局的角度对整个注册流程进行分析


    2.调试过程中,不同阶段,观察侧重点不同

    A.首次调试
    通常需要着重观察反汇编窗口和信息提示窗口

    B.区段集中调试时期
    应多注意寄存器和堆栈窗口

    C.某条特殊指令
    集中跟随数据窗口


    3.一气呵成,又不拘泥
    所谓一气呵成,就是指已经有了思路,那么就要一鼓作气,将其进行到底
    不然,开工一半,中途搁置
    过几天再拿起来...晕,又得从头分析

    不拘泥
    不是每个软件都是软柿子,不是每个软件设计者都不懂得ANTI-DBG
    要知道,现在的程序员的软件保护意识越来越强的!!

    暂时没有思路就先放一放,说生活中的某个细节会突然触发你的灵感

    如果只是为了破解而破解,那么建议你放弃CRACKER这条路
    学习破解只是一种很好的学习别人程序设计思路的方式
    并在学习过程中体会到自身提高的乐趣



    二、过程分析笔记

    !!!阅读建议:
    由于本篇是完全面向新手的文章,读者可以先下载注释笔记,然后浏览下
    然后边调试边看以下分析内容,效果会更好
    切记:一定要自己亲手调试

    在本例中
    我们用提示字符串进行注册代码段的定位
    提示信息:"invalid username or registration code"

    向上看代码,一般是在程序段的段首下断点

    关于"段首"的概念
    可以这样理解:在向上代码段中出现第一个retn的下方
    一般是push esp,push -1,push A,B格式的


    本例中,我们在地址0045BDB0处F2下断

    流程大致应该是这样的:
    1.运行程序,输入试练码,程序被断下

    2.进行首次跟踪
      主要完成些重要数据的记录(旁白注释)

    3.将程序细分段,确定各个分段的作用

    4.进行细跟踪
     搞定算法


    实例讲解:

    输入试练码:
    ID:luying10
    SN:9876543210abcdef

    点击确定,程序被OD断下

    注意观察代码窗口、信息提示窗口、(寄存器窗口只要注意字符串类型数据就好)

    并随时记录有用信息

    ;====================================================================|
    0045BDB0   .  6A FF         push    -1                               ;  //断在这
    0045BDB2   .  68 983A4700   push    00473A98                         ;  
    0045BDB7   .  64:A1 0000000>mov     eax, dword ptr fs:[0]
    0045BDBD   .  50            push    eax
    0045BDBE   .  64:8925 00000>mov     dword ptr fs:[0], esp
    0045BDC5   .  51            push    ecx
    0045BDC6   .  53            push    ebx
    0045BDC7   .  56            push    esi
    0045BDC8   .  8BF1          mov     esi, ecx
    0045BDCA   .  57            push    edi
    0045BDCB   .  8D4C24 0C     lea     ecx, dword ptr [esp+C]
    0045BDCF   .  E8 D4BE0000   call    <jmp.&MFC42.#540>
    0045BDD4   .  6A 01         push    1
    0045BDD6   .  8BCE          mov     ecx, esi
    0045BDD8   .  C74424 1C 000>mov     dword ptr [esp+1C], 0
    0045BDE0   .  E8 43C30000   call    <jmp.&MFC42.#6334>
    0045BDE5   .  E8 6CC20000   call    <jmp.&MFC42.#1168>
    0045BDEA   .  8B48 04       mov     ecx, dword ptr [eax+4]
    0045BDED   .  E8 78C30000   call    <jmp.&MFC42.#1669>
    ;
    0045BDF2   .  68 E8030000   push    3E8                              ; /Timeout = 1000. ms
    0045BDF7   .  FF15 3C524700 call    dword ptr [<&KERNEL32.Sleep>]    ; \Sleep
    0045BDFD   .  E8 54C20000   call    <jmp.&MFC42.#1168>
    0045BE02   .  8B48 04       mov     ecx, dword ptr [eax+4]
    在经过地址0045BDF7的CALL时候,程序停顿了一小会儿
    我们看英文注释也大概猜到这段代码的作用了----加入延时验证,防止暴力攻击
    ;--------------------------------------------------------------------|

    0045BE05   .  E8 5AC30000   call    <jmp.&MFC42.#2652>               ;  
    0045BE0A   .  8B46 64       mov     eax, dword ptr [esi+64]          ;  
    0045BE0D   .  8B4E 60       mov     ecx, dword ptr [esi+60]          ;
    程序运行到0045BE0A这行时候
    信息提示窗口提示dword ptr [esi+64] = "9876543210abcdef"
    [esi+64]中保存的是序列号
    这不正是我们最开始天的序列号嘛
    运行本行代码后,发现EAX变成了序列号
    同样,运行0045BE0D这行,ECX被赋予了用户名
    ;--------------------------------------------------------------------|
    0045BE10   .  8D5E 64       lea     ebx, dword ptr [esi+64]          ;  
    0045BE13   .  8D7E 60       lea     edi, dword ptr [esi+60]          ;  
    这两行只有值,没有所谓的字符串的东东
    我们学过LEA是装载有效地址的指令
    [esi+64]中保存的是序列号
    那么,执行完lea     ebx, dword ptr [esi+64]后,EBX中保存的就应该是序列号的地址
    同样,EDI中保存用户名的地址
    ;--------------------------------------------------------------------|
    0045BE16   .  50            push    eax                              ;  序列号压栈
    0045BE17   .  51            push    ecx                              ;  用户名压栈
    压栈操作,不用多解释,下面是一个CALL,我们首次跟踪,先F8过
    ;---------------------------------------------------------------------
    0045BE18   .  E8 83430000   call    004601A0                         ;  
    0045BE1D   .  83C4 08       add     esp, 8
    0045BE20   .  85C0          test    eax, eax
    0045BE22   .  75 1F         jnz     short 0045BE43                   ;  
    运行了0045BE18这行的CALL后,EAX变为0
    继续F8,来到跳转,跳转指向是绿色,跳转未实现
    下面英文提示invalid username or registration code
    显然再继续下去是提示注册失败咯
    ;--------------------------------------------------------------------|
    0045BE24   .  6A 40         push    40
    0045BE26   .  68 9C7C4900   push    00497C9C                         ;  sorry
    0045BE2B   .  68 707C4900   push    00497C70                         ;  invalid username or registration code      sorry
    0045BE30   .  8BCE          mov     ecx, esi
    0045BE32   .  E8 EDC30000   call    <jmp.&MFC42.#4224>               ;  
    提示注册失败,点击确定按钮,继续F8
    ;--------------------------------------------------------------------|
    0045BE37   .  C705 082C4E00>mov     dword ptr [4E2C08], 0            ;  
    0045BE41   .  EB 76         jmp     short 0045BEB9                   ;  //跳走
    程序跳走

    ;跳到这里来
    0045BEB9   >  8BCE          mov     ecx, esi                         ;  ->来到这
    0045BEBB   .  E8 74C20000   call    <jmp.&MFC42.#4853>
    0045BEC0   .  8D4C24 0C     lea     ecx, dword ptr [esp+C]
    0045BEC4   .  C74424 18 FFF>mov     dword ptr [esp+18], -1
    0045BECC   .  E8 8FBD0000   call    <jmp.&MFC42.#800>
    0045BED1   .  8B4C24 10     mov     ecx, dword ptr [esp+10]
    0045BED5   .  5F            pop     edi
    0045BED6   .  5E            pop     esi
    0045BED7   .  5B            pop     ebx
    0045BED8   .  64:890D 00000>mov     dword ptr fs:[0], ecx
    0045BEDF   .  83C4 10       add     esp, 10
    0045BEE2   .  C3            retn                                     ;  //结束
    ;====================================================================|

    首轮跟踪结束,总结下:

    1.关键跳转0045BE22

    2.关键CALL->004601A0

    3.标志位EAX
      EAX = 0 注册失败
      EAX = 1  注册成功

    4.可疑处,地址:0045BE7   mov dword ptr [4E2C08], 0
    楼主热帖
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情

    2021-1-19 10:45
  • 签到天数: 172 天

    [LV.7]常住居民III

     楼主| 发表于 2008-5-22 17:20:38 | 显示全部楼层
    两个研究方向
    1.关键CALL->004601A0
    2.可疑的赋值


    首先研究关键CALL

    ;====================================================================|
    ;在地址0045BE18处跟进关键CALL->004601A0
    ;--------------------------------------------------------------------|
    004601A0  /$  53            push    ebx                              ;
    OD下方显示:本地调用来自 00428B46, 00429225, 0044BB64, 0045120C, 00455368, 0045BE18, 0045E824  
    004601A1  |.  55            push    ebp
    注意:从这里我们可疑看到,程序有多处代码调用了CALL=>004601A0
    这也验证了为了程序只修改0014BE22处的关键跳转不能达到完全爆破的目的
    ;--------------------------------------------------------------------|
    004601A2  |.  8B6C24 0C     mov     ebp, dword ptr [esp+C]           ;  
    EBP = [esp+C] = 用户名

    004601A6  |.  56            push    esi
    004601A7  |.  57            push    edi
    004601A8  |.  BE 84014A00   mov     esi, 004A0184                    ;  ESI = 4A0184
    004601AD  |.  8BC5          mov     eax, ebp                         ;  EAX = 用户名
    004601AF  |>  8A10          /mov     dl, byte ptr [eax]              ;  用户名的第1个字符
    004601B1  |.  8A1E          |mov     bl, byte ptr [esi]
    004601B3  |.  8ACA          |mov     cl, dl
    004601B5  |.  3AD3          |cmp     dl, bl
    004601B7  |.  75 1E         |jnz     short 004601D7                  ;  
    跳转实现//跳出循环体(跳至EAX置零)
    ;----------------------------
    004601B9  |.  84C9          |test    cl, cl
    004601BB  |.  74 16         |je      short 004601D3                  ;  
    004601BD  |.  8A50 01       |mov     dl, byte ptr [eax+1]
    004601C0  |.  8A5E 01       |mov     bl, byte ptr [esi+1]
    004601C3  |.  8ACA          |mov     cl, dl
    004601C5  |.  3AD3          |cmp     dl, bl
    004601C7  |.  75 0E         |jnz     short 004601D7
    004601C9  |.  83C0 02       |add     eax, 2
    004601CC  |.  83C6 02       |add     esi, 2
    004601CF  |.  84C9          |test    cl, cl
    004601D1  |.^ 75 DC         \jnz     short 004601AF                  ;  //循环

    004601D3  |>  33C0          xor     eax, eax                         ;  
    004601D5  |.  EB 05         jmp     short 004601DC                   ;
    程序跳出了循环体,条件是用户名不为空

    我们可以看看如果程序从004601D5这跳会怎样
    首先跳至004601DC
    因为EAX = 0,所以又跳至00460242
    接着EAX置零后返回
    而我们的主程序在EAX=0的时候是注册失败的

    ;----------------------------
    004601D7  |>  1BC0          sbb     eax, eax                         ;  
    004601D9  |.  83D8 FF       sbb     eax, -1                          ;  
    004601DC  |>  85C0          test    eax, eax
    004601DE  |.  74 62         je      short 00460242                   ;

    EAX=1,跳转未实现

    综上,我们可疑得出,上段代码是检查用户名是否为空
    ;--------------------------------------------------------------------|

    004601E0  |.  8B7C24 18     mov     edi, dword ptr [esp+18]          ;
    EDI = [esp+18] = 序列号
    004601E4  |.  BE 84014A00   mov     esi, 004A0184                    ;  ESI = 4A0184
    004601E9  |.  8BC7          mov     eax, edi                         ;
    004601EB  |>  8A10          /mov     dl, byte ptr [eax]              ;  序列号的第i个字符
    004601ED  |.  8A1E          |mov     bl, byte ptr [esi]
    004601EF  |.  8ACA          |mov     cl, dl
    004601F1  |.  3AD3          |cmp     dl, bl
    004601F3  |.  75 1E         |jnz     short 00460213                  ;  
    跳转实现//跳出循环体(跳至EAX置零)
    004601F5  |.  84C9          |test    cl, cl
    004601F7  |.  74 16         |je      short 0046020F                  ;
    004601F9  |.  8A50 01       |mov     dl, byte ptr [eax+1]
    004601FC  |.  8A5E 01       |mov     bl, byte ptr [esi+1]
    004601FF  |.  8ACA          |mov     cl, dl
    00460201  |.  3AD3          |cmp     dl, bl
    00460203  |.  75 0E         |jnz     short 00460213
    00460205  |.  83C0 02       |add     eax, 2
    00460208  |.  83C6 02       |add     esi, 2
    0046020B  |.  84C9          |test    cl, cl
    0046020D  |.^ 75 DC         \jnz     short 004601EB                  ;  //循环

    0046020F  |>  33C0          xor     eax, eax                         ;
    00460211  |.  EB 05         jmp     short 00460218                   ;  
    程序跳出了循环体,条件是序列号不为空

    我们可以看看如果程序从00460211这跳会怎样
    首先跳至00460218
    因为EAX = 0,所以又跳至00460242
    接着EAX置零后返回
    而我们的主程序在EAX=0的时候是注册失败的
    00460213  |>  1BC0          sbb     eax, eax                         ;  
    00460215  |.  83D8 FF       sbb     eax, -1                          ;
    00460218  |>  85C0          test    eax, eax                         ;  
    0046021A  |.  74 26         je      short 00460242                   ;  

    EAX=1,跳转未实现
    综上,我们可疑得出,上段代码是检查序列号是否为空
    ;--------------------------------------------------------------------|
    0046021C  |.  57            push    edi                              ;  
    0046021D  |.  55            push    ebp                              ;  
    0046021E  |.  E8 6DF9FFFF   call    0045FB90                         ;  
    00460223  |.  83C4 08       add     esp, 8
    00460226  |.  85C0          test    eax, eax                         ;  
    00460228  |.  75 0E         jnz     short 00460238                   ;
      
    EDI保存序列号
    EBP保存用户名
    EAX = 0
    跳转未实现,继续

    有一个CALL->0045FB90 ,下次跟入


    假设跳转实现,程序跳至00460238
    EAX = 1,返回-》注册成功
    ;--------------------------------------------------------------------|
    0046022A  |.  57            push    edi                              ;  
    0046022B  |.  55            push    ebp                              ;
    0046022C  |.  E8 8FFBFFFF   call    0045FDC0                         ;
    00460231  |.  83C4 08       add     esp, 8
    00460234  |.  85C0          test    eax, eax                         ;  
    00460236  |.  74 0A         je      short 00460242                   ;

    EDI保存序列号
    EBP保存用户名
    EAX = 0
    跳转实现

    EAX = 0,返回,注册失败
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情

    2021-1-19 10:45
  • 签到天数: 172 天

    [LV.7]常住居民III

     楼主| 发表于 2008-5-22 17:21:47 | 显示全部楼层
    假设跳转未实现
    EAX = 1,返回,注册成功
    ;--------------------------------------------------------------------|
    00460238  |>  5F            pop     edi
    00460239  |.  5E            pop     esi
    0046023A  |.  5D            pop     ebp
    0046023B  |.  B8 01000000   mov     eax, 1                           ;  
    00460240  |.  5B            pop     ebx
    00460241  |.  C3            retn                                     ;
    标志位赋值:EAX = 1 //返回
    ;--------------------------------------------------------------------|
    00460242  |>  5F            pop     edi                              ;  
    跳转来自 004601DE, 0046021A, 00460236
    00460243  |.  5E            pop     esi
    00460244  |.  5D            pop     ebp
    00460245  |.  33C0          xor     eax, eax                         ;  
    00460247  |.  5B            pop     ebx
    00460248  \.  C3            retn                                     ;  
    EAX置零//返回
    ;====================================================================|


    跟进call    0045FB90 ,只有一处调用

    跟进call    0045FDC0  ,只有一处调用


    我们可以爆破了
    在第二层中想办法让EAX的返回值为1

    思路.
    1.修改关键跳转
    地址00460236处jnz改为jmp

    2.修改赋值语句
    地址00460245处xor eax,eax修改为inc eax(nop填充)



    哈哈,这么简单就搞定``````

    还有个可疑点呢,别忘了噢~~~

    我们在运行到0045BE20   .  85C0          test    eax, eax
    这行时候,修改下EAX的值,将其由0置为1
    使下面的跳转实现

    ;--------------------------------------------------------------------|
    0045BE43   >  8B07          mov     eax, dword ptr [edi]             ;  
    0045BE45   .  8D4C24 0C     lea     ecx, dword ptr [esp+C]
    0045BE49   .  50            push    eax                              ;  
    0045BE4A   .  68 547C4900   push    00497C54                         ;  license to:%s
    0045BE4F   .  51            push    ecx
    0045BE50   .  E8 07C20000   call    <jmp.&MFC42.#2818>
    0045BE55   .  8B5424 18     mov     edx, dword ptr [esp+18]          ;  
    提示窗口信息(ASCII "License To:luying10             ")
    ;---------------------------
    0045BE59   .  83C4 0C       add     esp, 0C
    0045BE5C   .  8BCE          mov     ecx, esi
    0045BE5E   .  6A 40         push    40
    0045BE60   .  68 487C4900   push    00497C48                         ;  thank you
    0045BE65   .  52            push    edx                              ;  
    提示窗口信息(ASCII "License To:luying10             ")
    0045BE66   .  E8 B9C30000   call    <jmp.&MFC42.#4224>               ;  

    提示注册成功
    ;---------------------------
    0045BE6B   .  57            push    edi
    0045BE6C   .  B9 04034A00   mov     ecx, 004A0304                    ;  ASCII "萷?"
    0045BE71   .  E8 3EBE0000   call    <jmp.&MFC42.#858>
    0045BE76   .  53            push    ebx
    0045BE77   .  B9 08034A00   mov     ecx, 004A0308                    ;  ASCII "乇?"
    0045BE7C   .  E8 33BE0000   call    <jmp.&MFC42.#858>
    0045BE81   .  C705 082C4E00>mov     dword ptr [4E2C08], 1            ;  
    这块很可疑噢~
    mov     dword ptr [4E2C08], 1
    ;---------------------------
    0045BE8B   .  8B3F          mov     edi, dword ptr [edi]             ;  
    0045BE8D   .  57            push    edi                              ;  
    0045BE8E   .  68 A0F24800   push    0048F2A0                         ;  username
    0045BE93   .  68 94F24800   push    0048F294                         ;  register
    0045BE98   .  B9 F4014A00   mov     ecx, 004A01F4
    0045BE9D   .  E8 5EC7FEFF   call    00448600                         ;
    EDI为用户名
    0045BEA2   .  8B1B          mov     ebx, dword ptr [ebx]             ;  
    0045BEA4   .  B9 F4014A00   mov     ecx, 004A01F4
    0045BEA9   .  53            push    ebx                              ;  
    0045BEAA   .  68 84F24800   push    0048F284                         ;  registercode
    0045BEAF   .  68 94F24800   push    0048F294                         ;  register
    0045BEB4   .  E8 47C7FEFF   call    00448600                         ;  
    EBX为序列号
    ;---------------------------
    0045BEB9   >  8BCE          mov     ecx, esi                         ;  
    0045BEBB   .  E8 74C20000   call    <jmp.&MFC42.#4853>
    0045BEC0   .  8D4C24 0C     lea     ecx, dword ptr [esp+C]
    0045BEC4   .  C74424 18 FFF>mov     dword ptr [esp+18], -1
    0045BECC   .  E8 8FBD0000   call    <jmp.&MFC42.#800>
    0045BED1   .  8B4C24 10     mov     ecx, dword ptr [esp+10]
    0045BED5   .  5F            pop     edi
    0045BED6   .  5E            pop     esi
    0045BED7   .  5B            pop     ebx
    0045BED8   .  64:890D 00000>mov     dword ptr fs:[0], ecx
    0045BEDF   .  83C4 10       add     esp, 10
    0045BEE2   .  C3            retn                                     ;  //结束

    ;====================================================================|


    注册失败mov     dword ptr [4E2C08], 0
    注册成功mov     dword ptr [4E2C08], 1

    分析,将注册失败后[4E2C08]也赋值为1
    但在整个程序中,有很多地方调用关键CALL
    并且两段是不相干的代码
    修改地址赋值不能改变关键CALL
    修改关键CALL后该地址赋值就相应随之发生变化

    结论:修改此处,不能达到完美爆破的目的
          只修改关键CALL就可以达到完美爆破的目的


    通过本文,主要是让兄弟们学会如何给程序加注释,和确定程序代码段的功能

    两点说明:
    1.恰当的书写注释
    注释不是越多越好,太多的注释反而影响程序的阅读
    用最少的文字表达概括语句含义

    2.注册流程分析的意义
    明确区段代码的作用,为以后定位注册关键代码段做铺垫,减少不必要的代码分析
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    郁闷
    2014-6-3 22:22
  • 签到天数: 21 天

    [LV.4]偶尔看看III

    发表于 2008-5-22 20:31:50 | 显示全部楼层
    哦,这个东东网上多得是啊,当然能收集并分享到这里也算是辛苦了!只是希望发更多的原版精品就好了!!!
    本帖子由阳光论坛管理组成员答复[增加管理津贴2个]

    打造出国内一流的行业软件应用交流论坛--阳光网驿助力企业信息化
    启用邀请码注册,提高发帖质量,建设交流社区

    该用户从未签到

    发表于 2008-6-24 14:07:40 | 显示全部楼层
    看了这么多,还是有点云里来雾里去的,本人实在太菜
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    擦汗
    2011-2-13 10:58
  • 签到天数: 18 天

    [LV.4]偶尔看看III

    发表于 2008-6-25 10:45:12 | 显示全部楼层
    关键在于自己要领悟!如何吸收性理解间接经验!
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情

    2015-4-1 17:28
  • 签到天数: 20 天

    [LV.4]偶尔看看III

    发表于 2008-7-8 16:39:25 | 显示全部楼层
    其实学破解是个漫长的过程,多谢提供资料了.
    启用邀请码注册,提高发帖质量,建设交流社区
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    快速回复 返回顶部 返回列表