用外掛(plugin)的方式改變IDA Pro的邊界線 (16千字)

看雪資料發表於2015-11-15

用外掛(plugin)的方式改變IDA Pro的邊界線

(同時在看雪論壇(用bpx)http://www.chat001.com/forum/crackforum/index.html和說吧論壇(歐陽

鋒)http://bbs.sayba.com/cgi-bin/forums.cgi?forum=49上發表。

在說吧論壇的附件中包含整個工程。如果沒有ida pro sdk的朋友可將壓縮包中的BorderPatch.plw複製到ida的plugin子目錄就可以了。否則,將工程解壓到sdk的plugin子目錄。

IDA Pro,這個2001年世界最佳開發工具亞軍(冠軍是MS .net), 在功能上是一個近乎完美的工具。

4.50 加上了偵錯程式,簡直是如虎添翼。然而,對於使用中文Windows的使用者,她卻有一個小小的瑕疵

,那就是分界線顯示為
"哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪"
感覺不爽。以前想過改掉它,但沒有成功。也不願再多花更多時間。想等公司買了正版以後再說。後

來看雪論壇有高手貼出過修改idag.exe的方法。方法很不錯。昨天看了IDA SDK, 發現有更好的辦法

。那就是用外掛。

修改idag.exe存在以下不足之處:
1. 每顯示一行資訊都要跳出去檢查是不是邊界線,對效能有一定影響。而外掛只是在載入時patch邊

界線生成的程式碼。對效能沒有絲毫影響。
2. 版本更新後又要去修改,而用外掛的方法理論上可以支援各種版本,且不用重編譯。
3. 修改idag.exe不方便支援雙位元組邊界線,用=====或------畫面略顯單調。而用外掛使用者可選擇多

種邊界線,如

0040113C ; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
0040113D    align 4
00401140
00401140 ; 〓〓〓〓〓〓〓〓 S U B R O U T I N E  〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
00401140
00401140
00401140 CStatus::Free proc near            ; CBoardDisplay::Free+8p
00401140                                    ; CHistory::Free+18p ...
00401140
00401140 arg_0= dword ptr  4
00401140
00401140    mov eax, [esp+arg_0]
00401144    push eax
00401145    call MemFree
0040114A    add esp, 4
0040114D    retn
0040114D CStatus::Free endp
0040114D
0040114D ; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


0040113C ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
0040113D    align 4
00401140
00401140 ; ★★★★★★★★ S U B R O U T I N E  ★★★★★★★★★★★★★★★★★★★
00401140
00401140
00401140 CStatus::Free proc near            ; CBoardDisplay::Free+8p
00401140                                    ; CHistory::Free+18p ...
00401140
00401140 arg_0= dword ptr  4
00401140
00401140    mov eax, [esp+arg_0]
00401144    push eax
00401145    call MemFree
0040114A    add esp, 4
0040114D    retn
0040114D CStatus::Free endp
0040114D
0040114D ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

以下是對這個外掛的簡單說明,詳細內容請參閱原始碼

ida邊界生成函式分別為
bool MakeBorder();
bool MakeSolidBorder();
它們在ida.wll這個壓縮動態連線庫中。其中後者為函式的分界線。我們就patch這兩個函式。

typedef bool (*BorderFunc)(void);

static bool PatchBorderFuncs(void)
{
    BorderFunc func;
    unsigned char* ptr, *ptr2;
    int i, j;

    // 獲得要patch函式的地址
    func = MakeBorder; // 這是thunk地址
    ptr = (unsigned char*)**(BorderFunc**)((char*)func + 2); // 這才是函式在ida.wll

中的真實地址
    ...
}

如果僅僅想邊界線顯示為=========或-------------,那就太簡單了,僅需將
push 0c4h 改成 push 2dh
push 0dbh 改成 push 3dh

如果想要顯示雙位元組邊界,除了patch以上二個函式外,還要修改sub_100732C4(),讓它支援中文字

符邊界,這樣美觀的多,你說呢?

用以上的方法雖解決了一個無關緊要問題,卻讓我們有了一個修改ida的一個方法! 以下是原始碼:

/*
*  This Border line patch
*  By Xiao Han-Qing (bpx)
*    April 5, 2003
*/

#include <ida.hpp>
#include <idp.hpp>
#include <bytes.hpp>
#include <loader.hpp>
#include <kernwin.hpp>

/*
MakeBorder()
{
10011E4C 55                  push        ebp
10011E4D 8B EC                mov        ebp,esp
10011E4F 83 C4 9C            add        esp,0FFFFFF9Ch
10011E52 F6 05 AE 85 0C 10 01 test        byte ptr ds:[100C85AEh],1 ;如果這個值為1,就不

顯示邊界線
10011E59 74 43                je          10011E9E
10011E5B EB 14                jmp        10011E71
10011E5D 6A 00                push        0
10011E5F 68 C6 82 0A 10      push        100A82C6h
10011E64 E8 EF 07 00 00      call        10012658
10011E69 84 C0                test        al,al
10011E6B 74 04                je          10011E71
10011E6D B0 01                mov        al,1
10011E6F EB 2F                jmp        10011EA0
10011E71 0F BE 15 F1 B4 0B 10 movsx      edx,byte ptr ds:[100BB4F1h]
10011E78 4A                  dec        edx
10011E79 74 E2                je          10011E5D
10011E7B 6A 4B                push        4Bh              ; 邊界線的長度,需要patch成

4ch
10011E7D 68 C4 00 00 00      push        0C4h            ; 就是這個醜陋字元,patch成

ThinBorder
10011E82 8D 4D 9C            lea        ecx,[ebp-64h]
10011E85 51                  push        ecx
10011E86 E8 39 14 06 00      call        sub_100732C4    ; 這個函式里面要patch
10011E8B 83 C4 0C            add        esp,0Ch
10011E8E 8D 45 9C            lea        eax,[ebp-64h]
10011E91 C6 45 E7 00          mov        byte ptr [ebp-19h],0 ; 因為將長度改成了4c, 故

patch成 mov byte ptr [ebp-18h], 0
10011E95 50                  push        eax
10011E96 E8 79 8C FF FF      call        1000AB14
10011E9B 59                  pop        ecx
10011E9C EB 02                jmp        10011EA0
10011E9E 33 C0                xor        eax,eax
10011EA0 8B E5                mov        esp,ebp
10011EA2 5D                  pop        ebp
10011EA3 C3                  ret
}
*/

/*
MakeSolidBorder()
{
10011EA4 55                  push        ebp
10011EA5 8B EC                mov        ebp,esp
10011EA7 83 C4 9C            add        esp,0FFFFFF9Ch
10011EAA 56                  push        esi
10011EAB 57                  push        edi
10011EAC 6A 4B                push        4Bh            ; SolidBorder長度,patch 成

'push 4c'
10011EAE 68 DB 00 00 00      push        0DBh            ; 醜陋的字元,patch成

SolidBorder
10011EB3 8D 45 9C            lea        eax,[ebp-64h]
10011EB6 50                  push        eax
10011EB7 E8 08 14 06 00      call        sub_100732C4
10011EBC 8D 7D AB            lea        edi,[ebp-55h]  ; 複製" S U B R O U T I N E "

的地址
10011EBF 83 C4 0C            add        esp,0Ch        ; patch成lea edi, [ebp-54h],

落在偶地址
10011EC2 8B C7                mov        eax,edi
10011EC4 BE C8 82 0A 10      mov        esi,100A82C8h
10011EC9 B9 05 00 00 00      mov        ecx,5
10011ECE 8D 55 9C            lea        edx,[ebp-64h]
10011ED1 F3 A5                rep movs    dword ptr [edi],dword ptr [esi] ; 這段程式碼複製

" S U B R O U T I N E "
10011ED3 66 A5                movs        word ptr [edi],word ptr [esi]  ; patch成 movs

byte ptr[edi], byte ptr[esi]
10011ED5 C6 45 C0 DB          mov        byte ptr [ebp-40h],0DBh        ; patch成4個

nop
10011ED9 C6 45 E7 00          mov        byte ptr [ebp-19h],0            ; 改變了長度,

故patch成 mov byte ptr [ebp-18h], 0
10011EDD 52                  push        edx
10011EDE E8 31 8C FF FF      call        1000AB14
10011EE3 59                  pop        ecx
10011EE4 5F                  pop        edi
10011EE5 5E                  pop        esi
10011EE6 8B E5                mov        esp,ebp
10011EE8 5D                  pop        ebp
10011EE9 C3                  ret
}
*/

/*
sub_100732C4()
{
100732C4 55                  push        ebp
100732C5 8B EC                mov        ebp,esp
100732C7 57                  push        edi
100732C8 8A 45 0C            mov        al,byte ptr [ebp+0Ch]    ; 我們要用雙位元組字元

作邊界, 故
100732CB 8B 55 10            mov        edx,dword ptr [ebp+10h]  ; patch 成 mov eax,

dword ptr [ebp+0ch]
100732CE 8B 7D 08            mov        edi,dword ptr [ebp+8]
100732D1 8A E0                mov        ah,al                    ; patch 成 nop
100732D3 F7 C2 FC FF FF FF    test        edx,0FFFFFFFCh
100732D9 74 5D                je          10073338
100732DB 66 89 07            mov        word ptr [edi],ax
100732DE 8D 4C 17 FC          lea        ecx,[edi+edw-4]
100732E2 66 89 47 02          mov        word ptr [edi+2],ax
100732E6 8B 07                mov        eax,dword ptr [edi]
100732E8 C1 EA 03            shr        edx,3
100732EB 74 43                je          10073330
100732ED 89 07                mov        dword ptr [edi],eax
100732EF 89 47 04            mov        dword ptr [edi+4],eax
100732F2 4A                  dec        edx
100732F3 74 30                je          10073325
100732F5 89 47 08            mov        dword ptr [edi+8],eax
100732F8 89 47 0C            mov        dword ptr [edi+0Ch],eax
100732FB 4A                  dec        edx
100732FC 74 27                je          10073325
100732FE 89 47 10            mov        dword ptr [edi+10h],eax
10073301 89 47 14            mov        dword ptr [edi+14h],eax
10073304 4A                  dec        edx
10073305 74 1E                je          10073325
10073307 89 47 18            mov        dword ptr [edi+18h],eax
1007330A 89 47 1C            mov        dword ptr [edi+1Ch],eax
1007330D 4A                  dec        edx
1007330E 74 15                je          10073325
10073310 89 47 20            mov        dword ptr [edi+20h],eax
10073313 89 47 24            mov        dword ptr [edi+24h],eax
10073316 4A                  dec        edx
10073317 74 0C                je          10073325
10073319 89 47 28            mov        dword ptr [edi+28h],eax
1007331C 89 47 2C            mov        dword ptr [edi+2Ch],eax
1007331F 8D 7F 30            lea        edi,[edi+30h]
10073322 4A                  dec        edx
10073323 75 C8                jne        100732ED
10073325 89 01                mov        dword ptr [ecx],eax
10073327 89 41 FC            mov        dword ptr [ecx-4],eax
1007332A 8B 45 08            mov        eax,dword ptr [ebp+8]
1007332D 5F                  pop        edi
1007332E 5D                  pop        ebp
1007332F C3                  ret
}
*/

//--------------------------------------------------------------------------
//
//      Initialize.
//
//      IDA will call this function only once.
//      If this function returns PLGUIN_SKIP, IDA will never load it again.
//      If this function returns PLUGIN_OK, IDA will unload the plugin but
//      remember that the plugin agreed to work with the database.
//      The plugin will be loaded again if the user invokes it by
//      pressing the hotkey or selecting it from the menu.
//      After the second load the plugin will stay on memory.
//      If this function returns PLUGIN_KEEP, IDA will keep the plugin
//      in the memory. In this case the initialization function can hook
//      into the processor module and user interface notification points.
//      See the hook_to_notification_point() function.
//

//-----------------------
// Do our job here
//-----------------------
// length
#define Sig1        0x4b6a
#define ChgSig1        0x4c6a

// Ugly thin border
#define Sig2        0xc468

// call instruction byte
#define Call        0xe8

// Ugly solid border
#define Sig3        0xdb68


// 選擇你喜歡的邊界線,反註釋
//-------------------------------------
//#define ThinBorder 0x2d2d968 // ==
//#define SolidBorder 0x3d3d68 // --
//-------------------------------------

// 以下適用於簡體中文Windows!!!
//-------------------------------------
//#define ThinBorder 0xa5a968  //━
//#define SolidBorder 0xfea168 //〓
//------------------------------------
#define ThinBorder  0xeea168 //☆
#define SolidBorder 0xefa168 //★
//------------------------------------
//#define ThinBorder 0xaaa168  //―
//#define SolidBorder 0xf9a168 //※
//------------------------------------
// #define ThinBorder 0xf0a168  //○
// #define SolidBorder 0xf1a168 //●
//------------------------------------
// #define ThinBorder 0xf3a168  //◇
// #define SolidBorder 0xf4a168 //◆
//------------------------------------
// #define ThinBorder 0xf5a168  //□
// #define SolidBorder 0xf6a168 //■
//------------------------------------
// #define ThinBorder 0xf7a168  //△
// #define SolidBorder 0xf8a168 //▲
//------------------------------------
typedef bool (*BorderFunc)(void);

static bool PatchBorderFuncs(void)
{
    BorderFunc func;
    unsigned char* ptr, *ptr2;
    int i, j;

    // 獲得要patch函式的thunk地址
    func = MakeBorder;

    // 這才是函式在ida.wll中的真實地址
    ptr = (unsigned char*)**(BorderFunc**)((char*)func + 2);
    
    // 最多搜尋80個字元
    for (i = 0; i < 80; i++) {
        // 找到要patch的指令
        // patch 'push 4bh'
        if (*(unsigned short*)ptr == Sig1) {    // search for 'push 0c4h'
            *(unsigned short*)ptr = ChgSig1;
            ptr += sizeof(short);
        }

        // patch 'push c4'
        if (*(unsigned int*)ptr == Sig2) {
            *(unsigned int*)ptr = ThinBorder;            //

change to 'push 02dh
            ptr += sizeof(int);

            // 找到'call sub_100732C4'指令
            for (ptr2 = ptr; *ptr2 != Call; ptr2++);

            // 模擬'call'的過程跟蹤到sub_100732C4地址
            ptr2 += 5 + *(int*)(ptr2 + 1);
            // 找到 mov al,byte ptr [ebp+0Ch]
            for (j = 0; j < 30; j++) {
                if ((*(unsigned int*)ptr2 & 0xffffff) == 0x0c458a) {
                    // patch成mov eax dword ptr [ebp+0ch]
                    *ptr2 = 0x8b;
                    ptr2 += 3;
                }
                // 找到mov ah, al
                if (*(unsigned short*)ptr2 == 0xe08a) {
                    // patch 成nop
                    *(unsigned short*)ptr2 = 0x9090;
                    break;
                }
                ptr2++;
            }

            // patch mov byte ptr [ebp-19h],0 to  mov byte ptr [ebp-18h],0
            while (*(unsigned int*)ptr != 0xe745c6) ptr++;
            *(unsigned int*)ptr = 0xe845c6;
            break;
        }
        ptr++;
    }

    if (i == 80) return false;

    func = MakeSolidBorder;
    ptr = (unsigned char*)**(BorderFunc**)((char*)func + 2);
    for (i = 0; i < 80; i++) {
        // patch push 4b
        if (*(unsigned short*)ptr == Sig1) {    // search for 'push 0c4h'
            *(unsigned short*)ptr = ChgSig1;
            ptr += sizeof(short);
        }

        // patch push db
        if (*(unsigned int*)ptr == Sig3) {
            *(unsigned int*)ptr = SolidBorder;            //

change to SolidBorder
            ptr += sizeof(int);
        }

        if ((*(unsigned int*)ptr & 0xffffff) == 0xab7d8d) {
            *(ptr+2) = 0xac;
            ptr += 3;
        }

        if (*(unsigned int*)ptr == 0xdbc045c6) {
            *(unsigned int*)ptr = 0x20c145c6;
            ptr += sizeof(int);

            // patch mov byte ptr [ebp-19h],0 to  mov byte ptr [ebp-18h],0
            while (*(unsigned int*)ptr != 0xe745c6) ptr++;
            *(unsigned int*)ptr = 0xe845c6;
            return true;
        }
        ptr++;
    }

    return false;
}

int init(void)
{
    if (PatchBorderFuncs())
        msg("Border line plugin loaded successfully!");

    return PLUGIN_SKIP; // never load again
}

//--------------------------------------------------------------------------
//
//      The plugin method
//
//      This is the main function of plugin.
//
//      It will be called when the user selects the plugin.
//
//              arg - the input argument, it can be specified in
//                    plugins.cfg file. The default is zero.
//
//

void run(int arg)
{
}

//--------------------------------------------------------------------------
char comment[] = "Border line plugin";
char help[] = "Border line plugin for IDA Pro running under Simplified Chinese Windows";


//--------------------------------------------------------------------------
// This is the preferred name of the plugin module in the menu system
// The preferred name may be overriden in plugins.cfg file
char wanted_name[] = "Border line plugin";

char wanted_hotkey[] = "";

//--------------------------------------------------------------------------
//
//      PLUGIN DESCRIPTION BLOCK
//
//--------------------------------------------------------------------------
extern "C" plugin_t PLUGIN = {
  IDP_INTERFACE_VERSION,
  0,                    // plugin flags
  init,                // initialize

  NULL, //term,                // terminate. this pointer may be NULL.

  run,                  // invoke plugin

  comment,              // long comment about the plugin
                        // it could appear in the status line
                        // or as a hint

  help,                // multiline help about the plugin

注 意
1. 不同版本的ida必須用其各自的sdk來編譯這個plugin,否則ida不會載入其它版本sdk編譯的plugin
2. 有些版本的ida(如ida4.30)其ida.wll必須用PeEditor將其程式碼段的特性改變為E000020,否則無法patch 其程式碼.

相關文章