1. 程式人生 > >ida藉助windbg 雙機除錯核心

ida藉助windbg 雙機除錯核心

用windbg雙機除錯的話,因為是命令列類似於以程式設計來代替手工跟蹤的方式。習慣了用OD+ida分析的,肯定會不適應,於是就有ida的除錯方式可以代替它,我使用的是ida 5.5,可能有一些區別,希望碰到問題的朋友能夠一起解決,交流才能進步。

把配置檔案配置好的話,會輕鬆很多。
第一個問題,IDA的windbg外掛不讀取pdb.cfg裡的pdb目錄設定,而是固執的放到temp目錄去,很讓人生氣、不過windbg.plw中會判斷系統環境變數_NT_SYMBOL_PATH,存在的話,就會照此設定來了。如果以前沒用過_NT_SYMBOL_PATH這個環境變數,可以用set建立成系統級別的環境變數:
Set _NT_SYMBOL_PATH = symsrv*symsrv.dll*f:\localsymbols*http://msdl.microsoft.com/download/symbols
不過我建議不要用線上的symbols,畢竟掛上去然後等幾分鐘,接著因為不匹配的pdb .sym noisy, .reload /f一番挺多餘的。可以下載一個確定是配套版本的symbols到本地來,再給解壓出來的symbols目錄裡添個flat.txt (achooollllls大俠對symbols裡的flat.txt和pingme.txt等寫過一個很精彩的說明),這樣一個Set就完全讓符號問題解決了。用登錄檔方式設定系統環境變數,不然_NT_SYMBOL_PATH存在時set只會設定目標命令列程序樹裡的環境變數。

reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v _NT_SYMBOL_PATH /d "D:\xpoy\tools\偵錯程式\win symbol\symbol xp sp3" /f

在模組基地址0x19C1000,windbg.plw中的程式碼位置是:
.text:019D0892                 call    sub_19C2468 ;//讀取環境變數_NT_SYMBOL_PATH
.text:019D0897                 test    al, al
.text:019D0899                 jnz     short loc_19D08BB//
.text:019D089B                 push    400h
.text:019D08A0                 lea     edx, [ebp+var_400]
.text:019D08A6                 push    edx
.text:019D08A7                 call    sub_19C249C//沒的話得到temp目錄。
.text:019D08AC                 push    0
.text:019D08AE                 lea     ecx, [ebp+var_400]
.text:019D08B4                 push    ecx
.text:019D08B5                 push    ebx
.text:019D08B6                 call    sub_19D08C8

接著在ida的配置檔案中,ida.cfg中配置偵錯程式的目錄
//      Processor specific parameters
之後可以設定dbgeng.dll windbg除錯外掛使用到的DLL的目錄,
格式類似於
DBGTOOLS = "D:\\xpoy\\tools\\偵錯程式\\X86 win32 windbger\\";
然後還可以到dbg_windbg.cfg中,把kernel-mode直接選上
KERNELMODE = YES
這樣attack時候直接下一步就可以了。

要是覺得debug->attack中的沒用專案太多的話,可以到plugin\plugin.cfg中把不用的都註釋掉,前面加";"
只留一個
Windbg_debugger             windbg_user 0       0  DEBUG
便好了。

attack的命令列的話,就是給windbg的命令列引數。先一路配置好windbg可以遠端除錯了,然後windbg->view->windbg command line就彈出來所使用的完整命令行了,MessageBox彈出的對話方塊是可以直接ctrl+C複製裡面的內容出來的。
比如我的:

com:pipe,resets=0,reconnect,port=\\.\pipe\kd_xp_sp3_深度_unknow

然後提一些IDA除錯時的小經驗,其實我只是用了一會兒,就興沖沖來發帖了,有錯誤的話,見諒,也請大牛能指正下。 :P
執行起來時,要強制中斷執行的話,需要按彈出來視窗的那個大大的suspend。
Ctrl+ALt+S開啟的strack trace windows很有用,用windbg就一定會喜歡它的堆疊顯示方式,Ida 的這個也可以顯示類似的格式。
在最下方有一小行windbg的命令列顯示,這個命令列不支援"!"開頭的由ext等外掛提供的功能,但原windbg的命令列, "."開頭的命令列都支援,非常方便。但是普通命令不能用"g"/"t"/"p"等會讓被除錯物件執行起來的命令,必須用IDA的 F7、F8、F4等,這幾個和OD中的意義一樣,另外,用windbg的斷點命令設定的斷點,ida也不能檢測到而不會在它自己的斷點列表中顯示,雖然這些也可以工作。比方我要檢視當前除錯目標user程序的模組,就可以很正常的這樣來lm u,和windbg中的command line效果一樣。最大的缺陷就是,ida不能用擴充命令後,在核心方式除錯單個目標程序挺麻煩,!process等匯出的函式模組不能用了。要解決此問題,需要手動用.load載入對應的ext們:
.load D:\xpoy\tools\偵錯程式\X86 win32 windbger\winext\ext.dll;
...

.load D:\xpoy\tools\偵錯程式\X86 win32 windbger\winxp\acpikd.dll;
...
我為了自己方便用,寫了一個很簡陋的指令碼,也一併放上來,實在是找不到idc怎麼查詢一個目錄裡面的所有檔案.改成讀取配置檔案其實也很方便。
原版的這個腳本里,我只是固定的寫著WinSendCommand自己機器上面windbg目錄的那些ext檔案,同時#softinclude在了idc\userload.idc裡面,這樣每次開啟ida都會試著執行下。
windbg的sx?選項在debug option->edit exception中可以做類似的設定。也可以提前在cfg\exceptions.cfg中更改,但是沒windbg那麼方便。
ida的trace比od的還強大,在定位目標的時候很牛, 比方write trace, read trace用來定位全操作目標記憶體範圍的程式碼們。 :)!!!!!
另外ida還可以用來除錯其他平臺(arm、iphone)等

用ida在逆向時跟蹤核心實在是太爽了,至少在沒原始碼和除錯非windows核心模組(需要雙機除錯的使用者模組)的時候比windbg的外掛們好用多了。

另外,如果重啟被除錯機時,沒有在開機時候掛一個偵錯程式上去過,在系統執行途中需要先執行vmkdmon,然後再執行偵錯程式以掛上去。

用了幾天發現,雖然IDA的命令列視窗只能按照行來選,不過反彙編和點來點去跟蹤函式流程實在是超爽。而命令列視窗的問題,可以通過.logopen 這個命令,把windbg的命令列輸出到一個log檔案,這樣把log檔案拖到記事本開啟,然後ida裡還可以非常舒服的看彙編,ida藉助windbg <wbr>雙機除錯核心:

IDA6.1很奇怪的在查詢dbgeng.dll的時候,不會按照cfg中設定的windbg目錄去查詢,而是直覺在ida的目錄,再到windows目錄查詢下,似乎是因為環境變數的問題。但我把dbgeng.dll複製到ida6.1目錄下也可以解決問題。感謝落幕CC公開的6.1。

附ida原作者宣傳這個功能的視訊:

附2,指令碼

#include <idc.idc>

static SendLoadSpecExtWithPath (Path, Ext)
{
     auto CurrentExtPath, EvalStr;
     CurrentExtPath= ".load "+ Path+  Ext;
     Message ( CurrentExtPath+ "\r\n");
     WinDbgCommand (CurrentExtPath) ;
}
 
static strrchr (In_str, In_chr)
{
    auto Len_str, temp_chr;
    Len_str= strlen (In_str);
    while (0<Len_str)
    {
        temp_chr= substr(In_str, Len_str, Len_str+ 1);
        if (temp_chr==In_chr)
        {
            break;
        }
        Len_str= Len_str- 1;
    }

    return Len_str;
}

static main ()
{
    auto ExtPath;
    ExtPath= AskFile ( 0, "ext.dll", "選擇你的windbg目錄的winext\\ext.dll");
    ExtPath= substr ( ExtPath, 0, strrchr (ExtPath, "\\")+ 1);
   
    if (""!=strlen(ExtPath))
    {
        SendLoadSpecExtWithPath ( ExtPath, "kext.dll");
        SendLoadSpecExtWithPath ( ExtPath, "logexts.dll");
        SendLoadSpecExtWithPath ( ExtPath, "uext.dll");
        SendLoadSpecExtWithPath ( ExtPath, "wdfkd.dll");
        SendLoadSpecExtWithPath ( ExtPath, "ext.dll");
    }

    ExtPath= AskFile ( 0, "ext.dll", "選擇你的windbg目錄的winxp\\exts.dll");
    ExtPath= substr ( ExtPath, 0, strrchr (ExtPath, "\\")+ 1);
    if (""!=strlen(ExtPath))
    {
        SendLoadSpecExtWithPath (ExtPath,"acpikd.dll");
        SendLoadSpecExtWithPath (ExtPath,"exts.dll");
        SendLoadSpecExtWithPath (ExtPath,"fltkd.dll");
        SendLoadSpecExtWithPath (ExtPath,"kdexts.dll");
        SendLoadSpecExtWithPath (ExtPath,"ks.dll");
        SendLoadSpecExtWithPath (ExtPath,"minipkd.dll");
        SendLoadSpecExtWithPath (ExtPath,"ndiskd.dll");
        SendLoadSpecExtWithPath (ExtPath,"ntsdexts.dll");
        SendLoadSpecExtWithPath (ExtPath,"rpcexts.dll");
        SendLoadSpecExtWithPath (ExtPath,"scsikd.dll");
        SendLoadSpecExtWithPath (ExtPath,"traceprt.dll");
        SendLoadSpecExtWithPath (ExtPath,"vdmexts.dll");
        SendLoadSpecExtWithPath (ExtPath,"wmitrace.dll");
        SendLoadSpecExtWithPath (ExtPath,"wow64exts.dll");
        SendLoadSpecExtWithPath (ExtPath,"Wudfext.dll");
    }
}