首页
社区
课程
招聘
搞定crackme.de提供的一个crackme
发表于: 2006-7-12 20:04 7367

搞定crackme.de提供的一个crackme

2006-7-12 20:04
7367

本菜鸟花了4天时间,连跟踪调试到写tutorial。想骗一个精华。(诶,好廉价的劳动力啊 :))

这个crackme据说是十分简单,但是仍然需要花费很多功夫来写tutorial和keygen(本菜鸟可花了4天 :( )。

crackme来源: crackme.de
来看看该crackme作者是怎么说的:

Author: Kostya
Level : Very easy - 1 - for newbies
=========================================================================

Hi! There!..It's my first keygenme (crackme). Here are some tasks you should do:
-------------------------------------------------------------------------
1. To start searching a key for your name, you need to patch something to enter
   more than 1 symbol, (Patch it to 80 symbols) (no jne, je, & etc jump patching.)

2. Find key generator solution, and write a keygen

3. Patch it, to stop closing after the registration procedure
   (not allowed to patch jne, je, & etc "jump patching". (e.g: "jne" -> "je")
-------------------------------------------------------------------------
Exe file is not protected, and it is very easy to find key & to write a
keygen. But no built-in keygens (injections). As u can see I made it for newbies...
====================================================================================
====================================================================================
好,根据作者描述的步骤,说干就干!

1、
用PEID检测,显示MASM/TASM无壳,运行发现姓名和注册码都只能输入单个字符。
作者在第一点中提出要patch something to enter more than 1 symbol,
那么我们先干这个
首先看到程序加载后距离起点没几行有此代码:
0040100C  |.  E8 C5030000   CALL <JMP.&COMCTL32.#17>                 ; [InitCommonControls
00401011  |.  6A 00         PUSH 0                                   ; /lParam = NULL
00401013  |.  68 2E104000   PUSH KeygenMe.0040102E                   ; |DlgProc = KeygenMe.0040102E  ;说明这里是消息处理函数!
00401018  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
0040101A  |.  6A 65         PUSH 65                                  ; |pTemplate = 65
0040101C  |.  FF35 04304000 PUSH DWORD PTR DS:[403004]               ; |hInst = 00400000
00401022  |.  E8 7F030000   CALL <JMP.&USER32.DialogBoxParamA>       ; \DialogBoxParamA
...............

使用命令 at 0040102E
跟踪消息处理函数(其实就在下面)以下是片段:
00401043  |.  68 E9030000   PUSH 3E9                                 ; /ControlID = 3E9 (1001.)
00401048  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
0040104B  |.  E8 62030000   CALL <JMP.&USER32.GetDlgItem>            ; \GetDlgItem
00401050  |.  A3 0C324000   MOV DWORD PTR DS:[40320C],EAX
00401055  |.  33C0          XOR EAX,EAX
00401057  |.  68 EA030000   PUSH 3EA                                 ; /ControlID = 3EA (1002.)
0040105C  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
0040105F  |.  E8 4E030000   CALL <JMP.&USER32.GetDlgItem>            ; \GetDlgItem
00401064  |.  A3 10324000   MOV DWORD PTR DS:[403210],EAX
00401069  |.  33C0          XOR EAX,EAX
0040106B  |.  E8 9D020000   CALL KeygenMe.0040130D                   ;  看到前面的GetDlgItem了吗?所以这里是关键!F7 之.
00401070  |.  6A 13         PUSH 13                                  ; /Flags = SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE
00401072  |.  6A 00         PUSH 0                                   ; |Height = 0
00401074  |.  6A 00         PUSH 0                                   ; |Width = 0
00401076  |.  6A 00         PUSH 0                                   ; |Y = 0
00401078  |.  6A 00         PUSH 0                                   ; |X = 0
0040107A  |.  6A FF         PUSH -1                                  ; |InsertAfter = HWND_TOPMOST
0040107C  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
0040107F  |.  E8 4C030000   CALL <JMP.&USER32.SetWindowPos>          ; \SetWindowPos
00401084  |.  E9 E8010000   JMP KeygenMe.00401271
00401089  |>  3D 11010000   CMP EAX,111
........................

根据注释F7跟踪下去

0040130D  /$  50            PUSH EAX
0040130E  |.  33C0          XOR EAX,EAX
00401310  |.  A1 14324000   MOV EAX,DWORD PTR DS:[403214]
00401315  |.  6A 00         PUSH 0                                   ; /lParam = 0              ;放在高地址
00401317  |.  6A 01         PUSH 1                                   ; |wParam = 1  ;这里!!改成 push 50  (50h==80d)
00401319  |.  68 C5000000   PUSH 0C5                                 ; |Message = EM_LIMITTEXT
0040131E  |.  68 E9030000   PUSH 3E9                                 ; |ControlID = 3E9 (1001.)
00401323  |.  50            PUSH EAX                                 ; |hWnd => 00200284 ('KeygenMe #1 by Kostya',class='#32770')
00401324  |.  E8 A1000000   CALL <JMP.&USER32.SendDlgItemMessageA>   ; \SendDlgItemMessageA
00401329  |.  33C0          XOR EAX,EAX
0040132B  |.  A1 14324000   MOV EAX,DWORD PTR DS:[403214]
00401330  |.  6A 00         PUSH 0                                   ; /lParam = 0
00401332  |.  6A 01         PUSH 1                                   ; |wParam = 1 ;还有这里!!也改50
00401334  |.  68 C5000000   PUSH 0C5                                 ; |Message = EM_LIMITTEXT
00401339  |.  68 EA030000   PUSH 3EA                                 ; |ControlID = 3EA (1002.)
0040133E  |.  50            PUSH EAX                                 ; |hWnd => 00200284 ('KeygenMe #1 by Kostya',class='#32770')
0040133F  |.  E8 86000000   CALL <JMP.&USER32.SendDlgItemMessageA>   ; \SendDlgItemMessageA
00401344  |.  58            POP EAX
00401345  \.  C3            RETN
.................

一目了然了吧!

修改上述代码后别忘记 右键 “复制可执行文件” 选择 “所有修改”  点击“全部复制” 。再右键“保存文件”
暂时命名为"patched.exe"。
(别砸我,这个patch是crackme作者要求的)

3、补丁,补丁,补丁……
为了下面调试的方便,我们先打这个补丁。
这个阻止退出的补丁更是简单:
看到几个MessageBox那里:

00401143  |.  E8 7C020000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
00401148  |.  B8 00000000   MOV EAX,0                                
0040114D  |.  83F8 00       CMP EAX,0
00401150      0F85 FF000000 JNZ patched.00401255                     ;
00401156  |.^ E9 CCFEFFFF   JMP patched.00401027

呵呵,再看看它的要求吧,不能patch jmp,jne etc哦!!
命令行里输入 at 00401148

00401148  |.  B8 00000000   MOV EAX,0
这行改成 mov eax,1。呵呵,作者要求的两个补丁任务都完成了。

2、找出算法,写个KeyGen
现在,关掉原版crackme,利用刚刚打完补丁的patched.exe。
首先用OD打开patched.exe自是不用说了。
用w32dasm打开patched.exe(不要跟我说没有w32dasm),找到 004010e9 地址处。(为什么偏偏使用这个地址?--这个地址就是注册提示的MessageBox啊!)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040109B(C)
|
:004010B6 817D10ED030000          cmp dword ptr [ebp+10], 000003ED
:004010BD 0F85AE010000            jne 00401271
:004010C3 FF350C324000            push dword ptr [0040320C]

* Reference To: USER32.GetWindowTextLengthA, Ord:015Ch
........
你肯定想到去跟踪004010b6吧?其实004010b6 这个地址并没什么意思。
于是在 GetWindowTextLengthA 处按下F2设置断点
004010C3  |.  FF35 0C324000 PUSH DWORD PTR DS:[40320C]               ; /hWnd = 0017024C (class='Edit',parent=001C0186)
004010C9  |.  E8 F0020000   CALL <JMP.&USER32.GetWindowTextLengthA>  ; \GetWindowTextLengthA ;断点
................

F9运行,输入名字: wiaa 密码: 123456
004011E2  |.  A1 10324000   MOV EAX,DWORD PTR DS:[403210]
004011E7  |.  50            PUSH EAX                                 ; /hWnd => 00870284 (class='Edit',parent=0022027C)
004011E8  |.  E8 D1010000   CALL <JMP.&USER32.GetWindowTextLengthA>  ; \GetWindowTextLengthA
004011ED  |.  B9 00000000   MOV ECX,0                                ;  ecx=0 留意一下
004011F2  |.  83F8 18       CMP EAX,18                               ;  注册码长度必须等于18h==24d
004011F5  |.^ 0F85 20FFFFFF JNZ patched.0040111B
...............
运行到这里,发现注册码必须24位长
在这里F2设个断点。重新F9运行输入任意24位注册码(我用123456789012345678901234)
可运行没几行又发现问题。
0040120A  |.  E8 A9010000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
0040120F  |.  B8 0C314000   MOV EAX,patched.0040310C                 ;  ASCII "1234-6789012345678901234"
00401214  |.  E8 D2000000   CALL patched.004012EB
00401219  |.  B8 0C314000   MOV EAX,patched.0040310C                 ;  ASCII "1234-6789012345678901234"
0040121E  |.  83C0 04       ADD EAX,4
00401221  |.  8038 2D       CMP BYTE PTR DS:[EAX],2D                 ;  第5位必须是-
00401224  |.^ 0F85 F1FEFFFF JNZ patched.0040111B
.........................
他居然要求第5位是-,没办法,F9运行后把刚才注册码的第5位改成'-'
后面照样,它要求第15位也是'-'。F9运行,照改不误。

往后运行
00401236  |.  68 24324000   PUSH patched.00403224                    ;  ASCII "KOSD-378396E5D-FB79BB687"
0040123B  |.  68 0C314000   PUSH patched.0040310C                    ;  ASCII "1234-678901234-678901234"
00401240  |.  E8 1F010000   CALL patched.00401364                    ;  字符串比较函数,若相等返回1
...........
经测试,发现这个KOSD-378396E5D-FB79BB687确实是真正的注册码。
那么我们来看看这个注册码是怎么出来的。
看看下面代码吧,我在重要的地方都加了注释。
004010F8  |.  33C9          XOR ECX,ECX
004010FA  |.  33DB          XOR EBX,EBX                              ;  ebx被清零咯
004010FC  |.  33D2          XOR EDX,EDX
004010FE  |>  43            INC EBX                                  ;  ebx=1
004010FF  |.  53            PUSH EBX                                 ;  留意一下这一句 ebx=1
00401100  |.  FF35 0C324000 PUSH DWORD PTR DS:[40320C]               ; /hWnd = 001E0212 (class='Edit',parent=0026028C)
00401106  |.  E8 B3020000   CALL <JMP.&USER32.GetWindowTextLengthA>  ; \GetWindowTextLengthA
0040110B  |.  33C9          XOR ECX,ECX
0040110D  |.  8BD8          MOV EBX,EAX                              ;  ebx: 仍然是名字的长度
0040110F  |.  B8 0C304000   MOV EAX,patched.0040300C                 ;  ASCII "USER"
00401114  |.  E8 B8010000   CALL patched.004012D1                    ;  写注册机的时候需要跟进去
00401119  |.  EB 40         JMP SHORT patched.0040115B
0040111B  |>  33C0          XOR EAX,EAX                              ;  计算出注册码后跳到此处
0040111D  |.  83F9 01       CMP ECX,1                                ;  即前面字符串比较函数的返回值
00401120  |.  75 0E         JNZ SHORT patched.00401130

...............................
00401161  |.  33D2          XOR EDX,EDX
00401163  |.  890D 18324000 MOV DWORD PTR DS:[403218],ECX            ;  注册码和这个数值有关
00401169  |.  33C0          XOR EAX,EAX                              ;  pBufCount,一个指针,具体看SDK帮助吧
0040116B  |.  68 00304000   PUSH patched.00403000                    ; /pBufCount = patched.00403000
00401170  |.  68 0C304000   PUSH patched.0040300C                    ; |Buffer = patched.0040300C
00401175  |.  E8 62020000   CALL <JMP.&ADVAPI32.GetUserNameA>        ; \GetUserNameA
0040117A  |.  33D2          XOR EDX,EDX
0040117C  |.  33C9          XOR ECX,ECX                              ;  edx=ecx=0
0040117E  |.^ E9 7BFFFFFF   JMP patched.004010FE
00401183  |>  33D2          XOR EDX,EDX
00401185  |.  890D 1C324000 MOV DWORD PTR DS:[40321C],ECX            ;  注册码也和这个数值有关
0040118B  |.  FF35 1C324000 PUSH DWORD PTR DS:[40321C]
00401191  |.  FF35 18324000 PUSH DWORD PTR DS:[403218]
00401197  |.  E8 DE000000   CALL patched.0040127A                    ;  处理输入的名字和计算机登陆名的运算结果
0040119C  |.  A3 20324000   MOV DWORD PTR DS:[403220],EAX
004011A1  |.  E8 A0010000   CALL patched.00401346
004011A6  |.  FF35 1C324000 PUSH DWORD PTR DS:[40321C]               ;  登录名运算结果
004011AC  |.  68 24324000   PUSH patched.00403224                    ;  ASCII "B96DF378396E5D2FB79BB687"
004011B1  |.  E8 EC000000   CALL patched.004012A2                    ;  把先push的参数转化成16进制字符串,存到后push的参数指针中
004011B6  |.  B8 24324000   MOV EAX,patched.00403224                 ;  ASCII "B96DF378396E5D2FB79BB687"
004011BB  |.  83C0 08       ADD EAX,8                                ;  得到的不是注册码
004011BE  |.  FF35 20324000 PUSH DWORD PTR DS:[403220]               ;  要转化的参数 403220 在 40321C 后
004011C4  |.  8D00          LEA EAX,DWORD PTR DS:[EAX]               ;  无意义
004011C6  |.  50            PUSH EAX
004011C7  |.  E8 D6000000   CALL patched.004012A2
004011CC  |.  B8 24324000   MOV EAX,patched.00403224                 ;  ASCII "B96DF378396E5D2FB79BB687"
004011D1  |.  83C0 10       ADD EAX,10                               ;  注册码还是没有出来
004011D4  |.  FF35 18324000 PUSH DWORD PTR DS:[403218]
004011DA  |.  8D00          LEA EAX,DWORD PTR DS:[EAX]
004011DC  |.  50            PUSH EAX
004011DD  |.  E8 C0000000   CALL patched.004012A2
004011E2  |.  A1 10324000   MOV EAX,DWORD PTR DS:[403210]
004011E7  |.  50            PUSH EAX                                 ; /hWnd => 00740240 (class='Edit',parent=0026028C)
004011E8  |.  E8 D1010000   CALL <JMP.&USER32.GetWindowTextLengthA>  ; \GetWindowTextLengthA
004011ED  |.  B9 00000000   MOV ECX,0                                ;  ecx=0 留意一下
004011F2  |.  83F8 18       CMP EAX,18                               ;  注册码长度必须等于18h==24d
004011F5  |.^ 0F85 20FFFFFF JNZ patched.0040111B
004011FB  |.  40            INC EAX
004011FC  |.  50            PUSH EAX                                 ; /Count
004011FD  |.  68 0C314000   PUSH patched.0040310C                    ; |Buffer = patched.0040310C
00401202  |.  68 EA030000   PUSH 3EA                                 ; |ControlID = 3EA (1002.)
00401207  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
0040120A  |.  E8 A9010000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
0040120F  |.  B8 0C314000   MOV EAX,patched.0040310C                 ;  ASCII "1234-678901234-678901234"
00401214  |.  E8 D2000000   CALL patched.004012EB                    ;  把标准注册码的头3位改成KOS,并添加'-'符号
00401219  |.  B8 0C314000   MOV EAX,patched.0040310C                 ;  ASCII "1234-678901234-678901234"
0040121E  |.  83C0 04       ADD EAX,4
00401221  |.  8038 2D       CMP BYTE PTR DS:[EAX],2D                 ;  第5位必须是-
00401224  |.^ 0F85 F1FEFFFF JNZ patched.0040111B
0040122A  |.  83C0 0A       ADD EAX,0A
0040122D  |.  8038 2D       CMP BYTE PTR DS:[EAX],2D                 ;  第15位也是'-'哦
00401230  |.^ 0F85 E5FEFFFF JNZ patched.0040111B
00401236  |.  68 24324000   PUSH patched.00403224                    ;  ASCII "B96DF378396E5D2FB79BB687"
0040123B  |.  68 0C314000   PUSH patched.0040310C                    ;  ASCII "1234-678901234-678901234"
00401240  |.  E8 1F010000   CALL patched.00401364                    ;  字符串比较函数,若相等返回1
00401245  |.  8BC8          MOV ECX,EAX
.........................................
这个crackme的算法不是很好表达,具体细节需要自己跟踪才会透彻。不过有了本菜鸟的注释,可以少走写弯路。
算法大致是这样:

先根据输入的姓名放入DS:[0040300C],计算出一个ECX的值,再写入DS:[403218]处,再取计算机登录名经过同样的算法,计算出来ECX,存入DS:[40321C]
然后把这两个值经过一通运算,写入DS:[403220]
--------------------------------------------------------------------------
几个函数的作用
0040127A: 上面所说的 两个值的一通运算 (DWORD,DWORD)
00401346: 对登录名和输入名又是一通计算,并且不涉及堆栈操作
004012A2: 把先push的参数转化成16进制字符串,存到后push的参数指针中    (DWORD,DWORD)
004012EB: 把标准注册码的头3位改成KOS,并添加'-'符号

=================================================================
就此可以开始写KeyGen了!
我就套用曾经写过的注册机模版(见"看雪论坛"Win32/Win64编程栏目的主题帖子)这个模版是用汇编构造的。
用汇编写KeyGen的好处在于对那种生成正确注册码的程序可以通过简单的复制/粘贴,稍加修改就能完成一个KeyGen(呵呵,偷懒吧)。

好了,把计算注册码的那部分代码CTRL+C,CTRL+V粘贴到注册机模版上,一行一行改过来就完成KeyGen了。

所有文件、源代码下载:
http://wiaa.blogbus.com/files/1152705799.rar


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (12)
雪    币: 249
活跃值: (10)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
2
用复制、粘贴的方法写注册机瞬间就可完成KeyGen
代码:

.386
.Model Flat, StdCall
Option Casemap :None

Include windows.inc
Include user32.inc
Include kernel32.inc
Include gdi32.inc
include ADVAPI32.inc

includelib gdi32.lib
IncludeLib user32.lib
IncludeLib kernel32.lib
includelib ADVAPI32.lib
include macro.asm
       
        WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
        WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
        ;------------CONSTS-----------
        ID_BTOK                EQU 1
        ID_BTQUIT        EQU 2
        ID_EDNAME                EQU 3
        ID_EDCODE                EQU 4
        ;-----------------------------
.DATA
        blank                        db 0
        staticclass        db 'STATIC',0
        buttonclass        db 'BUTTON',0
        editclass        db 'EDIT',0
        szClassName db 'WCRPROGRAM_REGMODAL',0
        software                db '注册机',0
        nullname                db '先输入姓名吧 :)',0
        wcr403218        dd 0
        wcr40321C        dd 0
        wcr403220        dd 0
        wcr00403224        db 50 dup (0)
        namelength        dd 0
        ;--------------------------------------
        hInstance        dd 0
        btok                        dd        0
        btquit                dd 0
        edname                dd 0
        edcode                dd 0
        wcrname                db 51 dup (0)
        wcrcode                db 51 dup (0)
        codelenth        dd 0
.DATA?

.CODE
START:

        invoke GetModuleHandle,NULL
        mov hInstance,eax
        invoke WinMain,hInstance,NULL,NULL,SW_SHOWDEFAULT
        invoke ExitProcess,0

WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
        LOCAL wc   :WNDCLASSEX
        LOCAL msg  :MSG
        local hWnd :HWND
       
        mov wc.cbSize,sizeof WNDCLASSEX
        mov wc.style,CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
        mov wc.lpfnWndProc,offset WndProc
        mov wc.cbClsExtra,NULL
        mov wc.cbWndExtra,NULL
        push hInst
        pop wc.hInstance
        mov wc.hbrBackground,COLOR_BTNFACE+1
        mov wc.lpszMenuName,NULL
        mov wc.lpszClassName,offset szClassName
        invoke LoadIcon,hInst,100
        mov wc.hIcon,eax
        invoke LoadCursor,NULL,IDC_ARROW
        mov wc.hCursor,eax
        mov wc.hIconSm,0
        invoke RegisterClassEx, ADDR wc
        invoke CreateWindowEx,NULL,ADDR szClassName,offset software,WS_DLGFRAME or WS_VISIBLE,200,200,300,200,NULL,NULL,hInst,NULL
        mov hWnd,eax
        invoke CreateWindowEx,0,offset buttonclass,CTXT("生成注册码"),WS_CHILD or WS_VISIBLE,30,130,90,25,hWnd,ID_BTOK,hInst,0
        mov btok,eax
        invoke CreateWindowEx,0,offset buttonclass,CTXT("离开"),WS_CHILD or WS_VISIBLE,170,130,90,25,hWnd,ID_BTQUIT,hInst,0
        mov btquit,eax
        invoke CreateWindowEx,0,offset staticclass,CTXT("Name:"),WS_CHILD or WS_VISIBLE,20,30,50,25,hWnd,0,hInst,0
        invoke CreateWindowEx,0,offset staticclass,CTXT("Code:"),WS_CHILD or WS_VISIBLE,20,80,50,25,hWnd,0,hInst,0
        invoke CreateWindowEx,0,offset editclass,offset blank,WS_CHILD or WS_VISIBLE or WS_BORDER,80,30,180,23,hWnd,ID_EDNAME,hInst,0
        mov edname,eax
        invoke CreateWindowEx,0,offset editclass,offset blank,WS_CHILD or WS_VISIBLE or ES_READONLY or WS_BORDER or ES_AUTOHSCROLL,80,80,180,23,hWnd,ID_EDCODE,hInst,0
        mov edcode,eax
        StartLoop:
                invoke GetMessage,ADDR msg,NULL,0,0
                        cmp eax, 0
                        je ExitLoop
                                invoke TranslateMessage, ADDR msg
                                invoke DispatchMessage, ADDR msg
                        jmp StartLoop
        ExitLoop:
       
mov eax,msg.wParam
ret
WinMain endp
wcr004012d1:
;004012D1  /$  8A10          MOV DL,BYTE PTR DS:[EAX]                 ;  dx:[eax] : 名字的第[eax]个字符
MOV DL,BYTE PTR DS:[EAX]
;004012D3  |.  6BC9 48       IMUL ECX,ECX,48
IMUL ECX,ECX,48H
;004012D6  |.  2BCA          SUB ECX,EDX
SUB ECX,EDX
;004012D8  |.  83E9 6F       SUB ECX,6F
SUB ECX,6FH
;004012DB  |.  8BD1          MOV EDX,ECX
MOV EDX,ECX
;004012DD  |.  81F1 AFAC0B00 XOR ECX,0BACAF
XOR ECX,0BACAFH
;004012E3  |.  40            INC EAX
INC EAX
;004012E4  |.  4B            DEC EBX
DEC EBX
;004012E5  |.  83FB 00       CMP EBX,0
CMP EBX,0H
;004012E8  |.^ 75 E7         JNZ SHORT patched.004012D1               ;  循环读取每个字符 返回函数开始
jnz wcr004012d1
;004012EA  \.  C3            RETN
retn

wcr0040127a:
;0040127A  /$  55            PUSH EBP
push ebp
;0040127B  |.  8BEC          MOV EBP,ESP
MOV EBP,ESP
;0040127D  |.  33C0          XOR EAX,EAX
XOR EAX,EAX
;0040127F  |.  33DB          XOR EBX,EBX
XOR EBX,EBX
;00401281  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]
MOV EAX,DWORD PTR SS:[EBP+8h]
;00401284  |.  8B5D 0C       MOV EBX,DWORD PTR SS:[EBP+C]
MOV EBX,DWORD PTR SS:[EBP+0CH]
;00401287  |.  8BD0          MOV EDX,EAX
MOV EDX,EAX
;00401289  |.  33D3          XOR EDX,EBX
XOR EDX,EBX
;0040128B  |.  81F2 ACFF0000 XOR EDX,0FFAC
XOR EDX,0FFACH
;00401291  |.  81F3 53050000 XOR EBX,553
XOR EBX,553H
;00401297  |.  03C3          ADD EAX,EBX
ADD EAX,EBX
;00401299  |.  03DA          ADD EBX,EDX
ADD EBX,EDX
;0040129B  |.  4B            DEC EBX
DEC EBX
;0040129C  |.  03C3          ADD EAX,EBX
ADD EAX,EBX
;0040129E  |.  C9            LEAVE
LEAVE
;0040129F  \.  C2 0800       RETN 8
RETN 8H

wcr00401346:
;00401346  /$  A1 1C324000   MOV EAX,DWORD PTR DS:[40321C]            ;  登录名运算结果
MOV EAX,DWORD PTR DS:[wcr40321C]
;0040134B  |.  8B1D 18324000 MOV EBX,DWORD PTR DS:[403218]            ;  输入名运算结果
MOV EBX,DWORD PTR DS:[wcr403218]
;00401351  |.  3BC3          CMP EAX,EBX
CMP EAX,EBX
;00401353  |.  75 0E         JNZ SHORT patched.00401363               ;  跳到retn
JNZ wcr00401363
;00401355  |.  81F3 8E000000 XOR EBX,8E
XOR EBX,8EH
;0040135B  |.  03D8          ADD EBX,EAX
ADD EBX,EAX
;0040135D  |.  891D 18324000 MOV DWORD PTR DS:[403218],EBX
MOV DWORD PTR DS:[wcr403218],EBX
wcr00401363:;00401363  \>  C3            RETN
retn

wcr004012A2:
;004012A2  /$  55            PUSH EBP
push ebp
;004012A3  |.  8BEC          MOV EBP,ESP
MOV EBP,ESP
;004012A5  |.  8B75 08       MOV ESI,DWORD PTR SS:[EBP+8]
MOV ESI,DWORD PTR SS:[EBP+8H]
;004012A8  |.  83C6 08       ADD ESI,8
ADD ESI,8H
;004012AB  |.  8B45 0C       MOV EAX,DWORD PTR SS:[EBP+C]
MOV EAX,DWORD PTR SS:[EBP+0Ch]
;004012AE  |.  B9 10000000   MOV ECX,10
MOV ECX,10H
;004012B3  |.  33DB          XOR EBX,EBX
XOR EBX,EBX
wcr004012B5:;004012B5  |>  33D2          /XOR EDX,EDX                             ;  jnz跳这里
XOR EDX,EDX
;004012B7  |.  F7F1          |DIV ECX
DIV ECX
;004012B9  |.  4E            |DEC ESI
DEC ESI
;004012BA  |.  80C2 30       |ADD DL,30
ADD DL,30H
;004012BD  |.  80FA 3A       |CMP DL,3A
CMP DL,3AH
;004012C0  |.  72 03         |JB SHORT patched.004012C5
JB wcr004012C5
;004012C2  |.  80C2 07       |ADD DL,7
ADD DL,7H
wcr004012C5:;004012C5  |>  8816          |MOV BYTE PTR DS:[ESI],DL                ;  jb跳这里
MOV BYTE PTR DS:[ESI],DL    ;error1
;004012C7  |.  43            |INC EBX
INC EBX
;004012C8  |.  83FB 08       |CMP EBX,8
CMP EBX,8H
;004012CB  |.^ 75 E8         \JNZ SHORT patched.004012B5
JNZ SHORT wcr004012B5
;004012CD  |.  C9            LEAVE
LEAVE
;004012CE  \.  C2 0800       RETN 8
RETN 8H

wcr004012EB:
;004012EB  /$  BA 24324000   MOV EDX,patched.00403224
MOV EDX,offset wcr00403224
;004012F0  |.  83C2 04       ADD EDX,4
ADD EDX,4H
;004012F3  |.  C602 2D       MOV BYTE PTR DS:[EDX],2D
MOV BYTE PTR DS:[EDX],2DH
;004012F6  |.  83C2 0A       ADD EDX,0A
ADD EDX,0AH
;004012F9  |.  C602 2D       MOV BYTE PTR DS:[EDX],2D
MOV BYTE PTR DS:[EDX],2Dh
;004012FC  |.  BA 24324000   MOV EDX,patched.00403224
MOV EDX,offset wcr00403224
;00401301  |.  C602 4B       MOV BYTE PTR DS:[EDX],4B
MOV BYTE PTR DS:[EDX],4BH
;00401304  |.  42            INC EDX
INC EDX
;00401305  |.  C602 4F       MOV BYTE PTR DS:[EDX],4F
MOV BYTE PTR DS:[EDX],4Fh
;00401308  |.  42            INC EDX
INC EDX
;00401309  |.  C602 53       MOV BYTE PTR DS:[EDX],53
MOV BYTE PTR DS:[EDX],53h
;0040130C  \.  C3            RETN
RETN

WndProc proc hWin:DWORD,uMsg:DWORD,wParam :DWORD,lParam :DWORD
        .if uMsg==WM_CREATE
                ;----------------------Write it by your self :)---------------------------------------------------------
                ; MessageBox,hWin,CTXT("作者QQ:154550544",0dh,0dh,"E-mail: [email]wiaamail@163.com[/email]"),offset software,0 ;|
                ;-------------------------------------------------------------------------------------------------------
        .elseif uMsg == WM_DESTROY
                invoke PostQuitMessage,NULL
        .elseif uMsg==WM_COMMAND
                shl wParam,16D
                shr wParam,16D
                .if wParam==ID_BTOK
                        xor eax,eax
                        mov DWORD PTR wcrcode,eax
                        invoke GetWindowText,edname,offset wcrname,50
                        mov namelength,eax
                        and eax,eax
                        jnz WndProc1
                        invoke MessageBox,hWin,offset nullname,offset software,0
                        ret
WndProc1:
;------------------------------------TO DO:-----------------------------------------
;        The most important code here:
;                name has been in var [wcrname] (max 50 except '\0').
;                code will be calculated by you and put in var [wcrcode] and that's your job.
;        HINIT: you can make full use of 'wsprintf' to help you transfer the int to text.
;------------------------------------START------------------------------------------
;1234-678901234-678901234
;004010C9  |.  E8 F0020000   CALL <JMP.&USER32.GetWindowTextLengthA>  ; \GetWindowTextLengthA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mov eax,namelength
invoke GetWindowTextLength,edname
;004010CE  |.  B9 00000000   MOV ECX,0
;004010D3  |.  83F8 13       CMP EAX,13                               ;  名字长度不能太长
;004010D6  |.  7F 43         JG SHORT patched.0040111B
;004010D8  |.  83F8 03       CMP EAX,3                                ;  也不能太短
;004010DB  |.  7E 3E         JLE SHORT patched.0040111B
;004010DD  |.  40            INC EAX                                  ;  名字长度+1
inc eax
;004010DE  |.  50            PUSH EAX                                 ; /Count
push eax
;004010DF  |.  68 0C304000   PUSH wcr0040300C                    ; |Buffer = patched.0040300C
;004010E4  |.  68 E9030000   PUSH 3E9                                 ; |ControlID = 3E9 (1001.)
;004010E9  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
;004010EC  |.  E8 C7020000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
;  40300c 即是 wcrname
;004010F1  |.  B8 78204000   MOV EAX,patched.00402078                 ;  ASCII "=== I said it is very easy, for newbies :)... ==="
;004010F6  |.  33C0          XOR EAX,EAX                              ;  :) 上面多此一举
xor eax,eax
;004010F8  |.  33C9          XOR ECX,ECX
xor ecx,ecx
;004010FA  |.  33DB          XOR EBX,EBX                              ;  ebx被清零咯
xor ebx,ebx
;004010FC  |.  33D2          XOR EDX,EDX
xor edx,edx
wcr004010fe:;004010FE  |>  43            INC EBX                                  ;  ebx=1
inc ebx
;004010FF  |.  53            PUSH EBX                                 ;  留意一下这一句 ebx=1
push ebx
;00401100  |.  FF35 0C324000 PUSH DWORD PTR DS:[40320C]               ; /hWnd = NULL
;00401106  |.  E8 B3020000   CALL <JMP.&USER32.GetWindowTextLengthA>  ; \GetWindowTextLengthA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mov eax,namelength
invoke GetWindowTextLength,edname
;0040110B  |.  33C9          XOR ECX,ECX
xor ecx,ecx
;0040110D  |.  8BD8          MOV EBX,EAX                              ;  ebx: 仍然是名字的长度
mov ebx,eax
;0040110F  |.  B8 0C304000   MOV EAX,patched.0040300C
mov eax,offset wcrname
;00401114  |.  E8 B8010000   CALL patched.004012D1                    ;  写注册机的时候需要跟进去
call wcr004012d1
;00401119  |.  EB 40         JMP SHORT patched.0040115B
jmp wcr0040115b

wcr0040115b:;0040115B  |>  5B            POP EBX                                  ;  还记得到吧,第一次的ebx是处理输入的名字,第2次循环是处理计算机的登陆名
pop ebx
;0040115C  |.  83FB 02       CMP EBX,2
CMP EBX,2h
;0040115F  |.  74 22         JE SHORT patched.00401183
je wcr00401183
;00401161  |.  33D2          XOR EDX,EDX
xor edx,edx
;00401163  |.  890D 18324000 MOV DWORD PTR DS:[403218],ECX            ;  注册码和这个数值有关
MOV DWORD PTR DS:[wcr403218],ECX
;00401169  |.  33C0          XOR EAX,EAX                              ;  pBufCount,一个指针,具体看SDK帮助吧
XOR EAX,EAX
;0040116B  |.  68 00304000   PUSH patched.00403000                    ; /pBufCount = patched.00403000
;00401170  |.  68 0C304000   PUSH patched.0040300C                    ; |Buffer = patched.0040300C
;00401175  |.  E8 62020000   CALL <JMP.&ADVAPI32.GetUserNameA>        ; \GetUserNameA
push 0ffh
pop namelength
invoke GetUserName,offset wcrname,offset namelength
;0040117A  |.  33D2          XOR EDX,EDX
xor edx,edx
;0040117C  |.  33C9          XOR ECX,ECX                              ;  edx=ecx=0
xor ecx,ecx
;0040117E  |.^ E9 7BFFFFFF   JMP patched.004010FE
jmp wcr004010fe
wcr00401183:;00401183  |>  33D2          XOR EDX,EDX
xor edx,edx
;00401185  |.  890D 1C324000 MOV DWORD PTR DS:[40321C],ECX            ;  注册码也和这个数值有关
MOV DWORD PTR DS:[wcr40321C],ECX
;0040118B  |.  FF35 1C324000 PUSH DWORD PTR DS:[40321C]
PUSH DWORD PTR DS:[wcr40321C]
;00401191  |.  FF35 18324000 PUSH DWORD PTR DS:[403218]
PUSH DWORD PTR DS:[wcr403218]
;00401197  |.  E8 DE000000   CALL patched.0040127A                    ;  处理输入的名字和计算机登陆名的运算结果
call wcr0040127a
;0040119C  |.  A3 20324000   MOV DWORD PTR DS:[403220],EAX
MOV DWORD PTR DS:[wcr403220],EAX
;004011A1  |.  E8 A0010000   CALL patched.00401346                    ;  对登录名和输入名又是一通计算,并且不涉及堆栈操作
CALL wcr00401346
;004011A6  |.  FF35 1C324000 PUSH DWORD PTR DS:[40321C]               ;  登录名运算结果
PUSH DWORD PTR DS:[wcr40321C]
;004011AC  |.  68 24324000   PUSH patched.00403224
PUSH offset wcr00403224
;004011B1  |.  E8 EC000000   CALL patched.004012A2                    ;  把先push的参数转化成16进制字符串,存到后push的参数指针中
CALL wcr004012A2
;004011B6  |.  B8 24324000   MOV EAX,patched.00403224
MOV EAX,offset wcr00403224
;004011BB  |.  83C0 08       ADD EAX,8                                ;  得到的不是注册码
ADD EAX,8H
;004011BE  |.  FF35 20324000 PUSH DWORD PTR DS:[403220]               ;  要转化的参数 403220 在 40321C 后
PUSH DWORD PTR DS:[wcr403220]
;004011C4  |.  8D00          LEA EAX,DWORD PTR DS:[EAX]               ;  无意义
LEA EAX,DWORD PTR DS:[EAX]
;004011C6  |.  50            PUSH EAX
PUSH EAX
;004011C7  |.  E8 D6000000   CALL patched.004012A2
CALL wcr004012A2
;004011CC  |.  B8 24324000   MOV EAX,patched.00403224

MOV EAX,offset wcr00403224

;004011D1  |.  83C0 10       ADD EAX,10                               ;  注册码还是没有出来
ADD EAX,10H
;004011D4  |.  FF35 18324000 PUSH DWORD PTR DS:[403218]
PUSH DWORD PTR DS:[wcr403218]
;004011DA  |.  8D00          LEA EAX,DWORD PTR DS:[EAX]
LEA EAX,DWORD PTR DS:[EAX]
;004011DC  |.  50            PUSH EAX
PUSH EAX
;004011DD  |.  E8 C0000000   CALL patched.004012A2
CALL wcr004012A2
;004011E2  |.  A1 10324000   MOV EAX,DWORD PTR DS:[403210]
;004011E7  |.  50            PUSH EAX                                 ; /hWnd => NULL
;004011E8  |.  E8 D1010000   CALL <JMP.&USER32.GetWindowTextLengthA>  ; \GetWindowTextLengthA
invoke GetWindowTextLength,edcode
;004011ED  |.  B9 00000000   MOV ECX,0                                ;  ecx=0 留意一下
mov ecx,0
;004011F2  |.  83F8 18       CMP EAX,18                               ;  注册码长度必须等于18h==24d
;004011F5  |.^ 0F85 20FFFFFF JNZ patched.0040111B
;004011FB  |.  40            INC EAX
;004011FC  |.  50            PUSH EAX                                 ; /Count
;004011FD  |.  68 0C314000   PUSH patched.0040310C                    ; |Buffer = patched.0040310C
;00401202  |.  68 EA030000   PUSH 3EA                                 ; |ControlID = 3EA (1002.)
;00401207  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
;0040120A  |.  E8 A9010000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
;0040120F  |.  B8 0C314000   MOV EAX,patched.0040310C
mov eax,offset wcrname
;00401214  |.  E8 D2000000   CALL patched.004012EB                    ;  把标准注册码的头3位改成KOS,并添加'-'符号
CALL wcr004012EB
;00401219  |.  B8 0C314000   MOV EAX,patched.0040310C
;0040121E  |.  83C0 04       ADD EAX,4
;00401221  |.  8038 2D       CMP BYTE PTR DS:[EAX],2D                 ;  第5位必须是-
;00401224  |.^ 0F85 F1FEFFFF JNZ patched.0040111B
;0040122A  |.  83C0 0A       ADD EAX,0A
;0040122D  |.  8038 2D       CMP BYTE PTR DS:[EAX],2D                 ;  第15位也是'-'哦
;00401230  |.^ 0F85 E5FEFFFF JNZ patched.0040111B
;00401236  |.  68 24324000   PUSH patched.00403224
;0040123B  |.  68 0C314000   PUSH patched.0040310C
;00401240  |.  E8 1F010000   CALL patched.00401364                    ;  字符串比较函数,若相等返回1
invoke lstrcpy,offset wcrcode,offset wcr00403224

;--------------------------------YOU'VE FINISHED!-----------------------------------
;---------------------Provide the rest work to the Template,OK?---------------------
                        invoke SetWindowText,edcode,offset wcrcode
                .elseif wParam==ID_BTQUIT
                        invoke PostMessage,hWin,WM_CLOSE,0,0
                .endif
        .else
                invoke DefWindowProc,hWin,uMsg,wParam,lParam
        .endif
        ret
WndProc endp

END START

下载全部: http://wiaa.blogbus.com/files/1152705799.rar
2006-7-12 20:06
0
雪    币: 249
活跃值: (10)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
3
多谢坛主、版主了!
2006-7-12 20:09
0
雪    币: 47147
活跃值: (20455)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
4
wiaa你现在有精华帖,己转正了,可以上传附件、用FTP(1小时后)等。
另外,将你的CrackMe转份本地。
上传的附件:
2006-7-12 20:10
0
雪    币: 249
活跃值: (10)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
5
thank you again
2006-7-12 20:11
0
雪    币: 97697
活跃值: (200834)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
6
sustain.
2006-7-12 21:05
0
雪    币: 194
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
高手 高手 高手啊  楼主真的厉害啊  还说自己是菜鸟, 如果是 那我不是连菜鸟都不是. 其实在看这篇破文之前 我已经向这个crackme开过刀了. 只是我没有看作者的提示 [是看不懂啊]  所以我只是爆破了一下. 还是想再说一句楼主真是高啊  非常支持
2006-7-13 07:17
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
不错,好好学习一下
2006-7-13 08:27
0
雪    币: 433
活跃值: (176)
能力值: ( LV13,RANK:1250 )
在线值:
发帖
回帖
粉丝
9
对这种汇编写的SDK程序应该做得更彻底一点,最好能重构出整个程序的源代码来。
2006-7-13 16:02
0
雪    币: 249
活跃值: (10)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
10
其实上面那个Keygen基本上就是整个源代码了(除了原本几个messagegbox,和窗体消息的简单处理,没有复制到Keygen中)

我是把源代码复制到keygen中修改而成,keygen注释是原本的代码,注释后的那一行是修改后的代码

多谢 冲天剑 的指导
2006-7-13 16:27
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
新手好好学习一下,支持!
2006-7-18 22:46
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
楼主是用什么反汇编的呀?OD?softice?还是dasm?
2006-7-18 23:19
0
雪    币: 249
活跃值: (10)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
13
OD + DASM
2006-7-20 10:45
0
游客
登录 | 注册 方可回帖
返回
//