IDA Pro > IDA Pro教程 > 技术问题 > IDA Pro反编译器SDK

IDA Pro反编译器SDK

发布时间:2022-10-11 17: 28: 46

Below is the full source code of a sample plugin. It performs a quite useful transformation of the pseudocode: replaces zeroes in pointer contexts with NULLs. A NULL immediately conveys the idea that the current expression is pointer-related. This is especially useful for unknown function arguments.

 

The plugin is fully automatic. It hooks to the decompiler events and waits for the pseudocode to be ready. At that moment it takes control and modifies the ctree.

 

The conversion is performed by the convert_zeroes() function. It visits all expressions of the ctree and checks for pointer contexts. If a expression has a pointer type, then the make_null_if_zero() function is called for it. This function checks if the expression is a zero constant and converts it if necessary.

 

The plugin can be turned on or off by its menu item in the Plugins submenu.

 

The code is short and straightforward. Use it as a template for your plugins.

 

 

/*
*      Hex-Rays Decompiler project
*      Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com
*      ALL RIGHTS RESERVED.
*
*      Sample plugin for Hex-Rays Decompiler.
*      It automatically replaces zeroes in pointer contexts with NULLs.
*      For example, expression like
*
*              funcptr = 0;
*
*      will be displayed as
*
*              funcptr = NULL;
*
*      Due to highly dynamic nature of the decompier output, we must
*      use the decompiler events to accomplish the task. The plugin will
*      wait for the ctree structure to be ready in the memory and will
*      replace zeroes in pointer contexts with NULLs.
*
*/

#include

// Hex-Rays API pointer
hexdsp_t *hexdsp = NULL;

static bool inited = false;

static const char nodename[] = “$ hexrays NULLs”;
static const char null_type[] = “MACRO_NULL”;
//————————————————————————–
// Is the plugin enabled?
// The user can disable it. The plugin will save the on/off switch in the
// current database.
static bool is_enabled(void)
{
 netnode n(nodename); // use a netnode to save the state
 return n.altval(0) == 0; // if the long value is positive, then disabled
}

//————————————————————————–
// If the expression is zero, convert it to NULL
static void make_null_if_zero(cexpr_t *e)
{
 if ( e->is_zero_const() && !e->type.is_ptr() )
 { // this is plain zero, convert it
   number_format_t &nf = e->n->nf;
   nf.flags = enum_flag();
   nf.serial = 0;
   nf.type_name = null_type;
   e->type = tinfo_t::get_stock(STI_PVOID);
 }
}

//————————————————————————–
// Convert zeroes of the ctree to NULLs
static void convert_zeroes(cfunc_t *cfunc)
{
 // To represent NULLs, we will use the MACRO_NULL enumeration
 // Normally it is present in the loaded tils but let’s verify it
 if ( !get_named_type(NULL, null_type, NTF_TYPE) )
 {
   msg(“%s type is missing, cannot convert zeroes to NULLs\n”, null_type);
   return;
 }

 // We derive a helper class from ctree_visitor_t
 // The ctree_visitor_t is a base class to derive
 // ctree walker classes.
 // You have to redefine some virtual functions
 // to do the real job. Here we redefine visit_expr() since we want
 // to examine and modify expressions.
 struct ida_local zero_converter_t : public ctree_visitor_t
 {
   zero_converter_t(void) : ctree_visitor_t(CV_FAST) {}
   int idaapi visit_expr(cexpr_t *e)
   {
     // verify if the current expression has pointer expressions
     // we handle the following patterns:
     //  A. ptr = 0;
     //  B. func(0); where argument is a pointer
     //  C. ptr op 0 where op is a comparison
     switch ( e->op )
     {
       case cot_asg:   // A
         if ( e->x->type.is_ptr() )
           make_null_if_zero(e->y);
         break;

       case cot_call:  // B
         {
           carglist_t &args = *e->a;
           for ( int i=0; i < args.size(); i++ ) // check all arguments
           {
             carg_t &a = args[i];
             if ( a.formal_type.is_ptr_or_array() )
               make_null_if_zero(&a);
           }
         }
         break;

       case cot_eq:    // C
       case cot_ne:
       case cot_sge:
       case cot_uge:
       case cot_sle:
       case cot_ule:
       case cot_sgt:
       case cot_ugt:
       case cot_slt:
       case cot_ult:
         // check both sides for zeroes
         if ( e->y->type.is_ptr() )
           make_null_if_zero(e->x);
         if ( e->x->type.is_ptr() )
           make_null_if_zero(e->y);
         break;

       default:
         break;

     }
     return 0; // continue walking the tree
   }
 };
 zero_converter_t zc;
 // walk the whole function body
 zc.apply_to(&cfunc->body, NULL);
}

//————————————————————————–
// This callback will detect when the ctree is ready to be displayed
// and call convert_zeroes() to create NULLs
static ssize_t idaapi callback(void *, hexrays_event_t event, va_list va)
{
 if ( event == hxe_maturity )
 {
   cfunc_t *cfunc = va_arg(va, cfunc_t*);
   ctree_maturity_t mat = va_argi(va, ctree_maturity_t);
   if ( mat == CMAT_FINAL ) // ctree is ready, time to convert zeroes to NULLs
     convert_zeroes(cfunc);
 }
 return 0;
}

//————————————————————————–
// Initialize the plugin.
int idaapi init(void)
{
 if ( !init_hexrays_plugin() )
   return PLUGIN_SKIP; // no decompiler
 if ( is_enabled() ) // null plugin is enabled?
 {
   install_hexrays_callback(callback, NULL);
   const char *hxver = get_hexrays_version();
   msg(“Hex-rays version %s has been detected, %s ready to use\n”, hxver, PLUGIN.wanted_name);
 }
 inited = true;
 return PLUGIN_KEEP;
}

//————————————————————————–
void idaapi term(void)
{
 if ( inited )
 {
   // clean up
   remove_hexrays_callback(callback, NULL);
   term_hexrays_plugin();
 }
}

//————————————————————————–
bool idaapi run(size_t)
{
 // since all real work is done in the callbacks, use the main plugin entry
 // to turn it on and off.
 // display a message explaining the purpose of the plugin:
 int code = askbuttons(
      “~E~nable”,
      “~D~isable”,
      “~C~lose”,
      –1,
      “AUTOHIDE NONE\n”
      “Sample plugin for Hex-Rays decompiler.\n”
      “\n”
      “This plugin is fully automatic.\n”
      “It detects zeroes in pointer contexts and converts them into NULLs.\n”
      “\n”
      “The current state of the plugin is: %s\n”,
      is_enabled() ? “ENABLED” : “DISABLED”);
 switch ( code )
 {
   case –1:    // close
     break;
   case 0:     // disable
   case 1:     // enable
     netnode n;
     n.create(nodename);
     n.altset(0, code == 0);
     if ( code )
       install_hexrays_callback(callback, NULL);
     else
       remove_hexrays_callback(callback, NULL);
     info(“The %s plugin has been %s.”, PLUGIN.wanted_name, code ? “ENABLED” : “DISABLED”);
     break;
 }
 return true;
}

//————————————————————————–
static char comment[] = “Sample2 plugin for Hex-Rays decompiler”;

//————————————————————————–
//
//      PLUGIN DESCRIPTION BLOCK
//
//————————————————————————–
plugin_t PLUGIN =
{
 IDP_INTERFACE_VERSION,
 0,                    // plugin flags
 init,                 // initialize
 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
 “”,                   // multiline help about the plugin
 “Hex-Rays NULL converter”, // the preferred short name of the plugin
 “”                    // the preferred hotkey to run the plugin
};

 

中文翻译如下:

以下是一个示例插件的完整源代码。它执行一个非常有用的伪代码转换:将指针上下文中的零替换为NULL。NULL立即传达了当前表达式与指针相关的概念。这对于未知的函数参数尤其有用。

 

该插件是完全自动化的。它钩入反编译器事件并等待伪代码准备就绪。在那一刻,它接管并修改ctree。

 

转换是由convert_zeroes()函数执行的。它访问ctree的所有表达式并检查指针上下文。如果一个表达式具有指针类型,则为它调用make_null_if_zero()函数。此函数检查表达式是否为零常量并在必要时进行转换。

 

该插件可以通过插件子菜单中的菜单项打开或关闭。

 

代码短小简单。可以将其用作插件的模板。

/*

* Hex-Rays Decompiler project

* Copyright (c) 2007-2019 by Hex-Rays, support@hex-rays.com

* ALL RIGHTS RESERVED.

*

* Sample plugin for Hex-Rays Decompiler.

* It automatically replaces zeroes in pointer contexts with NULLs.

* For example, expression like

*

* funcptr = 0;

*

* will be displayed as

*

* funcptr = NULL;

*

* Due to highly dynamic nature of the decompier output, we must

* use the decompiler events to accomplish the task. The plugin will

* wait for the ctree structure to be ready in the memory and will

* replace zeroes in pointer contexts with NULLs.

*

*/

 

#include

 

// Hex-Rays API pointer

hexdsp_t *hexdsp = NULL;

 

static bool inited = false;

 

static const char nodename[] = “$ hexrays NULLs”;

static const char null_type[] = “MACRO_NULL”;

//————————————————————————–

// Is the plugin enabled?

// The user can disable it. The plugin will save the on/off switch in the

// current database.

static bool is_enabled(void)

{

netnode n(nodename); // use a netnode to save the state

return n.altval(0) == 0; // if the long value is positive, then disabled

}

 

//————————————————————————–

// If the expression is zero, convert it to NULL

static void make_null_if_zero(cexpr_t *e)

{

if ( e->is_zero_const() && !e->type.is_ptr() )

{ // this is plain zero, convert it

number_format_t &nf = e->n->nf;

nf.flags = enum_flag();

nf.serial = 0;

nf.type_name = null_type;

e->type = tinfo_t::get_stock(STI_PVOID);

}

}

 

//————————————————————————–

// Convert zeroes of the ctree to NULLs

static void convert_zeroes(cfunc_t *cfunc)

{

// To represent NULLs, we will use the MACRO_NULL enumeration

// Normally it is present in the loaded tils but let’s verify it

if ( !get_named_type(NULL, null_type, NTF_TYPE) )

{

msg(“%s type is missing, cannot convert zeroes to NULLs\n”, null_type);

return;

}

 

// We derive a helper class from ctree_visitor_t

// The ctree_visitor_t is a base class to derive

// ctree walker classes.

// You have to redefine some virtual functions

// to do the real job. Here we redefine visit_expr() since we want

// to examine and modify expressions.

struct ida_local zero_converter_t : public ctree_visitor_t

{

zero_converter_t(void) : ctree_visitor_t(CV_FAST) {}

int idaapi visit_expr(cexpr_t *e)

{

// verify if the current expression has pointer expressions

// we handle the following patterns:

// A. ptr = 0;

// B. func(0); where argument is a pointer

// C. ptr op 0 where op is a comparison

switch ( e->op )

{

case cot_asg: // A

if ( e->x->type.is_ptr() )

make_null_if_zero(e->y);

break;

 

case cot_call: // B

{

carglist_t &args = *e->a;

for ( int i=0; i < args.size(); i++ ) // check all arguments

{

carg_t &a = args[i];

if ( a.formal_type.is_ptr_or_array() )

make_null_if_zero(&a);

}

}

break;

 

case cot_eq: // C

case cot_ne:

case cot_sge:

case cot_uge:

case cot_sle:

case cot_ule:

case cot_sgt:

case cot_ugt:

case cot_slt:

case cot_ult:

// check both sides for zeroes

if ( e->y->type.is_ptr() )

make_null_if_zero(e->x);

if ( e->x->type.is_ptr() )

make_null_if_zero(e->y);

break;

 

default:

break;

 

}

return 0; // continue walking the tree

}

};

zero_converter_t zc;

// walk the whole function body

zc.apply_to(&cfunc->body, NULL);

}

 

//————————————————————————–

// This callback will detect when the ctree is ready to be displayed

// and call convert_zeroes() to create NULLs

static ssize_t idaapi callback(void *, hexrays_event_t event, va_list va)

{

if ( event == hxe_maturity )

{

cfunc_t *cfunc = va_arg(va, cfunc_t*);

ctree_maturity_t mat = va_argi(va, ctree_maturity_t);

if ( mat == CMAT_FINAL ) // ctree is ready, time to convert zeroes to NULLs

convert_zeroes(cfunc);

}

return 0;

}

 

//————————————————————————–

// Initialize the plugin.

int idaapi init(void)

{

if ( !init_hexrays_plugin() )

return PLUGIN_SKIP; // no decompiler

if ( is_enabled() ) // null plugin is enabled?

{

install_hexrays_callback(callback, NULL);

const char *hxver = get_hexrays_version();

msg(“Hex-rays version %s has been detected, %s ready to use\n”, hxver, PLUGIN.wanted_name);

}

inited = true;

return PLUGIN_KEEP;

}

 

//————————————————————————–

void idaapi term(void)

{

if ( inited )

{

// clean up

remove_hexrays_callback(callback, NULL);

term_hexrays_plugin();

}

}

 

//————————————————————————–

bool idaapi run(size_t)

{

// since all real work is done in the callbacks, use the main plugin entry

// to turn it on and off.

// display a message explaining the purpose of the plugin:

int code = askbuttons(

“~E~nable”,

“~D~isable”,

“~C~lose”,

–1,

“AUTOHIDE NONE\n”

“Sample plugin for Hex-Rays decompiler.\n”

“\n”

“This plugin is fully automatic.\n”

“It detects zeroes in pointer contexts and converts them into NULLs.\n”

“\n”

“The current state of the plugin is: %s\n”,

is_enabled() ? “ENABLED” : “DISABLED”);

switch ( code )

{

case –1: // close

break;

case 0: // disable

case 1: // enable

netnode n;

n.create(nodename);

n.altset(0, code == 0);

if ( code )

install_hexrays_callback(callback, NULL);

else

remove_hexrays_callback(callback, NULL);

info(“The %s plugin has been %s.”, PLUGIN.wanted_name, code ? “ENABLED” : “DISABLED”);

break;

}

return true;

}

 

//————————————————————————–

static char comment[] = “Sample2 plugin for Hex-Rays decompiler”;

 

//————————————————————————–

//

// PLUGIN DESCRIPTION BLOCK

//

//————————————————————————–

plugin_t PLUGIN =

{

IDP_INTERFACE_VERSION,

0, // plugin flags

init, // initialize

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

“”, // multiline help about the plugin

“Hex-Rays NULL converter”, // the preferred short name of the plugin

“” // the preferred hotkey to run the plugin

};

展开阅读全文

标签:

读者也访问过这里:
邀请您进入交流群 点击扫码
400-8765-888 kefu@makeding.com

专业销售为您服务

欢迎添加好友,了解更多IDA优惠信息,领逆向工程学习资料礼包1份!
热门文章
exe反编译工具哪个好?反编译能力强的工具盘点
随着软件技术的发展,exe(可执行文件)已经成为了电脑、手机等多个平台上的主要软件运行格式,而对于exe文件的反编译也成为了逆向工程中不可缺少的一个步骤。本文将介绍一些常用的exe反编译工具,并评价其优缺点,帮助读者选择合适的工具。
2023-04-12
idapro怎么改为中文
IDA Pro是一款功能强大的反汇编和反编译工具,广泛应用于逆向工程和软件开发领域。在使用IDA Pro时,如果我们不习惯英文界面,可以将其改为中文界面。本文将介绍IDA Pro怎么改为中文界面。IDA Pro界面改成中文主要有两种方法,下面是详细介绍。
2023-04-19
c++反编译工具有哪些
反编译C++代码的工具一般是针对可执行文件和库文件的反汇编和逆向分析工具。本文将给大家介绍c++反编译工具有哪些的内容。市面说的c++反编译工具有很多,下面介绍几款使用认识较多的软件。
2023-04-23
ida怎么查找字符串 ida字符串窗口快捷键
在数字化时代,逆向工程作为解密软件和分析程序的关键技术,正日益受到广泛关注。在逆向分析的过程中,IDA(Interactive DisAssembler)是一款备受推崇的工具,它为逆向工程师们提供了强大的功能和灵活的操作。本文将带您深入探讨如何在IDA中查找字符串,优化字符串窗口的使用,并探讨IDA如何将变量转换成字符串,帮助您更加熟练地驾驭这一工具,为逆向分析的世界增添一抹精彩。
2023-09-27
ida如何转伪代码 ida伪代码怎么看
IDA Pro是一款常用的反汇编和反编译工具,可以帮助我们分析二进制文件的实现细节和执行过程,以便更好地理解程序的执行过程和逻辑。在进行逆向工程的过程中,我们经常需要将反汇编结果转换为伪代码,以便更好地进行分析和修改。本文将介绍如何使用IDA Pro转换为伪代码,并简单讲解ida伪代码怎么看。
2023-04-14
最新文章
ida设置断点怎么运行 ida断点在键盘上的使用方法
在使用IDA pro进行逆向分析的过程中,断点设置是最基础也是最常用的调试手段之一。尤其是在处理复杂的汇编逻辑或定位关键执行点时,合理地设置并运行断点,能够极大提升分析效率与准确度。本文将围绕ida设置断点怎么运行,ida断点在键盘上的使用方法两个关键问题展开,详细介绍IDA pro中的断点操作方式、快捷键使用逻辑及其在多架构平台上的适配特性,帮助用户在实战中更加高效掌控IDA pro的调试能力。
2025-09-28
IDA调试MBR切换到16位模式 IDA调试Apk修改寄存器v0
在逆向分析中,MBR和APK分别代表底层引导机制与上层移动应用的典型研究对象。前者常涉及16位实模式与汇编流程控制的深入理解,后者则要求熟练掌握Smali代码、寄存器模拟与调试器调用。IDA pro作为广泛应用的逆向工具,不仅支持对MBR类二进制的低位调试,也能在APK分析中发挥符号识别与寄存器控制优势。本文将围绕IDA调试MBR切换到16位模式和IDA调试Apk修改寄存器v0两个核心主题展开操作细节讲解。
2025-09-28
IDA逆向QT控件应用程序 qt获取窗口内所有控件
在逆向分析跨平台图形界面程序的实践中,QT框架的广泛应用对逆向人员提出了更高要求。QT采用信号与槽、动态UI加载等机制,传统Windows API分析手段难以适配。利用IDA pro进行QT应用程序的逆向分析,结合符号信息、vtable结构及动态控件创建逻辑,可以有效提取界面控件层级、信号连接机制等核心信息。同时,若拥有源码或调试权限,还可以通过QT原生函数如`findChildren`等方式实现对窗口中所有控件的枚举与分析。本文将围绕IDA逆向QT控件应用程序和qt获取窗口内所有控件两大主题进行详细讲解。
2025-09-28
IDA pro修改so教程 IDA pro修改exe
在逆向分析与二进制安全研究中,IDA pro作为主流静态分析工具,其强大的反汇编与重构能力,广泛应用于ELF格式的so库与PE格式的exe文件修改。通过IDA pro修改so文件,可用于Android应用补丁、破解函数逻辑、绕过验证;而对exe文件的修改则常用于Windows下的补丁、功能改写与程序定制。掌握IDA pro修改so与exe的流程,不仅能提升分析效率,更是逆向工程技能的基础能力。以下内容将系统讲解IDA pro修改so教程,IDA pro修改exe两大操作场景的具体步骤,帮助用户完整掌握二进制修改流程。
2025-09-28
IDA pro中修改remote GDB路径 IDA pro修改加载地址
在进行逆向分析或调试远程目标设备时,IDA pro作为静态与动态分析的核心工具,配合GDB远程调试功能可以实现对嵌入式、IoT系统乃至裸机程序的高效控制。而在不同项目中,经常会需要变更remote GDB路径或重新设定加载地址,这些操作看似简单,实则涉及IDA pro配置逻辑、GDB插件加载机制、调试环境变量等多个技术细节。本文将围绕IDA pro中修改remote GDB路径,IDA pro修改加载地址两大关键点 ,以助于用户更好掌控IDA pro调试行为。
2025-09-28
ida反汇编成c语言的三个步骤 怎样将反汇编代码转换成c语言代码
在逆向工程、安全分析以及老旧系统维护的实践中,如何借助IDA将汇编语言转化为C语言,是许多技术人员迫切关注的主题。IDA作为目前最成熟的反汇编工具之一,配合Hex-Rays Decompiler插件,可以将目标二进制程序自动生成接近C语言语义的伪代码,从而帮助开发者更快速理解程序逻辑、重构核心功能。本文围绕“ida反汇编成c语言的三个步骤,怎样将反汇编代码转换成c语言代码”这一主题,从实际操作出发,详细讲解整个转化过程。
2025-09-28

通过微信咨询我们

欢迎添加好友,了解更多IDA优惠信息,领取逆向工程学习资料礼包1份!

读者也喜欢这些内容: