1. 程式人生 > >一個簡單的linux crackme的逆向

一個簡單的linux crackme的逆向

前言

    最不喜歡的就是寫破解教程,酒後一時衝動,老夫卿發少年狂,許下將寫一篇linux平臺逆向的文章的諾言,作此文實非頗不得已。
    在此申明:本文在技術上非常初級,並沒有用到什麼高深的技術,本人水平亦有限,如有差錯,還請見諒!
    
開始之前的準備

    正如C語言教程從 hello world 開始,我們也由一個 crackme 說開去。本文的例子程式你可以到這來下載:
http://www.crackmes.de/users/veneta/crackmes/linux_crackme_v2 。古人云“工欲善其事,必先利其器”,本文中所用到的工具及操作平臺羅列如下:
  操作平臺: gentoo 2004.3 #  kernel 2.6.9
  逆向工具: 
    反彙編 -- objdump (這個工具基本上每個LINUX上都有)、lida( http://lida.sourceforge.net/ )
    偵錯程式 -- gdb
    十六進位制編輯器 -- hexedit
    文字編輯器 -- vim
    壓縮工具 -- upx  (http://upx.sourceforge.net)
    計算器 -- gcalctool(gnome計算器)
    
開始逆向之旅


首先我們看看程式基本資訊:
    開啟控制檯,切換到程式所在目錄。執行“ objdump -x cm2 ”,顯示如下:
程式碼:
    
[[email protected]]$ objdump -x cm2

cm2:     file format elf32-i386
cm2
architecture: i386, flags 0x00000102:
EXEC_P, D_PAGED
start address 0x08048080

程式頭:
    LOAD off    0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
         filesz 0x000005b8 memsz 0x000005b8 flags r-x
    LOAD off    0x000005b8 vaddr 0x080495b8 paddr 0x080495b8 align 2**12
         filesz 0x0000002c memsz 0x0000002c flags rw-

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
SYMBOL TABLE:
no symbols
  
    我們可以看到start address是0x08048080,但有一個問題是Sections下面卻什麼都沒有。這不是一個正常的程式?
    
    接下來,使用十六進位制工具 hexedit 檢視程式資訊。執行命令:hexedit cm2 ,顯示如下:
程式碼:
00000000   7F 45 4C 46  01 01 01 00  4C 69 6E 75  78 00 00 00  .ELF....Linux...

00000010   02 00 03 00  01 00 00 00  80 80 04 08  34 00 00 00  ............4...

00000020   00 00 00 00  00 00 00 00  34 00 20 00  02 00 00 00  ........4. .....

00000030   00 00 00 00  01 00 00 00  00 00 00 00  00 80 04 08  ................

00000040   00 80 04 08  B8 05 00 00  B8 05 00 00  05 00 00 00  ................

00000050   00 10 00 00  01 00 00 00  B8 05 00 00  B8 95 04 08  ................

00000060   B8 95 04 08  2C 00 00 00  2C 00 00 00  06 00 00 00  ....,...,.......

00000070   00 10 00 00  77 6C EA 93  7F 55 50 58  E4 05 0B 0A  ....wl...UPX....

00000080   31 ED 58 89  E1 8D 54 81  04 50 83 E4  F8 52 51 E8  1.X...T..P...RQ.

00000090   FE 01 00 00  F4 0A 00 24  49 6E 66 6F  3A 20 54 68  .......$Info: Th

000000A0   69 73 20 66  69 6C 65 20  69 73 20 70  61 63 6B 65  is file is packe

000000B0   64 20 77 69  74 68 20 74  68 65 20 55  50 58 20 65  d with the UPX e

000000C0   78 65 63 75  74 61 62 6C  65 20 70 61  63 6B 65 72  xecutable packer

000000D0   20 68 74 74  70 3A 2F 2F  75 70 78 2E  73 66 2E 6E   http://upx.sf.n

000000E0   65 74 20 24  0A 00 24 49  64 3A 20 55  50 58 20 31  et $..$Id: UPX 1

000000F0   2E 32 34 20  43 6F 70 79  72 69 67 68  74 20 28 43  .24 Copyright (C

00000100   29 20 31 39  39 36 2D 32  30 30 32 20  74 68 65 20  ) 1996-2002 the

00000110   55 50 58 20  54 65 61 6D  2E 20 41 6C  6C 20 52 69  UPX Team. All Ri

00000120   67 68 74 73  20 52 65 73  65 72 76 65  64 2E 20 24  ghts Reserved. 
$
    從上面的資訊中可以看到程式被UPX壓縮了,接下來請確信你係統中已有UPX,如果沒有請到上面給出的程式連結中下載。
    執行命令“ upx -d cm2 ”把程式解壓縮,顯示如下:
程式碼:
[[email protected] crack]$ upx -d cm2
                     Ultimate Packer for eXecutables
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
UPX 1.25         Markus F.X.J. Oberhumer & Laszlo Molnar        Jun 29th 2004

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
     10584 <-      4870   46.01%    linux/386    cm2

Unpacked 1 file.
    接下來,我們再使用命令“ objdump -x cm2 ”來檢視程式資訊。如下:
程式碼:
[[email protected] crack]$ objdump -x cm2

cm2:     file format elf32-i386
cm2
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080488b0

程式頭:
    PHDR off    0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2
         filesz 0x000000c0 memsz 0x000000c0 flags r-x
  INTERP off    0x000000f4 vaddr 0x080480f4 paddr 0x080480f4 align 2**0
         filesz 0x00000013 memsz 0x00000013 flags r--
    LOAD off    0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
         filesz 0x0000109c memsz 0x0000109c flags r-x
    LOAD off    0x00002000 vaddr 0x0804a000 paddr 0x0804a000 align 2**12
         filesz 0x00000398 memsz 0x00000ff0 flags rw-
 DYNAMIC off    0x00002248 vaddr 0x0804a248 paddr 0x0804a248 align 2**2
         filesz 0x000000e0 memsz 0x000000e0 flags rw-
    NOTE off    0x00000108 vaddr 0x08048108 paddr 0x08048108 align 2**2
         filesz 0x00000020 memsz 0x00000020 flags r--

動態節:
  NEEDED      libgtk-1.2.so.0
  NEEDED      libgdk-1.2.so.0
  NEEDED      libglib-1.2.so.0
  NEEDED      libc.so.6
  INIT        0x8048758
  FINI        0x8049074
  HASH        0x8048128
  STRTAB      0x804841c
  SYMTAB      0x80481fc
  STRSZ       0x225
  SYMENT      0x10
  DEBUG       0x0
  PLTGOT      0x804a33c
  PLTRELSZ    0x98
  PLTREL      0x11
  JMPREL      0x80486c0
  REL         0x80486b8
  RELSZ       0x8
  RELENT      0x8
  VERNEED     0x8048688
  VERNEEDNUM  0x1
  VERSYM      0x8048642

版本引用:
  required from libc.so.6:
    0x0d696911 0x00 03 GLIBC_2.1
    0x0d696910 0x00 02 GLIBC_2.0

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .interp       00000013  080480f4  080480f4  000000f4  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  08048108  08048108  00000108  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .hash         000000d4  08048128  08048128  00000128  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .dynsym       00000220  080481fc  080481fc  000001fc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynstr       00000225  0804841c  0804841c  0000041c  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .gnu.version  00000044  08048642  08048642  00000642  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version_r 00000030  08048688  08048688  00000688  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .rel.dyn      00000008  080486b8  080486b8  000006b8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rel.plt      00000098  080486c0  080486c0  000006c0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .init         00000017  08048758  08048758  00000758  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 10 .plt          00000140  08048770  08048770  00000770  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .text         000007c4  080488b0  080488b0  000008b0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .fini         0000001b  08049074  08049074  00001074  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .rodata       00000008  08049090  08049090  00001090  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 14 .eh_frame     00000004  08049098  08049098  00001098  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 15 .data         00000248  0804a000  0804a000  00002000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 16 .dynamic      000000e0  0804a248  0804a248  00002248  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 17 .ctors        00000008  0804a328  0804a328  00002328  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 18 .dtors        00000008  0804a330  0804a330  00002330  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 19 .jcr          00000004  0804a338  0804a338  00002338  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 20 .got          0000005c  0804a33c  0804a33c  0000233c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 21 .bss          00000c58  0804a398  0804a398  00002398  2**2
                  ALLOC
 22 .comment      00000119  00000000  00000000  00002398  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
no symbols
    從上面的資訊中可以看出,程式使用gtk編寫,程式入口start address=0x080488b0。
    我們再進一步的檢視程式資訊,執行命令“objdump -T cm2 >iat.txt”,下面的資訊將會儲存到iat.txt檔案中。
    
程式碼:
[[email protected] crack]$ objdump -T cm2

cm2:     file format elf32-i386

DYNAMIC SYMBOL TABLE:
00000000      DF *UND*  0000013d              gtk_widget_show
0804a248 g    DO *ABS*  00000000  Base        _DYNAMIC
08048780      DF *UND*  000000e4              gtk_widget_show_all
00000000      DF *UND*  00000027              gtk_dialog_new
08048790      DF *UND*  000001db              gtk_container_add
08048758 g    DF .init  00000000  Base        _init
080487a0      DF *UND*  000000d1              gtk_window_set_default_size
080487b0      DF *UND*  00000056              gtk_label_new
080487c0      DF *UND*  00000085              gtk_window_new
080487d0      DF *UND*  00000213              gtk_widget_set_uposition
080487e0      DF *UND*  0000010d              gtk_window_set_title
080487f0      DF *UND*  0000010c              gtk_entry_get_text
08048800      DF *UND*  00000242              gtk_box_pack_start
08048810      DF *UND*  00000067              gtk_init
08048820      DF *UND*  0000010d              g_print
08048830      DF *UND*  0000007c              gtk_main_quit
08048840      DF *UND*  000001d3              gtk_main
0804a398 g    D  *ABS*  00000000  Base        __bss_start
08048850      DF *UND*  000000e0  GLIBC_2.0   __libc_start_main
08049074 g    DF .fini  00000000  Base        _fini
08048860      DF *UND*  000000c7  GLIBC_2.0   exit
0804a398 g    D  *ABS*  00000000  Base        _edata
0804a33c g    DO *ABS*  00000000  Base        _GLOBAL_OFFSET_TABLE_
0804aff0 g    D  *ABS*  00000000  Base        _end
00000000      DF *UND*  00000028  GLIBC_2.1   fopen
08049094 g    DO .rodata        00000004  Base        _IO_stdin_used
00000000      DF *UND*  0000012e  GLIBC_2.0   fwrite
08048870      DF *UND*  00000027              gtk_entry_new
00000000  w   D  *UND*  00000000              _Jv_RegisterClasses
08048880      DF *UND*  00000157              gtk_signal_connect
08048890      DF *UND*  0000006d              gtk_button_new_with_label
080488a0      DF *UND*  00000044              gtk_vbox_new
00000000  w   D  *UND*  00000000              __gmon_start__
    我們再一次執行命令“objdump -d cm2 >disasm.txt”,對程式進行反彙編,並把結果儲存到disasm.txt中。
接下來,用VI開啟disasm.txt檔案。顯示如下:
http://bbs.pediy.com/upload/2005/4/image/disasm.jpg
    
相對WINDOW平臺的反彙編器,objdump 的反彙編結果在沒有除錯符號的情況下,不顯示API的名字。下一步API呼叫手工的加上。
我們開啟iat.txt檔案,把disasm.txt檔案中的地址全部轉換成函式名,例如:
程式碼:
 8048979:       68 00 00 00 00          push   $0x0
 804897e:       68 03 00 00 00          push   $0x3
 8048983:       e8 88 fe ff ff          call   0x8048810
轉換成

http://bbs.pediy.com/upload/2005/4/image/vidisasm.jpg
這樣將好看多了。這一點你可以寫個指令碼自動完成,而不用手工一個一個的替換。或者你也可以使用更強大的反彙編工器lida來自動顯示API呼叫名。為了方便初學者,下面使用LIDA來作為反彙編工具。用lida 載入程式,如下圖:

    好了,前期的工作都做了。下面讓我們來執行一下程式,看看有沒有什麼值得參考的。執行後,出現一個視窗。如下:
http://bbs.pediy.com/upload/2005/4/image/killme.jpg 
    如圖,提示我們的CRACK任務之一就是NOP掉這個視窗。點選關閉按鈕,出現第二個視窗,如下圖
http://bbs.pediy.com/upload/2005/4/image/crackme.jpg
    這是註冊的主視窗。
    對照LIDA中的反彙編程式碼加上GTK的一些基本知識,我們可以知道程式執行過程是這樣的:main->跳出killme視窗->註冊destroy事件處理函式->在關閉 killme 視窗時將引發destroy事件->執行回撥處理函式0x80489bd->跳出crackme視窗。
    我們CRACK的任務就是nop掉killme視窗,以及找出註冊碼。
    注:GTK的相關文件你可以到這來獲取 http://www.gtk.org/tutorial/


第一個任務:去除killme視窗。
    用lida反彙編cm2,點選選單 view -> Functions 找到main函式,點選進入,如下所示:
程式碼:
main():
08048970  55                                   push      ebp 
08048971  89 E5                                mov      ebp, esp 
08048973  81 EC 08 00 00 00                    sub      esp, 0x8 
08048979  68 00 00 00 00                       push      0x0 
0804897E  68 03 00 00 00                       push      0x3 
08048983  E8 88 FE FF FF                       call      gtk_init (08048810) ; (near - 0x178)
08048988  90                                   nop  -\
08048989  90                                   nop    \
0804898A  90                                   nop     |->怎麼會有nop指令出現?
0804898B  90                                   nop    /   我們在這加入call Function___080489BD
0804898C  90                                   nop  -/    直接顯示crackme視窗,跳過killme視窗的呼叫。因為在
0804898D  BE D2 A0 04 08                       mov      esi, " Kill this window (p" (0804A0D2)
08048992  E8 5C 04 00 00                       call      Function___08048DF3 (08048DF3) ; 建立killme視窗
08048997  68 00 00 00 00                       push      0x0 
0804899C  68 BD 89 04 08                       push      Function___080489BD (80489BD)  ; 回撥函式,顯示crackme視窗
080489A1  68 28 A2 04 08                       push      "destroy" (0804A228)
080489A6  FF 35 A0 A3 04 08                    push      0804A3A0 
080489AC  E8 CF FE FF FF                       call      gtk_signal_connect (08048880) ; 建立destroy事件回撥函式0x080489BD
080489B1  81 C4 10 00 00 00                    add      esp, 0x10 
080489B7  E8 84 FE FF FF                       call      gtk_main (08048840) ; 顯示killme視窗
080489BC  C3                                   ret
    我們跟入Function___08048DF3函式,如下:
程式碼:
Function___08048DF3:
08048DF3  55                                   push      ebp  ; xref ( 08048992 08048C9A 08048CA6 08048DAC )
08048DF4  89 E5                                mov      ebp, esp 
08048DF6  81 EC 08 00 00 00                    sub      esp, 0x8 
08048DFC  68 01 00 00 00                       push      0x1 
08048E01  E8 BA F9 FF FF                       call      gtk_window_new (080487C0) ; (near - 0x646)
08048E06  A3 A0 A3 04 08                       mov      0x0804A3A0, eax 
08048E0B  68 2C A0 04 08                       push      "CrackMe v13 (2 linux" (0804A02C)
08048E10  FF 35 A0 A3 04 08                    push      0804A3A0 
08048E16  E8 C5 F9 FF FF                       call      gtk_window_set_title (080487E0) ; (near - 0x63B)
08048E1B  56                                   push      esi 
08048E1C  E8 8F F9 FF FF                       call      gtk_label_new (080487B0) ; (near - 0x671)
08048E21  50                                   push      eax 
08048E22  FF 35 A0 A3 04 08                    push      0804A3A0 
08048E28  E8 63 F9 FF FF                       call      gtk_container_add (08048790) ; (near - 0x69D)
08048E2D  68 64 00 00 00                       push      0x64 
08048E32  68 2C 01 00 00                       push      0x12C 
08048E37  FF 35 A0 A3 04 08                    push      0804A3A0 
08048E3D  E8 5E F9 FF FF                       call      gtk_window_set_default_size (080487A0) ; (near - 0x6A2)
08048E42  FF 35 A0 A3 04 08                    push      0804A3A0 
08048E48  E8 33 F9 FF FF                       call      gtk_widget_show_all (08048780) ; (near - 0x6CD)
08048E4D  C9                                   leave   
08048E4E  C3                                   ret   
    上面這個函式建立killme視窗。
    為了去除這個killme視窗。我們可以在 程式碼:
08048988  90                                   nop  -\
08048989  90                                   nop    \
0804898A  90                                   nop     |->怎麼會有nop指令出現?
0804898B  90                                   nop    /   我們在這加入call Function___080489BD
0804898C  90                                   nop  -/    直接顯示crackme視窗,跳過killme視窗的呼叫。
0804898D  BE D2 A0 04 08                       mov      esi, " Kill this window (p" (0804A0D2)
08048992  E8 5C 04 00 00                       call      Function___08048DF3 (08048DF3)
    上面的nop正好5個,我懷疑作者寫crackme在這有一個對crackme函式的呼叫,生成程式後,他手工把這個程式碼NOP掉了,他是故意留出空間來做提示。因為在crackme 視窗函式中有完整的視窗初始化和退出處理,如下:
程式碼:
08048C22  68 3D A2 04 08                       push      "clicked" (0804A23D)
08048C27  FF 35 AC A3 04 08                    push      0804A3AC 
08048C2D  E8 4E FC FF FF                       call      gtk_signal_connect (08048880) ; (near - 0x3B2)
08048C32  81 C4 10 00 00 00                    add      esp, 0x10 
08048C38  E8 03 FC FF FF                       call      gtk_main (08048840) ; (near - 0x3FD)
08048C3D  68 2C A0 04 08                       push      "CrackMe v13 (2 linux" (0804A02C)
08048C42  E8 D9 FB FF FF                       call      g_print (08048820) ; (near - 0x427)
08048C47  81 C4 04 00 00 00                    add      esp, 0x4 
08048C4D  68 00 00 00 00                       push      0x0 
08048C52  E8 09 FC FF FF                       call      exit (08048860) ; 當點選crackme視窗上的quit按鈕後程序直接退出

Function___08048C57:
08048C57  55                                   push      ebp 
08048C58  89 E5                                mov      ebp, esp 
08048C5A  81 EC 08 00 00 00                    sub      esp, 0x8 
08048C60  E8 17 00 00 00                       call      Function___08048C7C (08048C7C) ; (near + 0x17)
08048C65  B8 00 00 00 00                       mov      eax, 0x0 
08048C6A  C9                                   leave   
08048C6B  C3                                   ret  
    從上面的程式碼可以看到,如果先呼叫crackme 視窗的函式,那麼 killme 視窗就不會出現了。
    好的,下面我們就改08048988處的指令為 call    080489BD ,用計算器算一下:80489BD-08048988-5=00000030,得到程式碼為 e8 30 00 00 00 。嘿嘿!
    好的,用hexedit 開啟 cm2 程式。看看前面objdump -x cm2列出的基地址為0x8048000,所以對應的file offset應該是0x8048988-0x8048000=0x988,我們按 return 鍵,開啟 go to 視窗,輸入 0x988 ,定位到08048988處,改程式碼為e830000000。改完後,“ ./cm2 ”執行程式,OK。出現 crackme 視窗了。

第二個任務,找出正確的註冊碼。
為保持本文一個苗條的身材及加大本文所包含的資訊量,我就不講怎麼根據按鈕名找對應的點選事件處理函數了,講一種簡單省事的方法,找註冊碼最省事的方法當然是動態跟蹤啦。搞不好還可以看到明碼喲。費話不多說,執行命令: gdb cm2  。提示沒有符號檔案,不用管它。
下斷點:
程式碼:
br gtk_entry_get_text 注(類似於WIN平臺下的 getdlgitemtexta )
再鍵入命令 “ run ”執行程式。出現了介面。
輸入名字和註冊碼,我這用的是:
名字:ncc2008
註冊碼:78787878
按crackme按鈕,中斷到gdb中。 
程式碼:
Breakpoint 1, 0x40096eb0 in gtk_entry_get_text () from /usr/lib/libgtk-1.2.so.0
讓我們看看是哪個CALL呼叫的,下命令"info frame",顯示如下:
程式碼:
(gdb) info frame
Stack level 0, frame at 0xbfffe250:
 eip = 0x40096eb0 in gtk_entry_get_text; saved eip 0x8048cc1  ;從這CALL來的
 called by frame at 0xbfffe254
 Arglist at 0xbfffe248, args:
 Locals at 0xbfffe248, Previous frame's sp is 0xbfffe250
 Saved registers:
  eip at 0xbfffe24c
呵呵,清除全部斷點,下命令“d”。在0x8048cc1下一個斷點:
程式碼:
br *0x8048cc1
,然後鍵“C”繼續執行程式。
程式中斷到我們所下的斷點0x8048cc1處。讓我們看看彙編程式碼:
下命令:x /10i $eip
顯示如下:
程式碼:
(gdb) x /10i $eip
0x8048cc1:      mov    %eax,%edx
0x8048cc3:      call   0x8048fc5
0x8048cc8:      cmp    $0x20,%eax
0x8048ccd:      jne    0x8048ca1
0x8048ccf:      mov    %edx,0x804a3e8
0x8048cd5:      call   0x8048f50
0x8048cda:      pushl  0x804a3c0
0x8048ce0:      call   0x80487f0
0x8048ce5:      mov    %eax,%edx
0x8048ce7:      call   0x8048fc5
看不懂?我們再看lida 中的 0x8048cc1處的程式碼。

程式碼:
Function___08048CAD:
08048CAD  55                                   push      ebp 
08048CAE  89 E5                                mov      ebp, esp 
08048CB0  81 EC 08 00 00 00                    sub      esp, 0x8 
08048CB6  FF 35 C4 A3 04 08                    push      0804A3C4 
08048CBC  E8 2F FB FF FF                       call      gtk_entry_get_text (080487F0) ; (near - 0x4D1)
08048CC1  89 C2                                mov      edx, eax 
08048CC3  E8 FD 02 00 00                       call      Function___08048FC5 (08048FC5) ; 註冊碼長
08048CC8  3D 20 00 00 00                       cmp      eax, 0x20 
08048CCD  75 D2                                jnz      Label_08048CA1 (08048CA1) ; 註冊碼必需是32個字元
08048CCF  89 15 E8 A3 04 08                    mov      0804A3E8, edx 
08048CD5  E8 76 02 00 00                       call      Function___08048F50 (08048F50) ; a2i,字串到 hex轉換
08048CDA  FF 35 C0 A3 04 08                    push      0804A3C0 
08048CE0  E8 0B FB FF FF                       call      gtk_entry_get_text (080487F0) ; (near - 0x4F5)
08048CE5  89 C2                                mov      edx, eax 
08048CE7  E8 D9 02 00 00                       call      Function___08048FC5 (08048FC5) ; (near + 0x2D9)
08048CEC  BE F0 A7 04 08                       mov      esi, 0x804A7F0 
08048CF1  50                                   push      eax 
08048CF2  3D 03 00 00 00                       cmp      eax, 0x3 
08048CF7  72 A8                                jc      Label_08048CA1 (08048CA1) ; 使用者名稱必需大於3個字元
08048CF9  89 C1                                mov      ecx, eax 
08048CFB  8A 02                                mov      al, [edx]  ; xref ( 08048D01 )
08048CFD  88 06                                mov      [esi], al 
08048CFF  42                                   inc      edx 
08048D00  46                                   inc      esi 
08048D01  E2 F8                                loop      08048CFB ; (near  0xF8)
08048D03  C7 05 C8 A3 04 08 10 A2 04 08        mov      0804A3C8, "MBECrew" (0804A210)
08048D0D  C7 05 CC A3 04 08 07 00 00 00        mov      0804A3CC, 0x7 
08048D17  E8 33 01 00 00                       call      Function___08048E4F (08048E4F) ; (near + 0x133)
08048D1C  C7 05 D0 A3 04 08 F0 A3 04 08        mov      0804A3D0, 0x804A3F0 
08048D26  C7 05 D4 A3 04 08 10 00 00 00        mov      0804A3D4, 0x10 
08048D30  E8 87 01 00 00                       call      Function___08048EBC (08048EBC) ; 註冊碼每位元組與F0相異或
08048D35  C7 05 C8 A3 04 08 10 A2 04 08        mov      0804A3C8, "MBECrew" (0804A210)
08048D3F  C7 05 CC A3 04 08 07 00 00 00        mov      0804A3CC, 0x7 
08048D49  E8 01 01 00 00                       call      Function___08048E4F (08048E4F) ; (near + 0x101)
08048D4E  58                                   pop      eax 
08048D4F  C7 05 D0 A3 04 08 F0 A7 04 08        mov      0804A3D0, 0x804A7F0 
08048D59  A3 D4 A3 04 08                       mov      0x0804A3D4, eax 
08048D5E  E8 59 01 00 00                       call      Function___08048EBC (08048EBC) ; (near + 0x159)
08048D63  BE F0 A3 04 08                       mov      esi, 0x804A3F0 
08048D68  BA F0 A7 04 08                       mov      edx, 0x804A7F0 
08048D6D  B9 10 00 00 00                       mov      ecx, 0x10 

Label_08048D72:
08048D72  8A 02                                mov      al, [edx]  ; xref ( 08048D7C 08048DB8 )
08048D74  3C 00                                cmp      al, 0x0 
08048D76  74 3B                                jz      Label_08048DB3 (08048DB3) ; (near + 0x3B)
08048D78  04 0A                                add      al, 0xA 
08048D7A  30 06                                xor      [esi], al 
08048D7C  E2 F4                                loop      Label_08048D72 (08048D72) ; (near  0xF4)
08048D7E  BA 18 A2 04 08                       mov      edx, 0x804A218 
08048D83  BE F0 A3 04 08                       mov      esi, 0x804A3F0 
08048D88  B9 04 00 00 00                       mov      ecx, 0x4 
08048D8D  8B 02                                mov      eax, [edx]  ; xref ( 08048DA5 )
08048D8F  33 06                                xor      eax, [esi]  ; 下斷點在這
08048D91  85 C0                                test      eax, eax 
08048D93  0F 85 08 FF FF FF                    jnz      Label_08048CA1 (08048CA1) ; 跳就死定了
08048D99  81 C2 04 00 00 00                    add      edx, 0x4 
08048D9F  81 C6 04 00 00 00                    add      esi, 0x4 
08048DA5  E2 E6                                loop      08048D8D ; (near  0xE6)
08048DA7  BE 8F A0 04 08                       mov      esi, " cracked ohh yeah !!" (0804A08F)
08048DAC  E8 42 00 00 00                       call      Function___08048DF3 (08048DF3) ; (near + 0x42)
08048DB1  C9                                   leave   
08048DB2  C3                                   ret   

Label_08048DB3:
08048DB3  BA F0 A7 04 08                       mov      edx, 0x804A7F0  ; xref ( 08048D76 )
08048DB8  EB B8                                jmp      Label_08048D72 (08048D72) ; (near  0xB8)
     
接下來,我們就一步一步跟吧!整個過程單調無趣,不多說了。註冊碼必需是32位,我使用“12345678abcdef0123456789abcdef0”
跟蹤其流程:
轉換註冊碼“12345678abcdef0123456789abcdef0”為:
程式碼:
0x804a3f0:      0x12    0x34    0x56    0x78    0x9a    0xbc    0xde    0xf0
0x804a3f8:      0x12    0x34    0x56    0x78    0x9a    0xbc    0xde    0xf0
然後每一位元組與"0xf0"相異或,生成:
程式碼:
0x804a3f0:      0xe2    0xc4    0xa6    0x88    0x6a    0x4c    0x2e    0x00
0x804a3f8:      0xe2    0xc4    0xa6    0x88    0x6a    0x4c    0x2e    0x00
我們在08048D8F下個斷點,中斷後可以看到正確的值,edx中的值為:
程式碼:
(gdb) x /20xb $edx
0x804a218:      0xc4    0x84    0x0b    0xb5    0xa1    0x02    0x0d    0x97
0x804a220:      0x5c    0xb2    0xe1    0xc9    0xa4    0x91    0x52    0xcc
0x804a218處的值與0x804a3f0處的值相比較,相等就註冊成功。結合前面註冊碼的變換,可以把上面的每位元組與F0異或就是正確的註冊碼了,掏出計算器,計算如下:
程式碼:
3474fb4551f2fd67ac4211395461a23c
註冊碼與名字無關,名字可隨便寫,在程式中輸入上面的註冊碼,成功!
http://bbs.pediy.com/upload/2005/4/image/crack.jpg
補丁和註冊機程式碼就不發作者了,古得白