├── golang_rev.py └── readme.md /golang_rev.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # vim:fenc=utf-8 4 | # 5 | # Copyright © 2020 wlz 6 | # 7 | # Distributed under terms of the MIT license. 8 | 9 | import idc 10 | import idaapi 11 | import idautils 12 | import ida_bytes 13 | import ida_name 14 | 15 | GOLANG_FUNC = "golang_rev:golang_func" 16 | GOLANG_STRING = "golang_rev:golang_string" 17 | RENAME_POINTER = 'golang_rev:rename_pointer' 18 | 19 | if idaapi.IDA_SDK_VERSION < 740: 20 | Qword = idc.Qword 21 | MakeQword = idc.MakeQword 22 | MakeStr = idc.MakeStr 23 | MakeName = idc.MakeName 24 | Name = idc.Name 25 | Dword = idc.Dword 26 | GetString = idc.GetString 27 | else: 28 | Qword = ida_bytes.get_qword 29 | Dword = ida_bytes.get_dword 30 | MakeQword = idc.create_qword 31 | MakeStr = idc.create_strlit 32 | 33 | def MakeName(ea, name): 34 | return idc.set_name(ea, name, ida_name.SN_CHECK) 35 | 36 | def Name(ea): 37 | return idc.get_name(ea, ida_name.GN_VISIBLE) 38 | 39 | def GetString(ea, length=-1, strtype=0): 40 | return idc.get_strlit_contents(ea, length, strtype).decode() 41 | 42 | 43 | class menu_action_handler_t(idaapi.action_handler_t): 44 | """ 45 | Action handler for menu actions 46 | """ 47 | 48 | def __init__(self, action): 49 | idaapi.action_handler_t.__init__(self) 50 | self.action = action 51 | 52 | def activate(self, ctx): 53 | if self.action == GOLANG_STRING: 54 | self.set_string() 55 | elif self.action == GOLANG_FUNC: 56 | self.set_function() 57 | elif self.action == RENAME_POINTER: 58 | self.rename_pointer() 59 | else: 60 | return 0 61 | return 1 62 | 63 | def update(self, ctx): 64 | return idaapi.AST_ENABLE_ALWAYS 65 | 66 | def set_string(self): 67 | start = idc.here() 68 | str_len = idaapi.ask_long(0, "string len...") 69 | if str_len: 70 | MakeStr(start, start + str_len) 71 | return 1 72 | 73 | def rename_pointer(self): 74 | name = 'p_{}'.format(Name(Qword(idc.here()))) 75 | MakeName(idc.here(), name) 76 | 77 | def set_function(self): 78 | try: 79 | base = idautils.ida_segment.get_segm_by_name('.gopclntab').start_ea 80 | except: 81 | print("Cannot get segment .gopclntab!") 82 | return 0 83 | ea = base + 8 84 | len = Qword(ea) * 8 * 2 85 | ptr = base + 8 + 8 86 | end = base + len 87 | while ptr <= end: 88 | MakeQword(ptr) 89 | func_addr = Qword(ptr) 90 | MakeQword(ptr + 8) 91 | name_offset = Qword(ptr + 8) 92 | name_addr = Dword(base + 8 + name_offset) + base 93 | name = GetString(name_addr) 94 | name = name.replace('.', '_') \ 95 | .replace("<-", '_chan_left_') \ 96 | .replace('*', '_ptr_') \ 97 | .replace('-', '_') \ 98 | .replace(';', '') \ 99 | .replace('"', '') \ 100 | .replace('\\\\', '') 101 | name = name.replace('(', '') \ 102 | .replace(')', '') \ 103 | .replace('/', '_') \ 104 | .replace(' ', '_') \ 105 | .replace(',', 'comma') \ 106 | .replace('{', '') \ 107 | .replace('}', '') 108 | MakeName(func_addr, name) 109 | print(name) 110 | print(ptr) 111 | ptr += 16 112 | idc.jumpto(idc.get_name_ea_simple('main_main')) 113 | return 1 114 | 115 | 116 | class UI_Hook(idaapi.UI_Hooks): 117 | def __init__(self): 118 | idaapi.UI_Hooks.__init__(self) 119 | 120 | def finish_populating_widget_popup(self, form, popup): 121 | form_type = idaapi.get_widget_type(form) 122 | 123 | if form_type == idaapi.BWN_DISASM or form_type == idaapi.BWN_DUMP: 124 | t0, t1, view = idaapi.twinpos_t(), idaapi.twinpos_t( 125 | ), idaapi.get_current_viewer() 126 | if idaapi.read_selection(view, t0, t1) \ 127 | or idc.get_item_size(idc.get_screen_ea()) > 1: 128 | idaapi.attach_action_to_popup(form, popup, GOLANG_FUNC, None) 129 | idaapi.attach_action_to_popup(form, popup, GOLANG_STRING, None) 130 | idaapi.attach_action_to_popup(form, popup, RENAME_POINTER, 131 | None) 132 | 133 | 134 | class Golang_Rev(idaapi.plugin_t): 135 | flags = idaapi.PLUGIN_UNL 136 | comment = "Golang_Rev" 137 | 138 | help = "" 139 | wanted_name = "Golang_Rev" 140 | wanted_hotkey = "" 141 | 142 | def init(self): 143 | self.hexrays_inited = False 144 | self.registered_actions = [] 145 | self.registered_hx_actions = [] 146 | 147 | global ARCH 148 | global BITS 149 | ARCH = idaapi.ph_get_id() 150 | info = idaapi.get_inf_structure() 151 | if info.is_64bit(): 152 | BITS = 64 153 | elif info.is_32bit(): 154 | BITS = 32 155 | else: 156 | BITS = 16 157 | 158 | print("Golang_Rev plugin has been loaded.") 159 | 160 | # Register menu actions 161 | menu_actions = ( 162 | idaapi.action_desc_t(GOLANG_STRING, "Set golang string", 163 | menu_action_handler_t(GOLANG_STRING), None, 164 | None, 9), 165 | idaapi.action_desc_t(GOLANG_FUNC, "Set golang function", 166 | menu_action_handler_t(GOLANG_FUNC), None, 167 | None, 9), 168 | idaapi.action_desc_t(RENAME_POINTER, "Set pointer", 169 | menu_action_handler_t(RENAME_POINTER), None, 170 | None, 9), 171 | ) 172 | for action in menu_actions: 173 | idaapi.register_action(action) 174 | self.registered_actions.append(action.name) 175 | 176 | # Add ui hook 177 | self.ui_hook = UI_Hook() 178 | self.ui_hook.hook() 179 | 180 | return idaapi.PLUGIN_KEEP 181 | 182 | def run(self, arg): 183 | pass 184 | 185 | def term(self): 186 | if hasattr(self, "ui_hook"): 187 | self.ui_hook.unhook() 188 | 189 | # Unregister actions 190 | for action in self.registered_actions: 191 | idaapi.unregister_action(action) 192 | 193 | 194 | def PLUGIN_ENTRY(): 195 | return Golang_Rev() 196 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # golang rev 2 | 3 | 一个ida的golang逆向插件。 4 | 5 | ## 功能 6 | 7 | 主要功能: 8 | 9 | - 快速解析`.gopclntab`段恢复函数名, 并自动跳转到`mian_main`函数 10 | - 通过指针头和长度快速设置字符串 11 | - 快速进行指针重命名 12 | 13 | ## 使用 14 | 15 | 将golang_rev.py放到`/ida/plugins`目录下。 16 | 17 | 重新启动ida, 载入去符号的golang二进制文件,分析中多使用右键菜单中的功能。 18 | 19 | 开始享受快捷吧。:wink: 20 | 21 | ## 注意 22 | 23 | 在设置字符串时,调用`MakeStr`字符串, 在某些版本可能出现的问题, 通过修改对应python文件解决: 24 | 25 | ```python 26 | # /ida/python/idc_bc695.py 27 | # 原 28 | def MakeStr(ea, endea): return create_strlit(ea, 0 if (endea) == ida_idaapi.BADADDR else endea-ea) 29 | # 修改后 30 | def MakeStr(ea, endea): return create_strlit(ea, endea) 31 | ``` 32 | 33 | ## 声明: 34 | 35 | 此插件的uihook部分编写仿照[lazyida插件](https://github.com/L4ys/LazyIDA)。 36 | 37 | ## 演示 38 | 39 | * 快速设置函数 40 | 41 | ![](https://i.loli.net/2020/07/22/mwXqKR8fHZcpbgT.gif) 42 | 43 | * 设置字符串 44 | 45 | ![](https://i.loli.net/2020/07/22/nGMKN3Yxs5mgQC2.gif) 46 | 47 | * 设置指针 48 | 49 | ![](https://i.loli.net/2020/07/22/WA9rXTsfoRmSCYv.gif) --------------------------------------------------------------------------------