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