1. 程式人生 > >序列號型CrackMe逆向之IDA技巧篇

序列號型CrackMe逆向之IDA技巧篇

    前面我們探討了用OD來定位驗證邏輯位置,現在我們來探討下如何使用IDA來定位驗證邏輯位置~

控制元件ID搜尋法

    如果一個windows程式使用了rc資源(把程式往Resrouce Hacker一拖,能看到對話方塊之類的資源的說明就使用了rc資源),並且控制元件的ID比較特殊的,就是搜尋不容易出現大量重複指令的ID,就可以使用搜索立即數的方式定位對應驗證邏輯,方法如下(這邊使用crackme.chm的figugegl.1.exe作為演示用例)~

    將程式載入IDA,然後搜尋立即數101或102,找到指令格式為PUSH 0x65(101的十六進位制格式)並且註釋為nIDDlgItem的指令(有些時候可能沒有註釋,但是指令的格式必須是PUSH的),指令所在的地址就是我們要找的程式驗證邏輯,這邊兩個函式都有這種指令,還需要進一步分析,請見下


    我們先看雙擊跟進第一個指令所在的地址,然後使用F5檢視對應的C程式碼,發現這個是視窗樣式初始化的程式碼,並不是我們要找的驗證邏輯(看到SetClassLongA就知道了)

    我們來看第二條指令所在的地址,F5仔細分析下程式邏輯基本可以斷定這就是我們要找的程式驗證邏輯,驗證演算法這邊就不分析了

搜尋虛表

    如果按鈕的控制元件ID不夠特殊,並且當驗證按鈕的控制元件ID為1或0的時候,這個時候只能通過找虛擬函式的方式來定位驗證邏輯了,這個情況比較少見。控制元件ID為1或0的時候對應的處理函式比較特殊,它預設處理函式是OnOK和OnCancel,而這兩個都是虛擬函式,具體操作如下(這邊使用crackme.chm的noos.1.exe

作為演示用例,這邊搜尋EDIT的控制元件ID值1001或1002定位更快,僅為演示而演示)

    首先找到一個CDialog的虛擬函式,如果使用者同時過載了OnOK和OnCancel那麼就找DoModel,否則要麼找OnOK或OnCancel,然後單擊函式的交叉引用轉到虛表

    下面的1、2、3分別是DoModel、OnOK、OnCancel,如果被使用者過載了,那麼就會變成sub_xx的字樣,所以我們可以知道2就是我們要找的驗證函式OnOK


F5分析失敗處理方法

    F5功能用過的都說好啊,但是有時候F5會失敗,雖然可以直接看彙編,但是總是不太爽滴,能看C程式碼還是儘量看C程式碼,這樣程式框架比較容易理清,比如下面這個程式(實驗程式下載連結:

傳送門)

    產生這個問題的原因就是IDA對有些函式的棧平衡方式分析出了問題,如果函式是_stdcall方式,棧由函式自己來平衡,但是如果是_cdecl方式,則由呼叫者來平衡,如果IDA對函式的呼叫方式分析出的問題,那麼就會導致棧不平衡,這個時候就會出現上面的錯誤,解決辦法就是修正報錯所在地址的棧值,這個棧值要修正成什麼樣子呢?函式在一開始的時候會有太高棧頂和儲存暫存器值的動作,在完成這些動作後的棧頂值就是函式執行過程中的“標準棧值”,就是如果函式中因為要呼叫其他庫函式壓引數入棧,那麼在函式呼叫完成後需要再恢復到“標準值”

    由於函式開頭儲存暫存器有時候可能是後面函式呼叫的輸入引數,所以通過分析開頭來確定“標準棧值”不太方便,這邊我是習慣找出錯地址前分析正常的Call呼叫,因為IDA這個時候沒分析錯,那麼Call呼叫後恢復的棧頂值肯定就是標準值,當然可以多找幾個Call來驗證,因為有時候在release版本下,可能在連續呼叫幾個函式後才統一平衡堆疊,最常見的例子就是printf,release下會在連續幾個printf後使用add esp,xx的方式平衡,這個時候就add指令之後棧頂值就是標準值,所以stdcall方式和cdecl方式確認標準值的方式是不同的

    在出錯地址處按下ALT+K撥出棧頂值調整視窗,Current SP value表示當前指令執行前的棧頂值,old and new SP表示是當前指令執行完成後棧頂值的變化值,兩者相加就是指令執行完成後的棧頂值

    由於前面的call ds:__imp_mfc100_10007應該是一個stdcall呼叫,所以在這個call呼叫上按下ALT+K,可以得出標準棧頂值為-0x22C(可以多找幾個Call呼叫來驗證),所以我們只要將上面的棧頂值也調整成-0x22C就可以了,就是編輯框的0x21C改成0即可

    修改完成後你會發現又能神奇的F5囉~

交叉引用

    IDA作為靜態分析的利器,它的交叉引用是一個非常強大的功能,通過資料交叉引用,我們能夠知道一些全域性變數在程式碼中的使用情況,比如有些CrackMe程式它使用全域性變數來儲存字串,並且的字串獲取在一個函式,驗證在另外一個函式,我們通過控制元件ID很容易定位到字串獲取函式,驗證函式我們就可以通過對儲存字串的Buffer的交叉引用來定位了(這邊使用crackme.chm的Cruehead.1.exe作為演示用例)~

    使用IDA搜尋立即數1000,定位字串獲取程式碼位置

    接下來我們查詢String的資料交叉引用就能找到對應的驗證邏輯了,因為驗證當然要讀取字串,肯定還會引用String變數的,雙擊變數進入資料段,然後單擊資料的交叉引用,是不是很快就找到驗證邏輯了呢?