您好,登錄后才能下訂單哦!
本篇文章為大家展示了ollydbg調試器中反匯編引擎的選擇與改造是怎樣的,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
小編選擇的是udis86,od的反匯編引擎ODDisassm雖然簡潔,但是只支持x86intel的匯編指令,不支持x64,指令集也很陳舊,BeaEngine雖然也不錯支持新指令集也多,但是代碼風格看起來不爽,capstone 雖然支持指令集比較多,也支持移動arm指令,但是整體代碼比較復雜,龐大臃腫,改造成本太高,最后還是選擇了udis86,代碼和接口都非常簡潔只有幾個cpp/h文件,支持支持MMX, FPU (x87), AMD 3DNow, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES, AMD-V, INTEL-VMX, SMX,支持x86/x64的Intel/AT&A的指令平臺,還有一個最大的特點就是解碼速度非常快。
1. udis86的使用
udis86的接口很簡單,使用也很簡單
一、第一步是初始化
ud_t ud_obj;
ud_init(&ud_obj);
ud_set_mode(&ud_obj,16); 設置反匯編系統16/32/64位
ud_set_pc(u, 0); 設置內存的段的基址,相當于PE文件的基址。
ud_set_asm_buffer(u,u->asm_buf_int,sizeof(u->asm_buf_int)); 設置反匯編的數據原始地址和數據長度
ud_set_syntax(&ud_obj, UD_SYN_INTEL);設置反匯編的語法平臺
二、第二步反匯編調用
代碼示例:
while (ud_disassemble(&ud_obj)) {
if (o_do_off)
printf("%016"FMT64 "x", ud_insn_off(&ud_obj));
if (o_do_hex) {
const char* hex1, *hex2;
hex1 = ud_insn_hex(&ud_obj);
hex2 = hex1 + 16;
printf("%-16.16s%-24s", hex1, ud_insn_asm(&ud_obj));
if (strlen(hex1) > 16) {
//printf("\n");
if (o_do_off)
printf("%15s-", "");
printf("%-16s",hex2);
}
}
else printf(" %-24s", ud_insn_asm(&ud_obj));
printf("\n");
}
ud_disassemble(&ud_obj)反匯編解析指令
ud_disassemble里調用ud_decode函數來實現解碼分析操作,然后使用translator函數對解碼的結果做指令翻譯操作翻譯成可讀的 intel或者AT&T的語法字符串。
ud_insn_off(&ud_obj)獲得當前的指令地址
ud_insn_asm(&ud_obj)獲取當前的反匯編后的字符串。
一下是結果顯示:
三、符號的設置
udis86還提供了一個設置解析符號的函數接口
ud_set_sym_resolver(&ud_obj,resolver);
resolver的接口定義:
const char* (*resolver)(struct ud*,
uint64_t addr,
int64_t *offset)
我們可以看到代碼里
void
ud_syn_print_addr(struct ud *u, uint64_t addr,char operand_asm_buf[64],int*index)
{
const char *name = NULL;
if (u->sym_resolver) {
int64_t offset =0;
name = u->sym_resolver(u, addr, &offset);
if (name) {
if (offset) {
ud_asmprintf(u, "%s%+" FMT64"d", name,offset);
ud_asmprintf2(operand_asm_buf,index,"%s%+"FMT64 "d",name, offset);
} else {
ud_asmprintf(u, "%s", name);
ud_asmprintf2(operand_asm_buf,index, "%s",name);
}
return;
}
}
ud_asmprintf(u, "%" FMT64"X", addr);
ud_asmprintf2(operand_asm_buf,index, "%"FMT64 "X",addr);
}
如果設置了sym_resolver接口,就會調用這個接口反匯的符號字符串來替代地址值的反匯編字符串。
縱觀以上udis86提供不少的功能但是在冒些情況下有很多不足之處,比如在一塊很大的內存進行反匯編解碼時沒有預解碼的函數接口,會導致使用者誤認為效率不高,還有其他情況與我們使用ollydbg不同的語法風格也需要我們去改造。
2. udis86改造
一、增加預分析接口。
unsigned int ud_predecode(struct ud* u)
{
int len;
if (u->inp_end) {
return 0;
}
len = ud_decode(u);
return len;
}
這個函數在分析解析過程速度非常快,效率非常高,這個函數用處主要在預分析,確定當前內存數據能反匯編出多少行指令,方便后續界面顯示時分頁顯示,因為它少了translator過程,預分析過程效率提高了幾百上千倍。
二.地址前綴顯示的改造
udis86在地址取址的前綴結果顯示與ollydbg不同,例如
static void opr_cast(struct ud* u, struct ud_operand* op) { if (u->br_far) { ud_asmprintf(u, "far "); } switch(op->size) { case 8: ud_asmprintf(u, "byte " ); break; case 16: ud_asmprintf(u, "word "); break; case 32: ud_asmprintf(u, "dword ");break; case 64: ud_asmprintf(u, "qword ");break; case 80: ud_asmprintf(u, "tword ");break; default: break; } } 為了保持了ollydbg一直我們需要改成: switch(op->size) { case 8: ud_asmprintf(u, "BYTE PTR ");ud_asmprintf2(operand_asm_buf,index,"BYTE PTR"); break; case 16: ud_asmprintf(u, "WORD PTR " );ud_asmprintf2(operand_asm_buf,index,"WORD PTR "); break; case 32: ud_asmprintf(u, "DWORD PTR ");ud_asmprintf2(operand_asm_buf,index,"DWORD PTR "); break; case 64: ud_asmprintf(u, "QWORD PTR ");ud_asmprintf2(operand_asm_buf,index,"QWORD PTR "); break; case 80: ud_asmprintf(u, "TWORD PTR ");ud_asmprintf2(operand_asm_buf,index,"TWORD PTR "); break; default: break; }
三、X64 RIP call指令不能顯示符號地址
這個應該屬于bug顯示問題,所以我們需要做以下修改,問題主要在ud_syn_print_mem_disp
函數,原是函數代碼為:
void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign,char operand_asm_buf[64], int*index) { UD_ASSERT(op->offset != 0); if (op->base == UD_NONE&& op->index== UD_NONE) { uint64_t v; UD_ASSERT(op->scale == UD_NONE&& op->offset!= 8); /* unsigned mem-offset */ switch (op->offset) { case 16: v = op->lval.uword; break; case 32: v = op->lval.udword; break; case 64: v = op->lval.uqword; break; default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ } ud_asmprintf(u, "%" FMT64"X", v); ud_asmprintf2(operand_asm_buf,index, "%"FMT64 "X",v); } else { int64_t v; UD_ASSERT(op->offset != 64); switch (op->offset) { case 8 : v = op->lval.sbyte; break; case 16: v = op->lval.sword; break; case 32: v = op->lval.sdword; break; default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ } if (v < 0) { ud_asmprintf(u, "-%" FMT64"X", -v); ud_asmprintf2(operand_asm_buf,index,"-%" FMT64"X", -v); } else if (v > 0) { ud_asmprintf(u, "%s%" FMT64"X", sign?"+" : "",v); ud_asmprintf2(operand_asm_buf,index,"%s%" FMT64"X", sign?"+" : "",v); } } } 修復主要在后面加一個RIP指令判斷 void ud_syn_print_mem_disp( struct ud* u, struct ud_operand *op, int sign) { UD_ASSERT(op->offset != 0); if (op->base == UD_NONE&& op->index== UD_NONE) { uint64_t v; UD_ASSERT(op->scale == UD_NONE&& op->offset!= 8); /* unsigned mem-offset */ switch (op->offset) { case 16: v = op->lval.uword; break; case 32: v = op->lval.udword; break; case 64: v = op->lval.uqword; break; default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ } if (u->sym_resolver) { LPTSTR name = NULL; int64_t offset =0; name = u->sym_resolver(u, v, &offset); if (name) { if (offset) { op->_legacy = offset; ud_asmprintf(u,0, _T("%s.%")FMT64 _T("X"), name,offset); } else { op->_legacy = v; ud_asmprintf(u,0, _T("%s"),name); } return; } } ud_asmprintf(u,1, _T("%")FMT64 _T("X"), v); } else { int64_tv; UD_ASSERT(op->offset != 64); switch (op->offset) { case 8 : v = op->lval.sbyte; break; case 16: v = op->lval.sword; break; case 32: v = op->lval.sdword; break; default: UD_ASSERT(!"invalidoffset"); v = 0; /* keep cc happy */ } //這里為添加專門處理RIP的指令 if (op->base == UD_R_RIP) { v += (u->inp_ctr + u->insn_offset); if (u->sym_resolver) { LPTSTR name = NULL; int64_toffset = 0; name = u->sym_resolver(u, v, &offset); if (name) { if (offset) { op->_legacy = offset; ud_asmprintf(u,0, _T("%s.%") FMT64_T("X"),name, offset); } else { op->_legacy = v; ud_asmprintf(u,0, _T("%s"), name); } return; } } } if (v < 0) { ud_asmprintf(u,1, _T("-%") FMT64_T("X"),-v); } else if (v > 0) { if (op->base == UD_R_RIP) { ud_asmprintf(u,1, _T("%s%") FMT64_T("X"),sign? _T("") : _T(""), v); }else { ud_asmprintf(u,1, _T("%s%") FMT64_T("X"),sign? _T("+") : _T(""), v); } } } }
其他還有一些小的細節和ollydbg有細微差別,這里就不再贅述了,讀者可以自行去發現,經過一些改造與加工我們就能得到一個性能與結果完美的反匯編引擎,后面的一些界面顯示的速度性能等等一些調試器的交互工作就會事半功倍了。
上述內容就是ollydbg調試器中反匯編引擎的選擇與改造是怎樣的,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。