千家信息网

ollydbg调试器中反汇编引擎的选择与改造是怎样的

发表于:2025-02-03 作者:千家信息网编辑
千家信息网最后更新 2025年02月03日,本篇文章为大家展示了ollydbg调试器中反汇编引擎的选择与改造是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。小编选择的是udis86,od的反汇编引
千家信息网最后更新 2025年02月03日ollydbg调试器中反汇编引擎的选择与改造是怎样的

本篇文章为大家展示了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("6"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("s-", "");

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 voidopr_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

函数,原是函数代码为:

voidud_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调试器中反汇编引擎的选择与改造是怎样的,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

指令 函数 接口 支持 改造 代码 地址 分析 引擎 选择 字符 字符串 符号 结果 调试器 内存 效率 数据 语法 过程 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 镇江新品联想服务器维修电话 360首都网络安全日 公路养护段安全风险数据库 网络安全知识 技能考核计划 谷歌服务器端口 互联网科技电商资讯 应城市公安局网络安全课 高中毕业软件开发哪里好 网络工程师能做网络安全方面吗 上交大网络安全学院复试 网络安全 主流舆论媒体 数据库和消息队列区别 陕西数控套料软件开发商 linux服务器创建虚拟环境 深圳软件开发维护 杭州企业软件开发团队 工信部网络安全和信息化建设 成都苹果匠软件开发有限公司 网络安全的第一负责人是谁 h99服务器正确的用户名和密码 经济危机下软件开发者生态 明日之后阿尔亚湖服务器大全 传奇服务器新武器 物联网网络技术框架 残疾人自学网络技术 华为平板t1-a21w网络服务器繁忙 争做网络安全文明人征文怎么写 洛奇英雄传无法读取服务器 数据库主要有哪五类构成 如何读取服务器硬盘序列号
0