Tiny microcode optimizer 【微碼優化器 】

注:ida pro7.4及以後版本纔有這功能。

It is not a surprise to hear the IDA and Decompiler cannot handle all possible cases and eventually fail to recognize a construct, optimize an expression and represent it in its simplest form. It is perfectly understandable — nobody has resources to handle everything. This is why we publish a rich API that can be used to enhance the analysis and add your own optimization rules.

聽到IDA和Decompiler無法處理所有可能的情況並最終無法識別構造,優化表達式並以最簡單的形式表示它,這不足爲奇。 完全可以理解-沒有人有能力處理所有事情。 因此,我們發佈了豐富的API,可用於增強分析並添加您自己的優化規則。

Let us consider the decompiler. Currently, we focus on the compiler-generated code because hand-crafted code can use literally infinite number of tricks to confuse an automatic tool, not to mention seasoned reverses. Nevertheless, some users still want our decompiler to handle some assembler constructs that are usually not used by a compiler. To be concrete, let us take the following example:

讓我們考慮反編譯器。 當前,我們專注於編譯器生成的代碼,因爲手工編寫的代碼可以使用字面上無數的技巧來混淆自動工具,更不用說經驗豐富的反向技巧了。 儘管如此,一些用戶仍然希望我們的反編譯器處理一些編譯器通常不使用的彙編器結構。 具體來說,讓我們以以下示例爲例:

x | ~x

This expression always evaluates to -1 (all bits set) but the decompiler does not know about this fact and does not have a dedicated optimization rule for it. However, it is pretty easy to implement a very short plugin for that. The core of the plugin will take just a few lines to carry out the optimization:

該表達式的計算結果始終爲-1(所有位均已設置),但是反編譯器不知道這一事實,也沒有專用的優化規則。 但是,爲此實現一個非常短的插件非常容易。 插件的核心僅需幾行即可進行優化:

if ins.opcode == m_or and ins.r.is_insn(m_bnot) and ins.l == ins.r.d.l:
   if not ins.l.has_side_effects(): # avoid destroying side effects
       ins.opcode = m_mov
       ins.l.make_number(-1, ins.r.size)
       ins.r = mop_t()
       self.cnt = self.cnt + 1 # number of changes we made

We check if the current instruction is an OR of an operand with its binary negation. If so, we check for the side effects because we do not want to remove function calls, for example. If everything is fine, we replace x|~x with -1 and increment the number of changes that we made to the microcode. 

我們檢查當前指令是否爲操作數or與它的二進制取反。 如果是這樣,我們將檢查副作用,因爲例如,我們不想刪除函數調用。 如果一切正常,則將x |〜x替換爲-1,並增加對微碼所做的更改次數。

The rest is just boilerplate code. The full text of the plugin and a sample database are available below.

剩下的只是樣板代碼。 插件的全文和示例數據庫在下面提供。

We hope this very short post and the tiny plugin will inspire you to write more complex optimization rules.

我們希望這篇簡短的文章和這個小插件能激發您編寫更復雜的優化規則。

be_ornot_be.py

#
#      Hex-Rays Decompiler project
#      Copyright (c) 2007-2020 by Hex-Rays, [email protected]
#      ALL RIGHTS RESERVED.
#
#      Sample plugin for Hex-Rays Decompiler.
#      It installs a custom microcode optimization rule:
#        x | ~x => -1
#
#      To see this plugin in action please use be_ornot_be.idb
#

from ida_hexrays import *
import ida_idaapi

# recognize "x | ~x" and replace by -1
class subinsn_optimizer_t(minsn_visitor_t):
    cnt = 0
    def __init__(self):
        minsn_visitor_t.__init__(self)
    def visit_minsn(self):      # for each instruction...
        ins = self.curins       # take a reference to the current instruction

        # THE CORE OF THE PLUGIN IS HERE:
        # check the pattern "x | ~x"
        if ins.opcode == m_or and ins.r.is_insn(m_bnot) and ins.l == ins.r.d.l:
            if not ins.l.has_side_effects(): # avoid destroying side effects
                # pattern matched, convert to "mov -1, ..."
                ins.opcode = m_mov
                ins.l.make_number(-1, ins.r.size)
                ins.r = mop_t()
                self.cnt = self.cnt + 1 # number of changes we made
        return 0 # continue traversal

# a custom instruction optimizer, boilerplate code
class sample_optimizer_t(optinsn_t):
    def __init__(self):
        optinsn_t.__init__(self)
    def func(self, blk, ins, optflags):
        opt = subinsn_optimizer_t()
        ins.for_all_insns(opt)
        if opt.cnt != 0:                # if we modified microcode,
            blk.mba.verify(True)        # run the verifier
        return opt.cnt                  # report the number of changes

# a plugin interface, boilerplate code
class my_plugin_t(ida_idaapi.plugin_t):
    flags = ida_idaapi.PLUGIN_HIDE
    wanted_name = "optimize x|~x"
    wanted_hotkey = ""
    comment = ""
    help = ""
    def init(self):
        if init_hexrays_plugin():
            self.optimizer = sample_optimizer_t()
            self.optimizer.install()
            print("Installed sample optimizer for 'x | ~x'")
            return ida_idaapi.PLUGIN_KEEP # keep us in the memory
    def term(self):
            self.optimizer.remove()
    def run(self):
            pass

def PLUGIN_ENTRY():
    return my_plugin_t()

idb 地址:

https://www.hex-rays.com/wp-content/uploads/2020/04/be_ornot_be.idb

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章