首页
社区
课程
招聘
[原创]Adler32CrackMe破文
发表于: 2008-2-8 15:05 6534

[原创]Adler32CrackMe破文

2008-2-8 15:05
6534
【文章标题】: Adler32CrackMe破文
【文章作者】: dttom
【作者邮箱】: dttom2006@126.com
【下载地址】: http://bbs.pediy.com/attachment.php?attachmentid=6637&d=1183881215
【保护方式】: 无
【使用工具】: ollydbg,IDA,peid
【软件介绍】: adler32算法的crackme
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  春节在家休息没事,看了看windrand发布密码学系列crackme,看了一下只有crc32的破文,出于兴趣我也来试试adler32算法crackme的破解。首先在网
  上查了一下adler32算法,查到RFC1950文档有adler32算法,大概看了一下C代码,下面开始查看crackMe程序。
  peid 检查为delphi编译,ollydbg打开F9,输入用户名,注册码,bp GetDlgItemTextA 下断,下面见代码:
  .....
  0040886E   > \68 FF000000   push    0FF                              ; /Count = FF (255.); Case 3EA of switch 00408854
  00408873   .  68 AC924000   push    004092AC                         ; |Buffer = Adler32C.004092AC
  00408878   .  68 F2030000   push    3F2                              ; |ControlID = 3F2 (1010.)
  0040887D   .  8B45 08       mov     eax, dword ptr [ebp+8]           ; |
  00408880   .  50            push    eax                              ; |hWnd
  00408881   .  E8 B6BEFFFF   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA  下断后在这个函数里,即在系统函数领空
  00408886   .  8D45 B4       lea     eax, dword ptr [ebp-4C]          ;  Alt+F9来到这里
  00408889   .  BA AC924000   mov     edx, 004092AC                    ;  ASCII "dttom"
  0040888E   .  B9 FF000000   mov     ecx, 0FF
  00408893   .  E8 C0AFFFFF   call    00403858
  00408898   .  837D B4 00    cmp     dword ptr [ebp-4C], 0
  0040889C   .  75 1C         jnz     short 004088BA
  0040889E   .  6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  004088A0   .  68 DC8A4000   push    00408ADC                         ; |Title = ""D7,"",A2,"",B2,"崽崾?
  004088A5   .  68 E88A4000   push    00408AE8                         ; |Text = "用",BB,"?,B2,"",BB,"能为空请输入?,A1,""
  004088AA   .  8B45 08       mov     eax, dword ptr [ebp+8]           ; |
  004088AD   .  50            push    eax                              ; |hOwner
  004088AE   .  E8 C1BEFFFF   call    <jmp.&user32.MessageBoxA>        ; \MessageBoxA
  004088B3   .  33DB          xor     ebx, ebx
  004088B5   .  E9 A2010000   jmp     00408A5C
  004088BA   >  68 FF000000   push    0FF                              ; /Count = FF (255.)
  004088BF   .  68 AC934000   push    004093AC                         ; |Buffer = Adler32C.004093AC
  004088C4   .  68 F3030000   push    3F3                              ; |ControlID = 3F3 (1011.)
  004088C9   .  8B45 08       mov     eax, dword ptr [ebp+8]           ; |
  004088CC   .  50            push    eax                              ; |hWnd
  004088CD   .  E8 6ABEFFFF   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA
  004088D2   .  8D45 B0       lea     eax, dword ptr [ebp-50]
  004088D5   .  BA AC934000   mov     edx, 004093AC                    ;  ASCII "55556666"
  004088DA   .  B9 FF000000   mov     ecx, 0FF
  004088DF   .  E8 74AFFFFF   call    00403858                         ;  计算假注册码长度
  004088E4   .  837D B0 00    cmp     dword ptr [ebp-50], 0            ;  检测假注册码是否为空
  004088E8   .  75 1C         jnz     short 00408906
  004088EA   .  6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  004088EC   .  68 DC8A4000   push    00408ADC                         ; |Title = ""D7,"",A2,"",B2,"崽崾?
  004088F1   .  68 008B4000   push    00408B00                         ; |Text = ""D7,"",A2,"",B2,"崧?,B2,"",BB,"能为空请输入?,A1,""
  004088F6   .  8B45 08       mov     eax, dword ptr [ebp+8]           ; |
  004088F9   .  50            push    eax                              ; |hOwner
  004088FA   .  E8 75BEFFFF   call    <jmp.&user32.MessageBoxA>        ; \MessageBoxA
  004088FF   .  33DB          xor     ebx, ebx
  00408901   .  E9 56010000   jmp     00408A5C
  00408906   >  33C0          xor     eax, eax
  00408908   .  55            push    ebp
  00408909   .  68 88894000   push    00408988
  0040890E   .  64:FF30       push    dword ptr fs:[eax]
  00408911   .  64:8920       mov     dword ptr fs:[eax], esp
  00408914   .  8D45 A8       lea     eax, dword ptr [ebp-58]
  00408917   .  BA AC924000   mov     edx, 004092AC                    ;  ASCII "dttom"
  0040891C   .  B9 FF000000   mov     ecx, 0FF
  00408921   .  E8 32AFFFFF   call    00403858
  00408926   .  8B45 A8       mov     eax, dword ptr [ebp-58]
  00408929   .  8D55 AC       lea     edx, dword ptr [ebp-54]
  0040892C   .  E8 EBFCFFFF   call    0040861C                         ;  F8后出现注册码,我们用F7跟进分析之
  00408931   .  8B45 AC       mov     eax, dword ptr [ebp-54]
  00408934   .  50            push    eax
  00408935   .  8D45 A4       lea     eax, dword ptr [ebp-5C]
  00408938   .  BA AC934000   mov     edx, 004093AC                    ;  ASCII "55556666"
  0040893D   .  B9 FF000000   mov     ecx, 0FF
  00408942   .  E8 11AFFFFF   call    00403858
  00408947   .  8B55 A4       mov     edx, dword ptr [ebp-5C]
  0040894A   .  58            pop     eax
  0040894B   .  E8 80B0FFFF   call    004039D0                         ;  真假注册码比较函数
  00408950   .  75 17         jnz     short 00408969
  00408952   .  6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  00408954   .  68 DC8A4000   push    00408ADC                         ; |Title = ""D7,"",A2,"",B2,"崽崾?
  00408959   .  68 188B4000   push    00408B18                         ; |Text = "恭?,B2,"您?,AC,"",D7,"",A2,"",B2,"崧胝",B7,"?,A1,""
  0040895E   .  8B45 08       mov     eax, dword ptr [ebp+8]           ; |
  00408961   .  50            push    eax                              ; |hOwner
  00408962   .  E8 0DBEFFFF   call    <jmp.&user32.MessageBoxA>        ; \MessageBoxA
  ......
  
  F7跟进40892C后,来到下面一段,下面要过两次子函数调用,省略了一些准备过程代码见下面的代码:
  ......
  0040869A   .  8BD3          mov     edx, ebx
  0040869C   .  E8 03FBFFFF   call    004081A4                         ;  注册算法子函数,F7跟进
  004086A1   .  8B55 F8       mov     edx, dword ptr [ebp-8]
  004086A4   .  8B45 F4       mov     eax, dword ptr [ebp-C]
  004086A7   .  E8 8CCEFFFF   call    00405538                         ;  对真注册码进行检查计算F7跟进(见最下面)
  004086AC   .  8BD6          mov     edx, esi
  
  ......
  
  004081C0  |.  8BCE          mov     ecx, esi
  004081C2  |.  8BD3          mov     edx, ebx
  004081C4  |.  E8 23FFFFFF   call    004080EC                        ;  第二个子函数F7跟进
  ......
  
  00408114  |.  8BC7          mov     eax, edi
  00408116  |.  E8 F9FEFFFF   call    00408014                        ;  Adler32算法核心  F7跟进
  ........
  
  00408014  /$  53            PUSH EBX
  00408015  |.  56            PUSH ESI
  00408016  |.  50            PUSH EAX
  00408017  |.  31DB          XOR EBX,EBX                              ;置s2=0;
  00408019  |.  66:8B58 02    MOV BX,WORD PTR DS:[EAX+2]
  0040801D  |.  8120 FFFF0000 AND DWORD PTR DS:[EAX],0FFFF             ;adler & 0xffff;
  00408023  |.  8B00          MOV EAX,DWORD PTR DS:[EAX]               ;置adler初值1,s1中间结果存在EAX
  00408025  |.  89D6          MOV ESI,EDX
  00408027  |.  09C9          OR ECX,ECX
  00408029  |.  74 25         JE SHORT Adler32C.00408050
  0040802B  |>  0FB616        /MOVZX EDX,BYTE PTR DS:[ESI]
  0040802E  |.  01D0          |ADD EAX,EDX
  00408030  |.  3D F1FF0000   |CMP EAX,0FFF1                            ;65521=0x0fff1
  00408035  |.  7C 05         |JL SHORT Adler32C.0040803C
  00408037  |.  2D F1FF0000   |SUB EAX,0FFF1
  0040803C  |>  01C3          |ADD EBX,EAX
  0040803E  |.  81FB F1FF0000 |CMP EBX,0FFF1
  00408044  |.  7C 06         |JL SHORT Adler32C.0040804C
  00408046  |.  81EB F1FF0000 |SUB EBX,0FFF1
  0040804C  |>  46            |INC ESI
  0040804D  |.  49            |DEC ECX
  0040804E  |.^ 75 DB         \JNZ SHORT Adler32C.0040802B
  00408050  |>  C1E3 10       SHL EBX,10                                ;(s2 << 16)
  00408053  |.  01C3          ADD EBX,EAX                               ;+ s1
  00408055  |.  58            POP EAX
  00408056  |.  8918          MOV DWORD PTR DS:[EAX],EBX
  00408058  |.  5E            POP ESI
  00408059  |.  5B            POP EBX
  0040805A  \.  C3            RETN
  ......  

  00405538  /$  53            push    ebx
  00405539  |.  56            push    esi
  0040553A  |.  57            push    edi
  0040553B  |.  8BFA          mov     edi, edx
  0040553D  |.  8BF0          mov     esi, eax
  0040553F  |.  8BC6          mov     eax, esi
  00405541  |.  E8 3EE3FFFF   call    00403884                        ;  计算真注册码长度
  00405546  |.  8BD8          mov     ebx, eax
  00405548  |.  8BC7          mov     eax, edi
  0040554A  |.  8BD3          mov     edx, ebx
  0040554C  |.  E8 7FE5FFFF   call    00403AD0
  00405551  |.  8BD6          mov     edx, esi
  00405553  |.  8B37          mov     esi, dword ptr [edi]
  00405555  |.  85DB          test    ebx, ebx
  00405557  |.  74 15         je      short 0040556E
  00405559  |>  8A02          /mov     al, byte ptr [edx]             ;  比较注册码每个字节,若大于0x61小于0x7A,则减0x20
  0040555B  |.  3C 61         |cmp     al, 61
  0040555D  |.  72 06         |jb      short 00405565
  0040555F  |.  3C 7A         |cmp     al, 7A
  00405561  |.  77 02         |ja      short 00405565
  00405563  |.  2C 20         |sub     al, 20
  00405565  |>  8806          |mov     byte ptr [esi], al
  00405567  |.  42            |inc     edx
  00405568  |.  46            |inc     esi
  00405569  |.  4B            |dec     ebx
  0040556A  |.  85DB          |test    ebx, ebx
  0040556C  |.^ 75 EB         \jnz     short 00405559
  0040556E  |>  5F            pop     edi
  0040556F  |.  5E            pop     esi
  00405570  |.  5B            pop     ebx
  00405571  \.  C3            retn
  .....
   
  核心算法汇编代码大概对应如下的C代码:
  #define BASE 65521
  unsigned long update_adler32(unsigned long adler,
           unsigned char *buf, int len)
        {
          unsigned long s1 = adler & 0xffff;
          unsigned long s2 = (adler >> 16) & 0xffff;
          int n;
  
          for (n = 0; n < len; n++) {
            s1 = (s1 + buf[n]) % BASE;
            s2 = (s2 + s1)     % BASE;
          }
          return (s2 << 16) + s1;
        }
   
  注册算法分析出来,下面写出注册代码,这一块我的基础比较差,写的不完善,算是抛砖引玉吧
  
  #include <stdio.h>
  #include <string>
  
  #define BASE 65521 /* largest prime smaller than 65536 */
  
  unsigned long update_adler32(unsigned long adler,unsigned char *buf, int len)
  {
          unsigned long s1 = adler & 0xffff;
          unsigned long s2 = (adler >> 16) & 0xffff;
          int n;
  
          for (n = 0; n < len; n++) {
            s1 = (s1 + buf[n]) % BASE;
            s2 = (s2 + s1)     % BASE;
          }
          return (s2 << 16) + s1;
  }
  
  unsigned long adler32(unsigned char *buf, int len)
  {
          return update_adler32(1L, buf, len);
  }
  
  void main()
  {
          unsigned long Tmp=0;
          int len;
          unsigned char *str;
          str = (unsigned char *) malloc(512);
                 
          printf("请输入用户名:");
          scanf("%s",str);
         
          len=strlen((const char*)str);
         
          Tmp=adler32(str,len);
          printf("\n注册码:%p \n",Tmp);
  
  }
  
--------------------------------------------------------------------------------
【经验总结】
  最好先了解算法原理,再跟踪,这样难度就小多了。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2008年02月21日 下午 01:51:01

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
2
好久没看到CrackMe的破文了,顶贴以表支持!
我还没敢看算法的,等我下定决心后再仔细研究。。。
2008-2-8 18:06
0
雪    币: 479
活跃值: (25)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3
Adler32算法的汇编注册机
首先我要感谢CCDebuger的RadASM模板,省去了我不少时间。
;Adler32keygen.inc

include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc

includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib

DlgProc                        PROTO        :HWND,:UINT,:WPARAM,:LPARAM
GetAdler32code             PROTO  
.const

MAIN_DIALOG                        equ 101
DLG_ABOUT                        equ 102
IDC_NAME                        equ 1001
IDC_SN                                equ 1002
IDC_GEN                                equ 1005
IDC_EXIT                        equ 1006
IDC_ABOUT                        equ 1007
IDC_OK                                equ 1008
ICON_MAIN                        equ 10
BASE                            equ  0FFF1h
.data

szFormat                        db '%p',0        ;You must change here to fit your serial format
error                                db 'Please input your name!',0
s1                              dd  0
s2                              dd  0
;#########################################################################

.data?

hInstance                        dd ?
username                        dw ?
serial                                dd ?
;#################################################

;Adler32keygen.inc        end

;Adler32keygen.asm

.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include Adler32keygen.inc

.code

start:

        invoke GetModuleHandle,NULL
        mov        hInstance,eax

        invoke InitCommonControls
        invoke DialogBoxParam,hInstance,MAIN_DIALOG,NULL,addr DlgProc,NULL
        invoke ExitProcess,0

;########################################################################
AboutProc proc hAWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
       
        mov        eax,uMsg
        .if eax == WM_INITDIALOG
                invoke LoadIcon,hInstance,ICON_MAIN
                invoke SendMessage, hAWin, WM_SETICON, ICON_SMALL, eax
        .elseif eax == WM_COMMAND
                mov eax,wParam
                .if eax == IDC_OK
                        invoke EndDialog,hAWin,0
                .endif       
        .elseif eax == WM_CLOSE
        invoke EndDialog,hAWin,NULL
        .else
                mov                eax,FALSE
                ret
        .endif
        mov                eax,TRUE
        ret

AboutProc endp
;########################################################################

DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

                mov        eax,uMsg
                .if eax == WM_INITDIALOG
                        invoke LoadIcon,hInstance,ICON_MAIN
                        invoke SendMessage, hWin, WM_SETICON, ICON_SMALL, eax
                        pop edi
                .elseif eax == WM_COMMAND
                        mov eax,wParam
                        .if eax == IDC_GEN
                                invoke GetDlgItemText,hWin,IDC_NAME, addr username, 255
                                .if eax == 0
                                        invoke SetDlgItemText,hWin,IDC_SN,addr error
                                        ret
                                .endif
;########################################################################
;Add your code at here:
                        lea   ebx,username
                        invoke    GetAdler32code
                        mov ebx,eax   

;########################################################################

                                invoke wsprintf,addr serial,addr szFormat,ebx
                                invoke SetDlgItemText,hWin,IDC_SN,addr serial
                        .elseif eax == IDC_ABOUT
                        invoke CreateDialogParam,hInstance,DLG_ABOUT,hWin,addr AboutProc,FALSE
                               
                        .elseif eax == IDC_EXIT
                                invoke    EndDialog,hWin,NULL
                        .endif
                       
                .elseif eax == WM_CLOSE
                        invoke EndDialog,hWin,0
                .else
                        mov                eax,FALSE
                        ret
                .endif
        mov                eax,TRUE
        ret

DlgProc endp

GetAdler32code proc
        xor ecx,ecx
        mov ax,1
        mov cx,-1
        and ax,cx
        movzx eax,ax
        mov s1,eax
        shr eax,10h
        mov cx,-1
        movzx ecx,cx
        and eax,ecx
        mov s2,eax
        or ebx, ebx
        jz @@1
    @@2:   
        mov dl,[ebx]
        or dl,dl
        jz @@1
        movzx edx,dl
        mov eax,s1
        add eax,edx
        cmp eax,BASE
        jB @@3
      @@@5:
        sub eax,BASE
        cmp eax,BASE
        jge @@@5
    @@3:
        mov s1,eax
        add eax,s2
        cmp eax,BASE
        jB @@4
      @@@6:
        sub eax,BASE
        cmp eax,BASE
        jge @@@6
    @@4:
        mov s2,eax
        inc ebx
        jmp @@2

    @@1:
        shl eax,10h
        add eax,s1
        ret

GetAdler32code endp

end start

代码写的很差,但是能够凑合工作,有个问题要说明一下, 我声明s1和s2要是不在初始化的.data里,用户名一长就会造成注册码对用户名的覆盖,导致注册码不正确,我用od跟了一下但是我解决不了,后来干脆把s1和s2放入初始化数据里,注册机成功。
上传的附件:
2008-2-17 01:35
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
4
支持。
你的s1 s2是不是定义的太短了才这样呢?
我见过一个老外写的CrackMe,先读取用户名的长度,然后根据长度申请内存,把用户名读到申请的内存里,不用的时候再释放掉。当时把我佩服的。。Orz
2008-2-17 08:01
0
雪    币: 479
活跃值: (25)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
5
谢谢petnt的支持。
我试验了不是s1,s2定义长度的问题。暂时还搞不清楚。
2008-2-17 12:18
0
雪    币: 2256
活跃值: (941)
能力值: (RANK:2210 )
在线值:
发帖
回帖
粉丝
6

分析的再详细一下
就可以加精了
再接再厉
2008-2-17 15:39
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7

分析的再详细一下
就可以加精了
再接再厉
2008-6-7 15:51
0
游客
登录 | 注册 方可回帖
返回
//