IDA Pro 4.x 邊界線的最後解決,順便去掉了一個IDA本身的小錯誤 (10千字)

看雪資料發表於2003-04-09

IDA Pro 4.x 邊界線的最後解決,順便去掉了一個IDA本身的小錯誤
以下是原始碼:

/*
*  This is a Border line patch for IDA Pro 4.x
*  By Xiao Han-Qing (bpx)
*    April 5, 2003
*/

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

// classic typedefs
typedef unsigned char        BYTE;
typedef unsigned short        WORD;
typedef unsigned int        DWORD;

typedef bool (*BorderFunc)(void);

#define I_Call                0xe8
#define I_Jmp                0xe9
#define SizeOfCall            5

#define GetRealAddrOf(func) (BYTE*)**(BorderFunc**)((char*)(func) + 2)
#define Call(ptr)            ptr + SizeOfCall + *(int*)(ptr + 1)

// Sig for MakeBorder
#define Sig1                0xc4684b6a

// Sig for MakeSolidBorder
#define Sig2                0xdb684b6a

// Sig for SegBorder
#define Sig3                0xcd684b6a

// 選擇你喜歡的邊界線,反註釋

//-------------------------------------
// For English Windows OS
//-------------------------------------
//#define ThinBorder    0x2d2d9b866 // --
//#define SolidBorder  0x3d3db866 // ==
//#define SegBorder    0x3d3db866 // ==
//-------------------------------------

// 以下適用於簡體中文Windows!!!

// 檔案頭方框, 隨便選一個吧
#if 0
#define UpperLeft    0xb3a9 //'┏'
#define HorLine        0xa5a9 //'━'
#define UpperRight    0xb7a9 //'┓'
#define VerLine        0xa7a9 //'┃'
#define LowerLeft    0xbba9 //'┗'
#define LowerRight    0xbfa9 //'┛'
#else
#define UpperLeft    0xf9a1 //'※'
#define HorLine        0xf9a1 //'※'
#define UpperRight    0xf9a1 //'※'
#define VerLine        0xf9a1 //'※'
#define LowerLeft    0xf9a1 //'※'
#define LowerRight    0xf9a1 //'※'
#endif

// 段邊界, 邏輯邊界, 函式邊界
//-------------------------------------
#define SegBorder    0xf9a1b866 //※
//-------------------------------------
#define ThinBorder    0xa5a9b866 //━
#define SolidBorder 0xfea1b866 //〓
//------------------------------------
//#define ThinBorder  0xeea1b866 //☆
//#define SolidBorder 0xefa1b866 //★
//------------------------------------
// #define ThinBorder 0xf0a1b866  //○
// #define SolidBorder 0xf1a1b866 //●
//------------------------------------
// #define ThinBorder 0xf3a1b866  //◇
// #define SolidBorder 0xf4a1b866 //◆
//------------------------------------
// #define ThinBorder 0xf5a1b866  //□
// #define SolidBorder 0xf6a1b866 //■
//------------------------------------
// #define ThinBorder 0xf7a1b866  //△
// #define SolidBorder 0xf8a1b866 //▲
//------------------------------------

// windows.h conflicts with IDA's header files, so copy it from MSDN
extern "C" int VirtualProtect(
  void* lpAddress,      // region of committed pages
  DWORD dwSize,          // size of the region
  DWORD flNewProtect,    // desired access protection
  DWORD* lpflOldProtect  // old protection
);

DWORD OldProt;
void Unprotect(void* addr, DWORD sz)
{
    VirtualProtect(addr, sz, 4/*PAGE_READWRITE)*/, &OldProt);
}

void Protect(void* addr, DWORD sz)
{
    VirtualProtect(addr, sz, OldProt, &OldProt);
}

// 生成邊界的程式碼, 比原版還要快!
BYTE code[] = {
    0x57,                        // push edi
    0x8d, 0x7d, 0x9c,          // lea edi, [ebp-64h]
    0xb9, 0x26, 00, 00, 00,    // mov ecx, 26h
    0xfc,                        // cld
    0xf2, 0x66, 0xab,            // repnz stosd
    0x5f,                        // pop edi
    0x90                        // nop
};

// patch各種邊界生成的地方,用我們的快程式碼!
bool DoPatch(BYTE* ptr, int range, DWORD sig, DWORD patch)
{
    int i;
    BYTE* p0, *p1;

    for (i = 0; i < range; i++, ptr++)
        if (*(DWORD*)ptr == sig)
            break;

    if (i == range) return false;

    Unprotect(ptr, sizeof(DWORD) + sizeof(code) + 35);

    *(DWORD*)ptr = patch;

    p1 = p0 = ptr + 16;
    for (i = 0; i < 35; i++) {
        // mov 'add esp, 0ch' to address right after 'call memset()'
        if ((*(DWORD*)p1 & 0xffffff) == 0xcc483 && p1 != p0) {
            memmove(p0 + 3, p0, p1 - p0);
            p1 += 3;
        }

        // mov byte ptr [esp-19], 0 --> mov byte ptr [esp-18], 0
        if (*(DWORD*)p1 == 0xe745c6)
            *(DWORD*)p1 = 0xe845c6;
        p1++;
    }

    memcpy(ptr + sizeof(DWORD), code, sizeof(code));

    Protect(ptr, sizeof(DWORD) + sizeof(code) + 35);

    return true;
}

//找到植入程式碼的空間
BYTE* FindSpaceForMyCode()
{
    BYTE* ptr = (BYTE*)&debug - 6 * 1024;

    do {
        while (*ptr != 0xcc) ptr++;
        if (*(DWORD*)ptr == 0xcccc && *((DWORD*)ptr + 1) == NULL)
            return ptr;
    } while (ptr++ < (BYTE*)&debug);

    return NULL;
}

// 檔案頭方框轉換程式碼
void ConvertLine(void)
{
_asm {
    push eax
    mov eax, dword ptr [esp+8]

Local_0:
    cmp byte ptr [eax], 0
    jz Local_done
    cmp byte ptr [eax], 0c9h
    jnz Local_1
    mov word ptr [eax], UpperLeft
    add eax, 2

Local_1:
    cmp byte ptr [eax], 0xcd
    jnz Local_2
    cmp byte ptr [eax+1], 0xcd
    jnz Local_11
    mov word ptr [eax], HorLine
    add eax, 2
    jmp short Local_1

Local_11:
    cmp [eax+1], 0xbb
    jnz Local_12
    mov word ptr [eax], UpperRight
    jmp short Local_done

Local_12:
    mov word ptr [eax], LowerRight
    jmp short Local_done

Local_2:
    cmp byte ptr [eax], 0xc8
    jnz Local_3
    mov word ptr [eax], LowerLeft
    add eax, 2
    jmp short Local_1

Local_3:
    cmp byte ptr [eax], 0xba
    jnz Local_4
    cmp byte ptr [eax+1], ' '    //這樣去掉了IDA一個內部bug!!! 否則檔案頭方框旁會多一個s
    jz Local_31                    //4.30和4.50都有這個問題.
    mov word ptr [eax], VerLine
    mov byte ptr [eax+2], 0
    jmp short Local_Done

Local_31:
    mov word ptr [eax], VerLine
    add eax, 2

Local_4:
    cmp byte ptr [eax], 0xbb
    jnz Local_5
    mov word ptr [eax], UpperRight
    mov byte ptr [eax+2], 0
    jmp short Local_done

Local_5:
    cmp byte ptr [eax], 0xbc
    jnz Local_6
    mov word ptr [eax], LowerRight
    mov byte ptr [eax+2], 0
    jmp short Local_done

Local_6:
    inc eax
    jmp short Local_0

Local_done:
    pop eax
    call MakeLine
}
}

// 植入我們的程式碼
BYTE* InsertMyCode()
{
    BYTE* ptr = FindSpaceForMyCode();

    if (ptr) {
        BYTE* pMakeLine, *p1, *p2;
        int MoveSz;

        pMakeLine = GetRealAddrOf(MakeLine);

        for (p1 = (BYTE*)ConvertLine; *(DWORD*)p1 != 0x24448b50; p1++);
        for (p2 = p1; *p2 != I_Call; p2++);

        MoveSz = p2 - p1;
        Unprotect(ptr, MoveSz + SizeOfCall);

        memcpy(ptr, p1, MoveSz);
        p1 = (BYTE*)ptr + MoveSz;
        *p1 = I_Jmp; // code for 'jmp MakeLine'
        *(int*)(p1 + 1) = pMakeLine - (p1 + SizeOfCall);

        Protect(ptr, MoveSz + SizeOfCall);
    }
    return ptr;
}

// 找到生成檔案頭方框函式內呼叫MakeLine()函式的地方
BYTE* FindCallMakeLine()
{
    // 從gen_idc_file()這個函式入手
    BYTE* ptr = GetRealAddrOf(gen_idc_file);
    BYTE* MakeLineAddr = GetRealAddrOf(MakeLine);
    int i = 0;

    while (*ptr++ != I_Call); // find and skip the first call
    while (*ptr != I_Call) ptr++;
    ptr = Call(ptr);

    do {
        while (*ptr != I_Call) {
            if (++i == 500)
                return 0;
            ptr++;
        }

        if (Call(ptr) == MakeLineAddr)
            break;

        ptr++;

    } while (1);

    return ptr;
}

// 在生成檔案頭方框的函式內截獲MakeLine()函式
bool PatchCallMakeLine()
{
    BYTE* MakeLineAddr, *MyCodeAddr;

    if ((MakeLineAddr = FindCallMakeLine()) != NULL &&
        (MyCodeAddr = InsertMyCode()) != NULL)
    {
        // 移花接木在此一舉!
        Unprotect(MakeLineAddr + 1, sizeof(DWORD));
        *(int*)(MakeLineAddr + 1) = MyCodeAddr - (MakeLineAddr + SizeOfCall);
        Protect(MakeLineAddr + 1, sizeof(DWORD));
        return true;
    }

    return false;
}

bool PatchBorderFuncs(void)
{
    BYTE* ptr;
    int i;

    if (!PatchCallMakeLine())
        return false;

    // 獲得要patch函式的真實地址
    ptr = GetRealAddrOf(MakeBorder);
    DoPatch(ptr - 5280, 1500, Sig3, SegBorder);
    DoPatch(ptr, 80, Sig1, ThinBorder);

    ptr = GetRealAddrOf(MakeSolidBorder);
    DoPatch(ptr, 80, Sig2, SolidBorder);

    for (i = 0; i < 80; i++) {
        // 將複製" S U B R O U T I N E "的地址向後移動一個位元組,
        // 否則剛好落在一個漢字的中間.
        // lea edi, [ebp-55] --> lea edi, [ebp-54]
        if ((*(DWORD*)ptr & 0xffffff) == 0xab7d8d) {
            ptr += 2;
            Unprotect(ptr, sizeof(BYTE));
            *(ptr) = 0xac;
            Protect(ptr, sizeof(BYTE));
            ptr++;
        }

        // mov [ebp-40], 0DBh --> mov [ebp - 3f], 20h
        if (*(DWORD*)ptr == 0xdbc045c6) {
            Unprotect(ptr, sizeof(DWORD));
            *(DWORD*)ptr = 0x20c145c6;
            Unprotect(ptr, sizeof(DWORD));
            return true;
        }
        ptr++;
    }

    return false;
}

int init(void)
{
    if (PatchBorderFuncs())
        msg("邊界線Patch安裝成功!");

    // 返回這個值告訴IDA載入這個plugin並幹完我
    // 們的活後就將這個plugin從記憶體中解除安裝掉
    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

  wanted_name,          // the preferred short name of the plugin
  wanted_hotkey        // the preferred hotkey to run the plugin
};

相關文章