iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 14
1
Security

逆向工程 – 從入門到放棄系列 第 14

Day14 - 史上最強Debugger - 人體肉眼 Debugger

  • 分享至 

  • xImage
  •  

今天,準備要開始逆向程式碼。在介紹工具之前,先來解說逆向工程的邏輯。基本上,對於逆向,有很多現成的工具可以直接套用,但許多有其極限(當然,有工具可以提升效率,我沒有說要完全摒棄工具)。但就對於想透過組合語言來解釋程式碼而言,不仰賴工具更可以練習自己的組合語言語感。因此,很多時候透過交叉比對,更可以解釋狀況。以下,我將講解如何將程式碼一步步拼湊回來。

我會先提供一份已經逆向過的程式碼截圖,讀者可以挑戰可否在不使用工具下,理解程式碼的運作邏輯?接著會提供透過 GDB 輔助動態追蹤的過程與解答,讓讀者比較是否與自己的理解相同。

路上撿到程式碼

情境引導:在通往偉大的航道,你撿到一支程式碼,執行後發現它是一支會驗證使用者輸入的程式(如下圖)。到底驗證過後能獲得什麼秘辛呢?好奇的你,真的好想知道。於是,你隨意輸入一段內文(LET ME IN),發現錯誤。果然沒那那麼簡單就可以拿到擁有世界上的一切的「海賊王」哥爾·D·羅傑的寶藏。你忽然想到,最近不是有學過逆向嗎?何不來逆逆看?

被逆向的程式碼

下圖是透過 GDB 逆向的程式碼,想請問讀者這段程式碼到底在做什麼?
讀者可以拿出紙與筆,畫出以下程式碼的運作流程圖。花一點時間,消化這幾天所看到的知識,若忘記可以往回翻,或查閱相關資料。重點是,若想提升組合語言的識別能力,不要輕易的直接看解答,先讓大腦思考一下。想跟大家分享,我去成大上課的時候,聽到 Jserv 大大的名言:

「如果你把游泳池當作浴缸泡著,再泡幾年還是不會游泳」
– jserv

拼湊程式碼

經過與海軍奮鬥的一番掙扎後,我們現在來講解一下如何肉眼識別程式碼。
先看下圖,其實我們看到組合語言密密麻麻,也不是每一個都是重點。讀者可能會問,那什麼是重點?我把重點用紅筆標示起來於下圖 - 重點就在每次的比較、跳躍與呼叫其他函式。比方說記憶體結尾是 5cc 的地方,有一個 cmp 指令,接著 5d0 的 jne;還有 5ea 的地方,有一個 call 的指令,後面還寫著 <printf@plt>。這些都是重點,因為我們逆向的時候,想知道到底什麼條件下會觸發這些事情?觸發後做了什麼事?

於是,透過上述方法,就可以簡略畫出程式運作圖(如下圖)。可以知道,總共有三個區域,分別是白色、紅色、綠色的區塊。分別對應三種情況。首先,白色區塊代表的就是驗證全部通過後的結果(找到寶藏),而紅色代表的是第一個驗證沒過的下場,綠色表的是第二個驗證沒過的下場。簡單來說,就是要走在白色這條主線上,才能通關成功!

透過與 GDB 的動態追蹤,可以得到下圖結果。紅色的 1 代表,沒通過參數個數驗證,綠色的 2 代表通過參數個數驗證,卻沒通過驗證碼的驗證,紫色的 3 代表驗證全部,安全達陣!

原始程式碼

以下是哥爾·D·羅傑的寶藏。解答公布:

#include <string.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
        if(argc==2) {
        printf("Checking License: %s\n", argv[1]);
        if(strcmp(argv[1], "AAAA-Z10N-42-OK")==0) {
            printf("Access Granted!\n");
        } else {
            printf("WRONG!\n");
        }
    } else {
        printf("Usage: <key>\n");
    }
    return 0;
}

結論

恭喜找到 ONE PIECE!動態追蹤程式程式碼蠻有趣的,雖然有點累、甚至有很多看不懂的情況,但了解背後邏輯94爽。明天,將會講解如何透過工具解讀程式碼、提升逆向效率。


上一篇
Day13 - Hello world 的奇妙冒險
下一篇
Day15 - 逆向神器 - IDA Pro
系列文
逆向工程 – 從入門到放棄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言