snowfox 发表于 2018-4-18 09:20

IDA7.0 Hexlight插件修改增强版

本帖最后由 snowfox 于 2018-4-18 09:33 编辑

IDA网站上 Hexlight 高亮插件在查看比较大的函数时, 能快速定位方便很多
但是有时比较复杂的圆括号嵌套, 不容易一眼看出对应关系, 常常要复制到其它编辑器中查看
因此对原有的Hexlight插件做了修改增强. 支持圆括号'()'和方括号'[]'的高亮显示,
定位时鼠标在要定位的括号后面点击
首先上图:

修改后的代码如下:
# highlighting plugin for Hex-Rays Decompiler
# Copyright (c) 2016
# Milan Bohacek <milan.bohacek+hexlight@gmail.com>
# All rights reserved.
#
# ==============================================================================
#
# This file is part of Hexlight.
#
# Hexlight is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.If not, see <http://www.gnu.org/licenses/>.
#
# ==============================================================================


import idautils
import idaapi
import idc


import traceback

hexlight_cb_info = None
hexlight_cb = None

posledni = 0

def jump(custom_viewer, line):
    (pl, x, y) = idaapi.get_custom_viewer_place(custom_viewer, False)
    pl2 = idaapi.place_t_as_simpleline_place_t(pl.clone())
    oldline = pl2.n
    pl2.n = line
    idaapi.jumpto(custom_viewer, pl2, x, y)
    return oldline

class hexrays_callback_info(object):
   
    def __init__(self):
      self.vu = None
      self.highlights = {}
      self.highl_brack = {}
      self.hicolor = 0x646464                #0xF2E8BF #0x00ffff00
      self.theotherline = None
      self.safe = False
      return
   
    def clearall(self, ps, refresh=True):
      ctr = 0
      for i in self.highlights:
            try:            
                ps.bgcolor = self.highlights
                ctr += 1
            except:
                pass
#               place_t_as_simpleline_place_t
#            ps.line.replace("\x04{\x04", "{")
#            ps.line.replace("\x04}\x04", "}")
               
      self.highlights = {}
      self.theotherline = None
      if((ctr > 0) and refresh):
            idaapi.refresh_idaview_anyway()

    def clearbracket(self, ps, refresh=True):
      ctr = 0
      for i in self.highl_brack:
            try:            
                ps.line = self.highl_brack
                ctr += 1
                #print('clear' + ps.line)
            except:
                pass
            
      self.highl_brack = {}
      if((ctr > 0) and refresh):
            idaapi.refresh_idaview_anyway()   
            
    def highlight_bracket2(self, ps, pos_brach, xpos, ypos):
      ln = ps.line[:]
      if (self.highl_brack.has_key(ypos) == False):
            self.clearbracket(ps, True)
            self.highl_brack = ln
      else:
            ln = self.highl_brack

      s1pos = idaapi.tag_advance(ln, pos_brach)
      s2pos = idaapi.tag_advance(ln, xpos)
      line = list(ln)
      while (line != idaapi.SCOLOR_ON or line != idaapi.SCOLOR_SYMBOL):
            s1pos += 1
            if (s1pos > len(line)):
                return
      while (line != idaapi.SCOLOR_ON or line != idaapi.SCOLOR_SYMBOL):
            s2pos += 1
            if (s2pos > len(line)):
                return

      line = idaapi.SCOLOR_ERROR
      line = idaapi.SCOLOR_ERROR
      line = idaapi.SCOLOR_ERROR
      line = idaapi.SCOLOR_ERROR
      ps.line = ''.join(line)      
      idaapi.refresh_idaview_anyway()
   
    def rfind_match_brack(self, start, strline, brack1, brack2):
      i = 0
      while (start >= 0) :
            if (strline == brack1):
                i = i + 1
            elif (strline == brack2):
                i = i - 1
            if (i == 0) :
                #find match
                return start
            start = start - 1
            
      return -1   
      
    def find_match_brack(self, start, strline, brack1, brack2):
      i = 0
      while (start < len(strline)) :
            if (strline == brack1):
                i = i + 1
            elif (strline == brack2):
                i = i - 1
            if (i == 0) :
                #find match
                return start
            start = start + 1
            
      return -1                  

    def event_callback(self, event, *args):
      try:
#            print "event: %d"%event
            if event == idaapi.hxe_keyboard:
                vu, keycode, shift = args

                if idaapi.lookup_key_code(keycode, shift, True) == idaapi.get_key_code("B") and shift == 0:
                  if self.theotherline:
                        self.theotherline = jump(vu.ct, self.theotherline)
                  return 0


            if event <= idaapi.hxe_print_func:
                self.safe = False

            if event == idaapi.hxe_switch_pseudocode:
                self.safe = False

            if event == idaapi.hxe_func_printed:
                self.safe = True

            if event == idaapi.hxe_text_ready:
                self.safe = True

            if event == idaapi.hxe_curpos:
                if not self.safe:
                  return 0
                #print "1"
                self.vu = args

                if not self.vu:
                  return 0
                #print "2"

                if self.vu.cfunc.maturity != idaapi.CMAT_FINAL:
                  return 0
                #print "3"

                if not self.vu.visible():
                  return 0
                #print "4"
                if not self.vu.refresh_cpos(idaapi.USE_KEYBOARD):
               #   print "refresh_cpos failed"
                  return 0
                pos = self.vu.cpos
                ypos = pos.lnnum
                xpos = pos.x
                #print "cursor click %d %d %d" % (pos.x, pos.y, pos.lnnum)

                if self.highlights.has_key(ypos):
                  return 0
                #print "5"

                ps = self.vu.cfunc.get_pseudocode()
                #print "6"
                #print "ypos:%d"%ypos
                #print "ps.line: %s"%(ps.line)

                #line = "%i, chr(i)) for i in
                #range(1,0x40) ]
                #ps.line = ''.join(line);
                #ps.line = '\x04'.join(line);
                #line = "%i,
                #chr(i)), chr(i+1)) for i in range(1,0x40) ]
                #ps.line = ''.join(line);
                #ps.line = '\x04'.join(line);
                ln = ps.line[:]
                curline = idaapi.tag_remove(ln)
                #print "7"

                #print curline
               
                if (xpos > 1 and xpos <= len(curline)):
                  chPrev = curline
                  
                  if (chPrev == ')'):
                        pos_brach = self.rfind_match_brack(xpos - 1, curline, ')', '(')
                        if (pos_brach != -1) :
                            self.highlight_bracket2(ps, pos_brach, xpos-1, ypos)
                  elif (chPrev == '('):
                        pos_brach = self.find_match_brack(xpos - 1, curline, '(', ')')
                        if (pos_brach != -1) :
                            self.highlight_bracket2(ps, pos_brach, xpos-1, ypos)
                  elif (chPrev == ']'):
                        pos_brach = self.rfind_match_brack(xpos - 1, curline, ']', '[')
                        if (pos_brach != -1) :
                            self.highlight_bracket2(ps, pos_brach, xpos-1, ypos)
                  elif (chPrev == '['):
                        pos_brach = self.find_match_brack(xpos - 1, curline, '[', ']')
                        if (pos_brach != -1) :
                            self.highlight_bracket2(ps, pos_brach, xpos-1, ypos)
                  else:
                        self.clearbracket(ps, True)
                else:
                  self.clearbracket(ps, True)
                     
                idxO = curline.find('{')
                idxC = curline.find('}')
                #print "O:", idxO, " C: ",idxC
                #there is no need to highlight first and last {
                #print "8"

                if (idxO >= 0) or (idxC >= 0):
                #   print "9"
                  self.clearall(ps, False)

                  self.highlights = ps.bgcolor

                  ps.bgcolor = self.hicolor
                  
                  dir = 1
                  bracechar = '}'
                  idx = idxO

                  if (idxC >= 0):
                        dir = -1
                        bracechar = '{'
                        idx = idxC

                  j = ypos + dir

                  max = len(ps)
               #   print "max: ",max

                  while (j >= 0) and (j < max):
                #       print "10"
                        #print "j:", j
                        ln = idaapi.tag_remove(ps.line)
                        if ln.find(bracechar) == idx:
                            if not(self.highlights.has_key(j)):
                              self.highlights = ps.bgcolor
                            #ps.line = ps.line.replace(bracechar,
                            #idaapi.COLSTR("\x04"+bracechar+"\x04", "\x27"))
                            #ps.line = ps.line.replace(bracechar,
                            #idaapi.COLSTR(bracechar, chr(52)))
                            ps.bgcolor = self.hicolor
                            self.theotherline = j
                            break
                        j+=dir
                  
                  idaapi.refresh_idaview_anyway()
                else:
                  self.clearall(ps)
                #print "11"
                return 0
      except:
            traceback.print_exc()
      
      return 0

def remove():
    if hexlight_cb:
      idaapi.remove_hexrays_callback(hexlight_cb)

class HexHLightPlugin_t(idaapi.plugin_t):
    flags = idaapi.PLUGIN_HIDE
    comment = "highlights the matching brace in Pseudocode-View"
    help = "press B to jump to the matching brace"
    wanted_name = "HexLight"
    wanted_hotkey = ""

    def init(self):
      # Some initialization
      global hexlight_cb_info, hexlight_cb

      if idaapi.init_hexrays_plugin():
            hexlight_cb_info = hexrays_callback_info()
            hexlight_cb = hexlight_cb_info.event_callback
            if not idaapi.install_hexrays_callback(hexlight_cb):
            #    print "could not install hexrays_callback"
                return idaapi.PLUGIN_SKIP
            print "Hexlight plugin installed Mod by Snow"
            addon = idaapi.addon_info_t()
            addon.id = "milan.bohacek.hexlight"
            addon.name = "Hexlight"
            addon.producer = "Milan Bohacek"
            addon.url = "milan.bohacek+hexlight@gmail.com"
            addon.version = "6.95"
            idaapi.register_addon(addon)
            return idaapi.PLUGIN_KEEP
      #print "init_hexrays_plugin failed"
      return idaapi.PLUGIN_SKIP

    def run(self, arg=0):
      return

    def term(self):
      remove()

def PLUGIN_ENTRY():
    return HexHLightPlugin_t()



脚本下载

snowfox 发表于 2019-12-22 12:48

剑舞 发表于 2019-12-22 07:53
发现看比较大的函数时,拖动滚动条高亮就不见了。

拖动滚动条, 光标位置就发生了变化, 高亮于是就重新计算没有了

snowfox 发表于 2018-4-18 20:03

lxf 发表于 2018-4-18 13:51
请问为什么会这样

这是大括号的跳转, 按B可以跳到对应的大括号去

Vvvvvoid 发表于 2018-4-18 09:24

感觉python语法 还是很高雅的

yikuaidao 发表于 2018-4-18 09:40

不错的插件,感谢共享

后天2333 发表于 2018-4-18 09:43

感谢发布原创作品,吾爱破解论坛因你更精彩!

gamezx 发表于 2018-4-18 09:48

看着舒服多了。感谢分享

一片小朵朵 发表于 2018-4-18 09:53

感谢楼主分享

Loopher 发表于 2018-4-18 10:22

感谢分享

书中妍如钰 发表于 2018-4-18 10:55

eclips能用吗

lxf 发表于 2018-4-18 13:51


请问为什么会这样

SeeAua 发表于 2018-4-18 16:23

感谢分享!
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: IDA7.0 Hexlight插件修改增强版