• 标 题:用插件(plugin)的方式改变IDA Pro的边界线 (16千字)
  • 作 者:bpx
  • 时 间:2003-4-5 3:30:42
  • 链 接:http://bbs.pediy.com

用插件(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+edx-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 其代码.