OllyDBG 入門系列 消息斷點及 RUN 跟蹤

標 題: 【原創】OllyDBG 入門系列(五)-消息斷點及 RUN 跟蹤
作 者: CCDebuger
時 間: 2006-02-19,16:02:46
鏈 接: http://bbs.pediy.com/showthread.php?t=21532

OllyDBG 入門系列(五)-消息斷點及 RUN 跟蹤

作者:CCDebuger

找了幾十個不同語言編寫的 crackme,發現只用消息斷點的話有很多並不能真正到達我們要找的關鍵位置,想想還是把消息斷點和 RUN 跟蹤結合在一起講,更有效一點。關於消息斷點的更多內容大家可以參考 jingulong 兄的那篇《幾種典型程序Button處理代碼的定位》的文章,堪稱經典之作。今天仍然選擇 crackmes.cjb.net 鏡像打包中的一個名稱爲 cycle 的 crackme。按照慣例,我們先運行一下這個程序看看:
http://bbs.pediy.com/upload/2006/4/image/5_1.gif 
我們輸入用戶名 CCDebuger,序列號 78787878,點上面那個“Check”按鈕,呵, 沒反應!看來是要註冊碼正確纔有動靜。現在關掉這個 crackme,用 PEiD 查一下殼,原來是 MASM32 / TASM32 [Overlay]。啓動 OllyDBG 載入這個程序,F9讓它運行。這個程序按我們前面講的採用字串參考或函數參考的方法都很容易斷下來。但我們今天主要學習的是消息斷點及 RUN 跟蹤,就先用消息斷點來斷這個程序吧。在設消息斷點前,有兩個內容我們要簡單瞭解一下:首先我們要了解的是消息。Windows 的中文翻譯就是“窗口”,而 Windows 上面的應用程序也都是通過窗口來與用戶交互的。現在就有一個問題,應用程序是如何知道用戶作了什麼樣的操作的?這裏就要用到消息了。Windows 是個基於消息的系統,它在應用程序開始執行後,爲該程序創建一個“消息隊列”,用來存放該程序可能創建的各種不同窗口的信息。比如你創建窗口、點擊按鈕、移動鼠標等等,都是通過消息來完成的。通俗的說,Windows 就像一箇中間人,你要幹什麼事是先通知它,然後它才通過傳遞消息的方式通知應用程序作出相應的操作。說到這,又有個問題了,在 Windows 下有多個程序都在運行,那我點了某個按鈕,或把某個窗口最大化,Windows 知道我是點的哪個嗎?這裏就要說到另一個內容:句柄(handle)了。句柄一般是個 32 位的數,表示一個對象。Windows 通過使用句柄來標識它代表的對象。比如你點擊某個按鈕,Windows 就是通過句柄來判斷你是點擊了那一個按鈕,然後發送相應的消息通知程序。說完這些我們再回到我們調試的程序上來,你應該已經用 OllyDBG 把這個 crackme 載入並按 F9 鍵運行了吧?現在我們輸入用戶名“CCDebuger”,序列號“78787878”,先不要點那個“Check”按鈕,我們來到 OllyDBG 中,點擊菜單 查看->窗口(或者點擊工具欄上那個“W”的圖標),我們會看到以下內容:
http://bbs.pediy.com/upload/2006/4/image/5_2.gif 
我們在選中的條目上點右鍵,再選擇上圖所示的菜單項,會來到下面這個窗口:
http://bbs.pediy.com/upload/2006/4/image/5_3.gif 
現在我們點擊圖上的那個下拉菜單,呵,原來裏面的消息真不少。這麼多消息我們選哪個呢?註冊是個按鈕,我們就在按下按鈕再鬆開時讓程序中斷。查一下 MSDN,我們知道這個消息應該是 WM_LBUTTON_UP,看字面意思也可以知道是左鍵鬆開時的消息:
http://bbs.pediy.com/upload/2006/4/image/5_4.gif 
從下拉菜單中選中那個 202 WM_LBUTTON_UP,再按確定按鈕,我們的消息斷點就設好了。現在我們還要做一件事,就是把 RUN 跟蹤打開。有人可能要問,這個 RUN 跟蹤是幹什麼的?簡單的說,RUN 跟蹤就是把被調試程序執行過的指令保存下來,讓你可以查看被調試程序運行期間幹了哪些事。RUN 跟蹤會把地址、寄存器的內容、消息以及已知的操作數記錄到 RUN 跟蹤緩衝區中,你可以通過查看 RUN 跟蹤的記錄來了解程序執行了那些指令。在這還要注意一個緩衝區大小的問題,如果執行的指令太多,緩衝區滿了的話,就會自動丟棄前面老的記錄。我們可以在調試選項->跟蹤中設置:
http://bbs.pediy.com/upload/2006/4/image/5_5.gif 
現在我們回到 OllyDBG 中,點擊菜單調試->打開或清除 RUN 跟蹤(第一次點這個菜單是打開 RUN 跟蹤,在打開的情況下點擊就是清除 RUN 跟蹤的記錄,對 RUN 跟蹤熟悉時還可以設置條件),保證當前在我們調試的程序領空,在反彙編窗口中點擊右鍵,在彈出菜單中選擇 RUN 跟蹤->添加所有函數過程的入口:
http://bbs.pediy.com/upload/2006/4/image/5_7.gif 
我們可以看到 OllyDBG 把識別出的函數過程都在前面加了灰色條:
http://bbs.pediy.com/upload/2006/4/image/5_8.gif 
現在我們回到那個 crackme 中按那個“Check”按鈕,被 OllyDBG 斷下了:
http://bbs.pediy.com/upload/2006/4/image/5_6.gif 
這時我們點擊菜單查看->內存,或者點擊工具欄上那個“M”按鈕(也可以按組合鍵 ALT+M),來到內存映射窗口:
http://bbs.pediy.com/upload/2006/4/image/5_9.gif 
爲什麼在這裏設訪問斷點,我也說一下。我們可以看一下常見的 PE 文件,沒加過殼的用 PEiD 檢測是這樣:
http://bbs.pediy.com/upload/2006/4/image/5_10.gif 
點一下 EP 段後面那個“>”符號,我們可以看到以下內容:
http://bbs.pediy.com/upload/2006/4/image/5_11.gif 
看完上面的圖我們應該瞭解爲什麼在 401000 處的代碼段下訪問斷點了,我們這裏的意思就是在消息斷點斷下後,只要按 F9 鍵運行時執行到程序代碼段的指令我們就中斷,這樣就可以回到程序領空了(當然在 401000 處所在的段不是絕對的,我們主要是要看程序的代碼段在什麼位置,其實在上面圖中 OllyDBG 內存窗口的“包含”欄中我們就可以看得很清楚了)。設好訪問斷點後我們按 F9 鍵,被 OllyDBG 斷下:
http://bbs.pediy.com/upload/2006/4/image/5_12.gif
現在我們先不管,按 F9 鍵(或者按 CTR+F12 組合鍵跟蹤步過)讓程序運行,再點擊菜單查看->RUN 跟蹤,或者點擊工具欄上的那個“…”符號,打開 RUN 跟蹤的記錄窗口看看:
http://bbs.pediy.com/upload/2006/4/image/5_13.gif 
我們現在再來看看統計的情況:
http://bbs.pediy.com/upload/2006/4/image/5_14.gif 
在地址 401082 處的那條指令上雙擊一下,來到以下位置:
http://bbs.pediy.com/upload/2006/4/image/5_15.gif 
現在我們在地址 4010A6 處的那條指令上按 F2,刪除所有其它的斷點,點菜單調試->關閉 RUN 跟蹤,現在我們就可以開始分析了:

004010E2 |. 8BFE             MOV EDI,ESI                                         ; 用戶名送 EDI
004010E4 |. 03F8             ADD EDI,EAX
004010E6 |. FC               CLD
004010E7 |. F3:A4            REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
004010E9 |. 33C9             XOR ECX,ECX                                         ; 清零,設循環計數器
004010EB |. BE 71214000      MOV ESI,cycle.00402171                              ; 註冊碼送ESI
004010F0 |> 41               INC ECX
004010F1 |. AC               LODS BYTE PTR DS:[ESI]                              ; 取註冊碼的每個字符
004010F2 |. 0AC0             OR AL,AL                                            ; 判斷是否爲空
004010F4 |. 74 0A            JE SHORT cycle.00401100                             ; 沒有則跳走
004010F6 |. 3C 7E            CMP AL,7E                                           ; 判斷字符是否爲非ASCII字符
004010F8 |. 7F 06            JG SHORT cycle.00401100                             ; 非ASCII字符跳走
004010FA |. 3C 30            CMP AL,30                                           ; 看是否小於30H,主要是判斷是不是數字或字母等
004010FC |. 72 02            JB SHORT cycle.00401100                             ; 小於跳走
004010FE |.^ EB F0           JMP SHORT cycle.004010F0
00401100 |> 83F9 11          CMP ECX,11                                          ; 比較註冊碼位數,必須爲十進制17位
00401103 |. 75 1A            JNZ SHORT cycle.0040111F
00401105 |. E8 E7000000      CALL cycle.004011F1                                 ; 關鍵,F7跟進去
0040110A |. B9 01FF0000      MOV ECX,0FF01
0040110F |. 51               PUSH ECX
00401110 |. E8 7B000000      CALL cycle.00401190                                 ; 關鍵,跟進去
00401115 |. 83F9 01          CMP ECX,1
00401118 |. 74 06            JE SHORT cycle.00401120
0040111A |> E8 47000000      CALL cycle.00401166                                 ; 註冊失敗對話框
0040111F |> C3               RETN
00401120 |> A1 68214000      MOV EAX,DWORD PTR DS:[402168]
00401125 |. 8B1D 6C214000    MOV EBX,DWORD PTR DS:[40216C]
0040112B |. 33C3             XOR EAX,EBX
0040112D |. 3305 82214000    XOR EAX,DWORD PTR DS:[402182]
00401133 |. 0D 40404040      OR EAX,40404040
00401138 |. 25 77777777      AND EAX,77777777
0040113D |. 3305 79214000    XOR EAX,DWORD PTR DS:[402179]
00401143 |. 3305 7D214000    XOR EAX,DWORD PTR DS:[40217D]
00401149 |.^ 75 CF           JNZ SHORT cycle.0040111A                             ; 這裏跳走就完蛋
0040114B |. E8 2B000000      CALL cycle.0040117B                                  ; 註冊成功對話框

寫到這準備跟蹤算法時,才發現這個 crackme 還是挺複雜的,具體算法我就不寫了,實在沒那麼多時間詳細跟蹤。有興趣的可以跟一下,註冊碼是17位,用戶名採用複製的方式擴展到 16 位,如我輸入“CCDebuger”,擴展後就是“CCDebugerCCDebug”。大致是先取擴展後用戶名的前 8 位和註冊碼的前 8 位,把用戶名的前四位和後四位分別與註冊碼的前四位和後四位進行運算,算完後再把擴展後用戶名的後 8 位和註冊碼的後 8 位分兩部分,再與前面用戶名和註冊碼的前 8 位計算後的值進行異或計算,最後結果等於 0 就成功。註冊碼的第 17 位我尚未發現有何用處。對於新手來說,可能這個 crackme 的難度大了一點。沒關係,我們主要是學習 OllyDBG 的使用,方法掌握就可以了。

最後說明一下:
1、這個程序在設置了消息斷點後可以省略在代碼段上設訪問斷點那一步,直接打開 RUN 跟蹤,消息斷點斷下後按 CTR+F12 組合鍵讓程序執行,RUN 跟蹤記錄中就可以找到關鍵地方。
2、對於這個程序,你可以不設消息斷點,在輸入用戶名和註冊碼後先不按那個“Check”按鈕,直接打開 RUN 跟蹤,添加“所有函數過程的入口”後再回到程序中點“Check”按鈕,這時在 OllyDBG 中打開 RUN 跟蹤記錄同樣可以找到關鍵位置。


【版權聲明】 本文純屬技術交流, 轉載請註明作者並保持文章的完整, 謝謝! 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章