├── .gitignore ├── README.md ├── go_entry.py └── GO_Utils ├── GoStrings.py ├── Gopclntab.py ├── Utils.py ├── Firstmoduledata.py ├── __init__.py └── Types.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IDAGolangHelper 2 | Set of IDA Pro scripts for parsing GoLang types information stored in compiled binary 3 | 4 | 5 | This is update for https://gitlab.com/zaytsevgu/GoUtils2.0 6 | 7 | Differences: 8 | 1. Add support for go1.8 and go1.9, go1.10 (well actually it seems no difference from go1.9) 9 | 2. Automatically add user-defined types to IDA. (Can be checked in Shift+f9 view) 10 | 3. Add some not very advanced string recognition. You can press Shift+S to process current function 11 | 12 | 13 | https://2016.zeronights.ru/wp-content/uploads/2016/12/GO_Zaytsev.pdf - My presentation about Golang reversing 14 | -------------------------------------------------------------------------------- /go_entry.py: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------- 2 | # This is an example illustrating how to use the Form class 3 | # (c) Hex-Rays 4 | # 5 | import GO_Utils 6 | idaapi.require("GO_Utils") 7 | idaapi.require("GO_Utils.Gopclntab") 8 | idaapi.require("GO_Utils.Utils") 9 | idaapi.require("GO_Utils.Firstmoduledata") 10 | idaapi.require("GO_Utils.Types") 11 | idaapi.require("GO_Utils.GoStrings") 12 | 13 | from idaapi import Form 14 | 15 | GO_SETTINGS = GO_Utils.GoSettings() 16 | 17 | # 18 | # -------------------------------------------------------------------------- 19 | class MyForm(Form): 20 | def __init__(self): 21 | self.invert = False 22 | Form.__init__(self, r"""STARTITEM {id:cGoVers} 23 | GoLoader 24 | 25 | {FormChangeCb} 26 | <##Try to detemine go version based on moduledata:{iButton1}> 27 | <##Try to detemine go version based on version string:{iButton2}> 28 | <##Rename functions:{iButton3}> 29 | Go version: 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {cGoVers}> 40 | <##Add standard go types:{iButton4}> 41 | <##Parse types by moduledata:{iButton5}> 42 | """, { 43 | 'iButton1': Form.ButtonInput(self.OnButton1), 44 | 'iButton2': Form.ButtonInput(self.OnButton2), 45 | 'iButton3': Form.ButtonInput(self.OnButton3), 46 | 'iButton4': Form.ButtonInput(self.OnButton4), 47 | 'iButton5': Form.ButtonInput(self.OnButton5), 48 | 'cGoVers': Form.RadGroupControl(("r2", "r3","r4","r5","r6","r7", "r8", "r9", "r10", "r16", "r17")), 49 | 'FormChangeCb': Form.FormChangeCb(self.OnFormChange), 50 | }) 51 | 52 | 53 | def OnButton1(self, code=0): 54 | GO_SETTINGS.findModuleData() 55 | print(GO_SETTINGS.tryFindGoVersion()) 56 | 57 | 58 | def OnButton3(self, code=0): 59 | GO_SETTINGS.renameFunctions() 60 | 61 | def OnButton2(self, code=0): 62 | print(GO_SETTINGS.getVersionByString()) 63 | 64 | def OnButton4(self, code=0): 65 | typ = self.GetControlValue(self.cGoVers) 66 | GO_SETTINGS.createTyper(typ) 67 | 68 | def OnButton5(self, code=0): 69 | typ = self.GetControlValue(self.cGoVers) 70 | GO_SETTINGS.typesModuleData(typ) 71 | 72 | 73 | def OnFormChange(self, fid): 74 | return 1 75 | 76 | 77 | 78 | # -------------------------------------------------------------------------- 79 | 80 | # -------------------------------------------------------------------------- 81 | def ida_main(): 82 | # Create form 83 | global f 84 | idaapi.add_hotkey("Shift-S", GO_Utils.GoStrings.stringify) 85 | f = MyForm() 86 | 87 | # Compile (in order to populate the controls) 88 | f.Compile() 89 | 90 | # Execute the form 91 | ok = f.Execute() 92 | 93 | # Dispose the form 94 | f.Free() 95 | 96 | # -------------------------------------------------------------------------- 97 | 98 | # 99 | 100 | 101 | # -------------------------------------------------------------------------- 102 | ida_main() -------------------------------------------------------------------------------- /GO_Utils/GoStrings.py: -------------------------------------------------------------------------------- 1 | import idc 2 | import idaapi 3 | import idautils 4 | import ida_bytes 5 | 6 | #Simple function to fix strings in current function 7 | #Mostly based on "Tim 'diff' Strazzere" ideas 8 | 9 | def parseOp(operand): 10 | if operand.type == idaapi.o_displ or operand.type == idaapi.o_phrase: 11 | if operand.reg == 4: #esp/rsp 12 | return True, operand.addr 13 | return False, 0 14 | 15 | def convert_operand(operand, size, num, pos): 16 | if operand.type == idaapi.o_displ or operand.type == idaapi.o_phrase: 17 | if operand.reg == 4: #esp/rsp 18 | if operand.addr < size: 19 | idc.OpHex(pos, num) 20 | 21 | #Well for now I don't know how determine ptr size ;[ 22 | def is_this_a_real_string(next_pos, instr, size_data): 23 | #Common scenario is when we mov offset into register 24 | #and after that either fill local string variable or push string as argument 25 | #so we just check that we use esp 26 | next_instr = idautils.DecodeInstruction(next_pos) 27 | if next_instr.get_canon_mnem() == "mov": 28 | is_stack_used, ptr_addr = parseOp(next_instr.Op1) 29 | if is_stack_used is True: 30 | #Check if we really place our offset 31 | if next_instr.Op2.type == idaapi.o_reg and next_instr.Op2.reg == instr.Op1.reg: 32 | next_pos += next_instr.size 33 | next_instr = idautils.DecodeInstruction(next_pos) 34 | if next_instr.get_canon_mnem() == "mov": 35 | is_stack_used, size_addr = parseOp(next_instr.Op1) 36 | #if we filling string or at least smthng looking very similar 37 | if is_stack_used is True and (size_addr - ptr_addr == size_data): 38 | #for now explicitly set 0x1000 as max string size 39 | if next_instr.Op2.type == idaapi.o_imm and next_instr.Op2.value < 0x1000: 40 | return True, next_instr.Op2.value 41 | return False, 0 42 | 43 | def make_string(addr, siz): 44 | print("Creating string at %x %d size" % (addr, siz)) 45 | ida_bytes.del_items(addr, siz) 46 | ida_bytes.create_strlit(addr, siz, -1) 47 | 48 | def get_bitness_bytes(addr): 49 | if idc.get_segm_attr(addr, idc.SEGATTR_BITNESS) == 2: 50 | return 8 51 | return 4 52 | 53 | def stringify(): 54 | ea = idc.here() 55 | size_data = get_bitness_bytes(ea) 56 | f = idaapi.get_func(ea) 57 | frsize = idc.get_func_attr(ea, idc.FUNCATTR_FRSIZE) 58 | position = f.start_ea 59 | size = 0 60 | while position < f.end_ea: 61 | instr = idautils.DecodeInstruction(position) 62 | if instr is None: 63 | print("%x: Not and instruction found" % position) 64 | break 65 | mnem = instr.get_canon_mnem() 66 | if mnem == "mov": 67 | if instr.Op2.type == idaapi.o_imm and instr.Op1.type == idaapi.o_reg: #this may be string load 68 | is_string, size_s = is_this_a_real_string(position + instr.size, instr, size_data) 69 | if is_string is True: 70 | make_string(instr.Op2.value, size_s) 71 | elif mnem == "lea": 72 | if instr.Op2.type == idaapi.o_mem and instr.Op1.type == idaapi.o_reg: 73 | is_string, size_s = is_this_a_real_string(position + instr.size, instr, size_data) 74 | if is_string is True: 75 | make_string(instr.Op2.addr, size_s) 76 | position += instr.size 77 | -------------------------------------------------------------------------------- /GO_Utils/Gopclntab.py: -------------------------------------------------------------------------------- 1 | import idc 2 | import idautils 3 | import idaapi 4 | import ida_bytes 5 | import ida_funcs 6 | import ida_search 7 | import ida_segment 8 | from . import Utils 9 | 10 | info = idaapi.get_inf_structure() 11 | try: 12 | is_be = info.is_be() 13 | except: 14 | is_be = info.mf 15 | 16 | lookup = "FF FF FF FB 00 00" if is_be else "FB FF FF FF 00 00" 17 | lookup16 = "FF FF FF FA 00 00" if is_be else "FA FF FF FF 00 00" 18 | 19 | def check_is_gopclntab(addr): 20 | ptr = Utils.get_bitness(addr) 21 | first_entry = ptr.ptr(addr+8+ptr.size) 22 | first_entry_off = ptr.ptr(addr+8+ptr.size*2) 23 | addr_func = addr+first_entry_off 24 | func_loc = ptr.ptr(addr_func) 25 | if func_loc == first_entry: 26 | return True 27 | return False 28 | 29 | def check_is_gopclntab16(addr): 30 | ptr = Utils.get_bitness(addr) 31 | offset = 8 + ptr.size *6 32 | # print(f"{addr+offset:x}") 33 | first_entry = ptr.ptr(addr+offset) + addr 34 | # print(f"{first_entry:x}") 35 | func_loc = ptr.ptr(first_entry) 36 | struct_ptr = ptr.ptr(first_entry+8) + first_entry 37 | first_entry = ptr.ptr(struct_ptr) 38 | if func_loc == first_entry: 39 | return True 40 | return False 41 | 42 | def findGoPcLn(): 43 | possible_loc = ida_search.find_binary(0, idc.BADADDR, lookup, 16, idc.SEARCH_DOWN) #header of gopclntab 44 | while possible_loc != idc.BADADDR: 45 | if check_is_gopclntab(possible_loc): 46 | return possible_loc 47 | else: 48 | #keep searching till we reach end of binary 49 | possible_loc = ida_search.find_binary(possible_loc+1, idc.BADADDR, lookup, 16, idc.SEARCH_DOWN) 50 | possible_loc = ida_search.find_binary(0, idc.BADADDR, lookup16, 16, idc.SEARCH_DOWN) #header of gopclntab 51 | while possible_loc != idc.BADADDR: 52 | print(f"found possible 1.16 gopclntab") 53 | if check_is_gopclntab16(possible_loc): 54 | print("Looks like this is go1.16 binary") 55 | return possible_loc 56 | else: 57 | #keep searching till we reach end of binary 58 | possible_loc = ida_search.find_binary(possible_loc+1, idc.BADADDR, lookup16, 16, idc.SEARCH_DOWN) 59 | return None 60 | 61 | 62 | def rename(beg, ptr, make_funcs = True): 63 | base = beg 64 | pos = beg + 8 #skip header 65 | size = ptr.ptr(pos) 66 | pos += ptr.size 67 | end = pos + (size * ptr.size * 2) 68 | print("%x" % end) 69 | while pos < end: 70 | offset = ptr.ptr(pos + ptr.size) 71 | ptr.maker(pos) #in order to get xrefs 72 | ptr.maker(pos+ptr.size) 73 | pos += ptr.size * 2 74 | ptr.maker(base+offset) 75 | func_addr = ptr.ptr(base+offset) 76 | if make_funcs == True: 77 | ida_bytes.del_items(func_addr, 1, ida_bytes.DELIT_SIMPLE) 78 | ida_funcs.add_func(func_addr) 79 | name_offset = idc.get_wide_dword(base+offset+ptr.size) 80 | name = idc.get_strlit_contents(base + name_offset) 81 | name = Utils.relaxName(name) 82 | Utils.rename(func_addr, name) 83 | 84 | 85 | def rename16(beg, ptr, make_funcs = True): 86 | base = beg 87 | first_entry = ptr.ptr(base+ptr.size * 6 + 8) + base 88 | 89 | cnt = ptr.ptr(base + 8) 90 | funcname_start = base + 8 + ptr.size *7 91 | for i in range(cnt): 92 | struct_ptr = ptr.ptr(first_entry + i*ptr.size*2 + 8) + first_entry 93 | # print(f"{struct_ptr:x}") 94 | func_addr = ptr.ptr(first_entry + i*ptr.size*2) 95 | str_val = ida_bytes.get_dword(struct_ptr+8) + funcname_start 96 | name = ida_bytes.get_strlit_contents(str_val, -1, -1) 97 | print(f"{func_addr:x} {name}") 98 | if make_funcs == True: 99 | ida_bytes.del_items(func_addr, 1, ida_bytes.DELIT_SIMPLE) 100 | ida_funcs.add_func(func_addr) 101 | # print(type(name)) 102 | name = Utils.relaxName(name.decode()) 103 | Utils.rename(func_addr, name) 104 | 105 | # fcn_name_offset = ptr.ptr(strict) 106 | # offset = ptr.ptr(pos + ptr.size) 107 | # ptr.maker(pos) #in order to get xrefs 108 | # ptr.maker(pos+ptr.size) 109 | # pos += ptr.size * 2 110 | # ptr.maker(base+offset) 111 | # func_addr = ptr.ptr(base+offset) 112 | # if make_funcs == True: 113 | # ida_bytes.del_items(func_addr, 1, ida_bytes.DELIT_SIMPLE) 114 | # ida_funcs.add_func(func_addr) 115 | # name_offset = idc.get_wide_dword(base+offset+ptr.size) 116 | # name = idc.get_strlit_contents(base + name_offset) 117 | # name = Utils.relaxName(name) 118 | # Utils.rename(func_addr, name) 119 | -------------------------------------------------------------------------------- /GO_Utils/Utils.py: -------------------------------------------------------------------------------- 1 | import ida_enum 2 | import ida_struct 3 | import idc 4 | import string 5 | import random 6 | 7 | class bitZ(object): 8 | def __init__(self, ptr, size, maker): 9 | self.ptr = ptr 10 | self.size = size 11 | self.maker = maker 12 | 13 | 14 | bits32 = bitZ(idc.get_wide_dword, 4, idc.create_dword) 15 | bits64 = bitZ(idc.get_qword, 8, idc.create_qword) 16 | 17 | 18 | def id_generator(size=6, chars=string.ascii_uppercase + string.digits): 19 | return ''.join(random.choice(chars) for _ in range(size)) 20 | 21 | 22 | def rename(offset, name): 23 | res = idc.set_name(offset, name, idc.SN_NOWARN) 24 | if res == 0: 25 | name = name+"_autogen_"+id_generator() 26 | idc.set_name(offset, name, idc.SN_NOWARN) 27 | 28 | 29 | def relaxName(name): 30 | name = name.replace('.', '_').replace("<-", '_chan_left_').replace('*', '_ptr_').replace('-', '_').replace(';','').replace('"', '').replace('\\', '') 31 | name = name.replace('(', '').replace(')', '').replace('/', '_').replace(' ', '_').replace(',', 'comma').replace('{','').replace('}', '').replace('[', '').replace(']', '') 32 | return name 33 | 34 | 35 | def get_bitness(addr): 36 | ptr = bits32 37 | if idc.get_segm_attr(addr, idc.SEGATTR_BITNESS) == 2: 38 | ptr = bits64 39 | return ptr 40 | 41 | 42 | def is_hardcoded_slice(addr, bt_obj): 43 | #compiled slices will have valid ptr 44 | if bt_obj.ptr(bt_obj.ptr(addr)) == idc.BADADDR: 45 | return False 46 | addr = addr + bt_obj.size 47 | val1 = bt_obj.ptr(addr) 48 | val2 = bt_obj.ptr(addr + bt_obj.size) 49 | if val1 != val2: 50 | return False 51 | return True 52 | 53 | 54 | class StructCreator(object): 55 | 56 | def __init__(self, bt_obj): 57 | self.types_id = {} 58 | if bt_obj.size == 8: 59 | self.uintptr = (idc.FF_QWORD|idc.FF_DATA, -1, bt_obj.size) 60 | else: 61 | self.uintptr = (idc.FF_DWORD | idc.FF_DATA, -1, bt_obj.size) 62 | 63 | self.baseptr = (idc.FF_DWORD | idc.FF_DATA, 0, 4) 64 | 65 | def configBase(self, robase): 66 | self.baseptr = (idc.FF_DWORD|idc.FF_0OFF, robase, 4) 67 | 68 | def createStruct(self, name): 69 | sid = ida_struct.get_struc_id(name) 70 | if sid != idc.BADADDR: 71 | idc.del_struc(sid) 72 | sid = idc.add_struc(-1, name, 0) 73 | self.types_id['name'] = sid 74 | return sid 75 | 76 | def fillStruct(self, sid, data): 77 | for i in data: 78 | new_type = None 79 | #(i1, i2, i3) = self.stepper.parseField(i[1]) 80 | name = i[1] 81 | if name[0] == "*": 82 | name = name[1:] 83 | 84 | member_sid = ida_struct.get_struc_id(i[1]) 85 | if i[1] == 'baseptr': 86 | i1, i2, i3 = self.baseptr 87 | elif i[1] == 'uintptr': 88 | i1, i2, i3 = self.uintptr 89 | elif member_sid != idc.BADADDR: 90 | i1, i2, i3 = (idc.FF_STRUCT, member_sid, ida_struct.get_struc_size(member_sid)) 91 | elif i[1].endswith(' *'): # It is a pointer to some class 92 | i1, i2, i3 = self.uintptr 93 | else: 94 | i1,i2,i3 = (idc.FF_BYTE|idc.FF_DATA, -1, 1) 95 | 96 | if name == i[1]: 97 | new_type = i[1] 98 | else: 99 | new_type = name + " *" 100 | res = idc.add_struc_member(sid, i[0], -1, i1, i2, i3) 101 | use_name = i[0] 102 | if res == -1: #Bad name 103 | #print("Bad name %s for struct member" % i[0]) 104 | use_name = i[0] + "_autogen_"+id_generator() 105 | idc.add_struc_member(sid, use_name, -1, i1, i2, i3) 106 | if new_type is not None: 107 | offset = idc.get_member_offset(sid, use_name) 108 | #print("Setting %s as %s" % (i[0], new_type)) 109 | idc.SetType(idc.get_member_id(sid, offset), new_type) 110 | 111 | def makeStruct(self, i): 112 | print("Creating structure %s" % (i[0])) 113 | sid = self.createStruct(i[0]) 114 | self.fillStruct(sid, i[1]) 115 | 116 | def createTypes(self, types): 117 | for i in types: 118 | self.makeStruct(i) 119 | 120 | def createEnum(self, enum): 121 | eid = idc.add_enum(-1, enum[0], 0x1100000) #what is this flag? 122 | ida_enum.set_enum_bf(eid, 1) 123 | val = 0 124 | mask = 0x1f 125 | ida_enum.set_enum_width(eid, 1) 126 | for i in enum[1]: 127 | idc.add_enum_member(eid, i, val, mask) 128 | val += 1 129 | 130 | def createEnums(self, enums): 131 | for i in enums: 132 | self.createEnum(i) 133 | 134 | -------------------------------------------------------------------------------- /GO_Utils/Firstmoduledata.py: -------------------------------------------------------------------------------- 1 | from . import Utils 2 | import idautils 3 | import struct 4 | 5 | def findFirstModuleData(addr, bt): 6 | # print(f"{addr:x}") 7 | possible_addr = [x for x in idautils.XrefsTo(addr)] 8 | for p_a in possible_addr: 9 | # print(f"Checking addr: {p_a}") 10 | if Utils.is_hardcoded_slice(p_a.frm, bt): 11 | return p_a.frm 12 | elif Utils.is_hardcoded_slice(p_a.frm+bt.size, bt): 13 | return p_a.frm 14 | return None 15 | 16 | def isGo17(addr, bt): 17 | addr += bt.size * 27 18 | addr2 = addr + bt.size * 6 # for go1.7 this addr will be for modulename 19 | return Utils.is_hardcoded_slice(addr, bt) and (not Utils.is_hardcoded_slice(addr2, bt)) 20 | 21 | 22 | def isGo18_10(addr, bt): 23 | addr += bt.size * 27 24 | addr2 = addr + bt.size * 6 # for go1.8 this addr will be for itablinks 25 | return Utils.is_hardcoded_slice(addr, bt) and (Utils.is_hardcoded_slice(addr2, bt)) 26 | 27 | def isGo116(addr, bt): 28 | addr += bt.size * 1 29 | # addr2 = addr + bt.size * 6 # for go1.8 this addr will be for itablinks 30 | return Utils.is_hardcoded_slice(addr, bt) 31 | 32 | def getTypeinfo17(addr, bt): 33 | addr2 = addr + bt.size * 25 34 | robase = bt.ptr(addr2) 35 | addr += bt.size * 27 36 | beg = bt.ptr(addr) 37 | size = bt.ptr(addr+bt.size) 38 | return beg, beg+size*4, robase 39 | 40 | 41 | def getTypeinfo18(addr, bt): 42 | addr2 = addr + bt.size * 25 43 | robase = bt.ptr(addr2) 44 | addr += bt.size * 30 45 | beg = bt.ptr(addr) 46 | size = bt.ptr(addr+bt.size) 47 | return beg, beg+size*4, robase 48 | 49 | def getTypeinfo116(addr, bt): 50 | addr2 = addr + bt.size * 35 51 | robase = bt.ptr(addr2) 52 | addr += bt.size * 40 53 | beg = bt.ptr(addr) 54 | size = bt.ptr(addr+bt.size) 55 | print(robase) 56 | return beg, beg+size*4, robase 57 | 58 | def getTypeinfo117(addr, bt): 59 | return getTypeinfo116(addr, bt) 60 | 61 | def getTypeinfo(addr, bt): 62 | addr += bt.size * 25 63 | beg = bt.ptr(addr) 64 | size = bt.ptr(addr+bt.size) 65 | 66 | return beg, beg+size*bt.size 67 | 68 | """ 69 | 1.16 70 | type moduledata struct { 71 | 0 pcHeader *pcHeader 72 | 1 funcnametab []byte 73 | 4 cutab []uint32 74 | 7 filetab []byte 75 | 10 pctab []byte 76 | 13 pclntable []byte 77 | 16 ftab []functab 78 | 19 findfunctab uintptr 79 | 20 minpc, maxpc uintptr 80 | 81 | 22 text, etext uintptr 82 | 24 noptrdata, enoptrdata uintptr 83 | 26 data, edata uintptr 84 | 28 bss, ebss uintptr 85 | 30 noptrbss, enoptrbss uintptr 86 | 32 end, gcdata, gcbss uintptr 87 | 35 types, etypes uintptr 88 | 89 | 37 textsectmap []textsect 90 | 40 typelinks []int32 // offsets from types 91 | itablinks []*itab 92 | 93 | ptab []ptabEntry 94 | 95 | pluginpath string 96 | pkghashes []modulehash 97 | 98 | modulename string 99 | modulehashes []modulehash 100 | 101 | hasmain uint8 // 1 if module contains the main function, 0 otherwise 102 | 103 | gcdatamask, gcbssmask bitvector 104 | 105 | typemap map[typeOff]*_type // offset to *_rtype in previous module 106 | 107 | bad bool // module failed to load and should be ignored 108 | 109 | next *moduledata 110 | } 111 | 1.10 - same as 1.10 112 | 1.9 - same as 1.8 113 | 1.8 114 | type moduledata struct { 115 | 3 pclntable []byte 116 | 6 ftab []functab 117 | 9 filetab []uint32 118 | 119 | 10 findfunctab uintptr 120 | 12 minpc, maxpc uintptr 121 | 14 text, etext uintptr 122 | 16 noptrdata, enoptrdata uintptr 123 | 18 data, edata uintptr 124 | 20 bss, ebss uintptr 125 | 22 noptrbss, enoptrbss uintptr 126 | 25 end, gcdata, gcbss uintptr 127 | 27 types, etypes uintptr 128 | 30 textsectmap []textsect 129 | typelinks []int32 // offsets from types 130 | itablinks []*itab 131 | ptab []ptabEntry 132 | pluginpath string 133 | pkghashes []modulehash 134 | modulename string 135 | modulehashes []modulehash 136 | gcdatamask, gcbssmask bitvector 137 | typemap map[typeOff]*_type // offset to *_rtype in previous module 138 | next *moduledata 139 | } 140 | 141 | 1.7 142 | type moduledata struct { 143 | 3 pclntable []byte 144 | 6 ftab []functab 145 | 9 filetab []uint32 146 | 10 findfunctab uintptr 147 | 12 minpc, maxpc uintptr 148 | 149 | 14 text, etext uintptr 150 | 16 noptrdata, enoptrdata uintptr 151 | 18 data, edata uintptr 152 | 20 bss, ebss uintptr 153 | 22 noptrbss, enoptrbss uintptr 154 | 25 end, gcdata, gcbss uintptr 155 | 27 types, etypes uintptr 156 | 157 | typelinks []int32 // offsets from types 158 | itablinks []*itab 159 | 160 | modulename string 161 | modulehashes []modulehash 162 | 163 | gcdatamask, gcbssmask bitvector 164 | 165 | typemap map[typeOff]*_type // offset to *_rtype in previous module 166 | 167 | next *moduledata 168 | } 169 | """ 170 | 171 | """1.6 172 | type moduledata struct { 173 | 3 pclntable []byte 174 | 6 ftab []functab 175 | 9 filetab []uint32 176 | 10 findfunctab uintptr 177 | 12 minpc, maxpc uintptr 178 | 179 | 14 text, etext uintptr 180 | 16 noptrdata, enoptrdata uintptr 181 | 18 data, edata uintptr 182 | 20 bss, ebss uintptr 183 | 22 noptrbss, enoptrbss uintptr 184 | 25 end, gcdata, gcbss uintptr 185 | 186 | typelinks []*_type 187 | 188 | modulename string 189 | modulehashes []modulehash 190 | 191 | gcdatamask, gcbssmask bitvector 192 | 193 | next *moduledata 194 | } 195 | """ 196 | """1.5 197 | type moduledata struct { 198 | 3 pclntable []byte 199 | 6 ftab []functab 200 | 9 filetab []uint32 201 | 10 findfunctab uintptr 202 | 12 minpc, maxpc uintptr 203 | 204 | 14 text, etext uintptr 205 | 16 noptrdata, enoptrdata uintptr 206 | 18 data, edata uintptr 207 | 20 bss, ebss uintptr 208 | 22 noptrbss, enoptrbss uintptr 209 | 25 end, gcdata, gcbss uintptr 210 | 211 | typelinks []*_type 212 | 213 | modulename string 214 | modulehashes []modulehash 215 | 216 | gcdatamask, gcbssmask bitvector 217 | 218 | next *moduledata 219 | } 220 | """ -------------------------------------------------------------------------------- /GO_Utils/__init__.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | from . import Gopclntab 3 | from . import Utils 4 | from . import Firstmoduledata 5 | from . import Types 6 | import idc 7 | import idautils 8 | import ida_ida 9 | import ida_search 10 | 11 | class GoSettings(object): 12 | 13 | 14 | def __init__(self): 15 | self.storage = {} 16 | self.bt_obj = Utils.get_bitness(ida_ida.inf_get_min_ea()) 17 | self.structCreator = Utils.StructCreator(self.bt_obj) 18 | self.processor = None 19 | self.typer = None 20 | self.is116 = False 21 | 22 | def getVal(self, key): 23 | if key in self.storage: 24 | return self.storage[key] 25 | return None 26 | 27 | def setVal(self, key, val): 28 | self.storage[key] = val 29 | 30 | def getGopcln(self): 31 | gopcln_addr = self.getVal("gopcln") 32 | if gopcln_addr is None: 33 | gopcln_addr = Gopclntab.findGoPcLn() 34 | print("Saving gopclntab entry") 35 | self.setVal("gopcln", gopcln_addr) 36 | return gopcln_addr 37 | 38 | def findModuleData(self): 39 | gopcln_addr = self.getGopcln() 40 | if gopcln_addr is not None: 41 | fmd = Firstmoduledata.findFirstModuleData(gopcln_addr, self.bt_obj) 42 | self.setVal("firstModData", fmd) 43 | return 44 | 45 | def tryFindGoVersion(self): 46 | fmd = self.getVal("firstModData") 47 | if fmd is None: 48 | return "This should be go <= 1.4 : No module data found" 49 | vers = "go1.5 or go1.6" 50 | if Firstmoduledata.isGo17(fmd, self.bt_obj) is True: 51 | vers = "go1.7" 52 | elif Firstmoduledata.isGo18_10(fmd, self.bt_obj) is True: 53 | vers = "go1.8 or go1.9 or go1.10" 54 | elif Firstmoduledata.isGo116(fmd, self.bt_obj) is True: 55 | vers = "go1.16" 56 | self.is116 = True 57 | return "According to moduleData struct is should be %s" % (vers) 58 | 59 | def renameFunctions(self): 60 | gopcln_tab = self.getGopcln() 61 | if self.is116: 62 | Gopclntab.rename16(gopcln_tab, self.bt_obj) 63 | else: 64 | Gopclntab.rename(gopcln_tab, self.bt_obj) 65 | 66 | def getVersionByString(self): 67 | # pos = idautils.Functions().next() 68 | end_ea = idc.get_segm_end(0) 69 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 31 36", 16, idc.SEARCH_DOWN) != idc.BADADDR: 70 | return 'Go 1.16' 71 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 31 33", 16, idc.SEARCH_DOWN) != idc.BADADDR: 72 | return 'Go 1.13' 73 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 31 32", 16, idc.SEARCH_DOWN) != idc.BADADDR: 74 | return 'Go 1.12' 75 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 31 31", 16, idc.SEARCH_DOWN) != idc.BADADDR: 76 | return 'Go 1.11' 77 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 31 30", 16, idc.SEARCH_DOWN) != idc.BADADDR: 78 | return 'Go 1.10' 79 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 39", 16, idc.SEARCH_DOWN) != idc.BADADDR: 80 | return 'Go 1.9' 81 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 38", 16, idc.SEARCH_DOWN) != idc.BADADDR: 82 | return 'Go 1.8' 83 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 37", 16, idc.SEARCH_DOWN) != idc.BADADDR: 84 | return 'Go 1.7' 85 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 36", 16, idc.SEARCH_DOWN) != idc.BADADDR: 86 | return 'Go 1.6' 87 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 35", 16, idc.SEARCH_DOWN) != idc.BADADDR: 88 | return 'Go 1.5' 89 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 34", 16, idc.SEARCH_DOWN) != idc.BADADDR: 90 | return 'Go 1.4' 91 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 33", 16, idc.SEARCH_DOWN) != idc.BADADDR: 92 | return 'Go 1.3' 93 | if ida_search.find_binary(0, end_ea, "67 6f 31 2e 32", 16, idc.SEARCH_DOWN) != idc.BADADDR: 94 | return 'Go 1.2' 95 | 96 | def createTyper(self, typ): 97 | if typ == 0: 98 | self.typer = Types.Go12Types(self.structCreator) 99 | elif typ == 1: 100 | self.typer = Types.Go14Types(self.structCreator) 101 | elif typ == 2: 102 | self.typer = Types.Go15Types(self.structCreator) 103 | elif typ == 3: 104 | self.typer = Types.Go16Types(self.structCreator) 105 | elif typ == 4 or typ == 5: 106 | self.typer = Types.Go17Types(self.structCreator) 107 | elif typ == 6: #1.9 108 | self.typer = Types.Go17Types(self.structCreator) 109 | elif typ == 7: #1.10 110 | self.typer = Types.Go17Types(self.structCreator) 111 | elif typ == 8: #1.16 112 | self.typer = Types.Go116Types(self.structCreator) 113 | elif typ == 9: #1.17 114 | self.typer = Types.Go117Types(self.structCreator) 115 | 116 | def typesModuleData(self, typ): 117 | if typ < 2: 118 | return 119 | if self.getVal("firstModData") is None: 120 | self.findModuleData() 121 | fmd = self.getVal("firstModData") 122 | if fmd is None: 123 | return 124 | if self.typer is None: 125 | self.createTyper(typ) 126 | robase = None 127 | if typ == 4: 128 | beg, end, robase = Firstmoduledata.getTypeinfo17(fmd, self.bt_obj) 129 | self.processor = Types.TypeProcessing17(beg, end, self.bt_obj, self, robase) 130 | elif typ == 5: 131 | beg, end, robase = Firstmoduledata.getTypeinfo18(fmd, self.bt_obj) 132 | self.processor = Types.TypeProcessing17(beg, end, self.bt_obj, self, robase) 133 | elif typ == 6: 134 | beg, end, robase = Firstmoduledata.getTypeinfo18(fmd, self.bt_obj) 135 | self.processor = Types.TypeProcessing19(beg, end, self.bt_obj, self, robase) 136 | elif typ == 7: 137 | beg, end, robase = Firstmoduledata.getTypeinfo18(fmd, self.bt_obj) 138 | self.processor = Types.TypeProcessing19(beg, end, self.bt_obj, self, robase) 139 | elif typ == 8: 140 | beg, end, robase = Firstmoduledata.getTypeinfo116(fmd, self.bt_obj) 141 | self.processor = Types.TypeProcessing116(beg, end, self.bt_obj, self, robase) 142 | elif typ == 9: 143 | beg, end, robase = Firstmoduledata.getTypeinfo117(fmd, self.bt_obj) 144 | self.typer.update_robase(robase) 145 | self.processor = Types.TypeProcessing117(beg, end, self.bt_obj, self, robase) 146 | else: 147 | beg, end = Firstmoduledata.getTypeinfo(fmd, self.bt_obj) 148 | self.processor = Types.TypeProcessing(beg, end, self.bt_obj, self) 149 | print("%x %x %x" % (beg, end, robase)) 150 | for i in self.processor: 151 | pass 152 | return -------------------------------------------------------------------------------- /GO_Utils/Types.py: -------------------------------------------------------------------------------- 1 | from . import Utils 2 | import ida_bytes 3 | import ida_struct 4 | import idc 5 | 6 | class GoTypes_BASE(object): 7 | def __init__(self, creator): 8 | self.standardTypes = [ 9 | ("string",[("ptr","*char"), ("len", "uintptr")]), 10 | ("slice", [("data","*char"),("len", "uintptr"), ("cap", "uintptr")]), 11 | ("__iface", [("itab","*char"),("ptr","*char")]) 12 | ] 13 | 14 | self.commonTypes = [ 15 | ("arrayType",[ 16 | ("type", "type"), 17 | ("elem", "*type"), 18 | ("slice", "*type"), 19 | ("len", "uintptr") 20 | ]), 21 | ("chanType", [ 22 | ("type", "type"), 23 | ("elem", "*type"), 24 | ("dir", "uintptr") 25 | ]), 26 | ("ptrType", [ 27 | ("type", "type"), 28 | ("elem", "*type") 29 | ]), 30 | ("sliceType", [ 31 | ("type", "type"), 32 | ("elem", "*type") 33 | ]) 34 | ] 35 | self.standardEnums = [ 36 | ("kind",[ 37 | "INVALID", "BOOL","INT","INT8", 38 | "INT16","INT32","INT64","UINT", 39 | "UINT8","UINT16","UINT32","UINT64", 40 | "UINTPTR","FLOAT32","FLOAT64","COMPLEX64", 41 | "COMPLEX128","ARRAY","CHAN","FUNC","INTERFACE","MAP","PTR","SLICE", 42 | "STRING","STRUCT","UNSAFE_PTR" 43 | ]) 44 | ] 45 | creator.createTypes(self.standardTypes) 46 | creator.createEnums(self.standardEnums) 47 | 48 | 49 | class GoTypes_l7(GoTypes_BASE): 50 | 51 | def __init__(self, creator): 52 | super(GoTypes_l7, self).__init__(creator) 53 | self.standardTypes = [ 54 | ("uncommonType", [("name", "*string"), ("pkgPath", "*string"), ("methods", "slice")]), 55 | ] 56 | #this types depends on type structure so should be created after 57 | self.commonTypes += [ 58 | ("method__", [("name", "*string"),("pkgPath","*string"),("mtype","*type"),("typ","*type"),("ifn", "void *"),("tfn","void *")]), 59 | ("structField",[ 60 | ("Name", "*string"), 61 | ("PkgPath","*string"), 62 | ("typ", "*type"), 63 | ("tag", "*string"), 64 | ("offset", "uintptr"), 65 | ]), 66 | ("structType", [ 67 | ("type","type"), 68 | ("fields", "slice") 69 | ]), 70 | ("imethod", [ 71 | ("name", "*string"), 72 | ("pkgPath", "*string"), 73 | ("typ", "*type") 74 | ]), 75 | ("interfaceType",[ 76 | ("type", "type"), 77 | ("methods", "slice") 78 | ]), 79 | ("funcType",[("type","type")]), #TODO:fix 80 | ] 81 | creator.createTypes(self.standardTypes) 82 | 83 | class Go116Types(GoTypes_BASE): 84 | def __init__(self, creator): 85 | super(Go116Types, self).__init__(creator) 86 | self.standardTypes = [ 87 | ("type", [ 88 | ("size", "uintptr"), 89 | ("ptrdata", "uintptr"), 90 | ("hash", "__int32"), 91 | ("flag", "__int8"), 92 | ("align", "__int8"), 93 | ("fieldAlign", "__int8"), 94 | ("kind", "kind"), 95 | ("equal", "*void"), 96 | ("gcdata", "*unsigned char"), 97 | ("string", "__int32"), 98 | ("ptrtothis", "__int32"), 99 | ]) 100 | ] 101 | 102 | #this types depends on type structure so should be created after 103 | self.commonTypes += [ 104 | ("uncommonType", [("pkgPath", "__int32"), ("mcount", "__int16"), ("unused1", "__int16"),("moff", "__int32"), ("unused2", "__int16")]), 105 | ("method__", [("name", "__int32"), ("mtyp", "__int32"),("ifn","__int32"), ("tfn", "__int32")]), 106 | ("structField",[ 107 | ("Name", "void *"), 108 | ("typ", "*type"), 109 | ("offset", "uintptr"), 110 | ]), 111 | ("structType", [ 112 | ("type","type"), 113 | ("pkgPath", "void *"), 114 | ("fields", "slice") 115 | ]), 116 | ("imethod", [ 117 | ("name", "__int32"), 118 | ("pkgPath", "__int32"), 119 | ]), 120 | ("interfaceType",[ 121 | ("type", "type"), 122 | ("pkgPath", "void *"), 123 | ("methods", "slice") 124 | ]), 125 | ("funcType", [ 126 | ("type", "type"), 127 | ("incount","__int16"), 128 | ("outcount", "__int16") 129 | ]), 130 | ("mapType", [ 131 | ("type", "type"), 132 | ("key","*type"), 133 | ("elem","*type"), 134 | ("bucket", "*type"), 135 | ("hasher", "void *"), 136 | ("keysize","__int8"), 137 | ("elemsize","__int8"), 138 | ("bucketsize","__int16"), 139 | ("flags","__int32"), 140 | ]) 141 | ] 142 | 143 | creator.createTypes(self.standardTypes) 144 | creator.createTypes(self.commonTypes) 145 | 146 | class Go117Types(GoTypes_BASE): 147 | def __init__(self, creator): 148 | super(Go117Types, self).__init__(creator) 149 | self.standardTypes = [ 150 | ("type", [ 151 | ("size", "uintptr"), 152 | ("ptrdata", "uintptr"), 153 | ("hash", "__int32"), 154 | ("flag", "__int8"), 155 | ("align", "__int8"), 156 | ("fieldAlign", "__int8"), 157 | ("kind", "kind"), 158 | ("equal", "*void"), 159 | ("gcdata", "*unsigned char"), 160 | ("string", "baseptr"), 161 | ("ptrtothis", "baseptr"), 162 | ]) 163 | ] 164 | 165 | #this types depends on type structure so should be created after 166 | self.commonTypes += [ 167 | ("uncommonType", [("pkgPath", "__int32"), ("mcount", "__int16"), ("unused1", "__int16"),("moff", "__int32"), ("unused2", "__int16")]), 168 | ("method__", [("name", "__int32"), ("mtyp", "__int32"),("ifn","__int32"), ("tfn", "__int32")]), 169 | ("structField",[ 170 | ("Name", "void *"), 171 | ("typ", "*type"), 172 | ("offset", "uintptr"), 173 | ]), 174 | ("structType", [ 175 | ("type","type"), 176 | ("pkgPath", "void *"), 177 | ("fields", "slice") 178 | ]), 179 | ("imethod", [ 180 | ("name", "baseptr"), 181 | ("pkgPath", "baseptr"), 182 | ]), 183 | ("interfaceType",[ 184 | ("type", "type"), 185 | ("pkgPath", "void *"), 186 | ("methods", "slice") 187 | ]), 188 | ("funcType", [ 189 | ("type", "type"), 190 | ("incount","__int16"), 191 | ("outcount", "__int16") 192 | ]), 193 | ("mapType", [ 194 | ("type", "type"), 195 | ("key","*type"), 196 | ("elem","*type"), 197 | ("bucket", "*type"), 198 | ("hasher", "void *"), 199 | ("keysize","__int8"), 200 | ("elemsize","__int8"), 201 | ("bucketsize","__int16"), 202 | ("flags","__int32"), 203 | ]) 204 | ] 205 | 206 | creator.createTypes(self.standardTypes) 207 | creator.createTypes(self.commonTypes) 208 | self.creator = creator 209 | 210 | def update_robase(self, robase): 211 | self.creator.configBase(robase) 212 | 213 | class Go17Types(GoTypes_BASE): 214 | def __init__(self, creator): 215 | super(Go17Types, self).__init__(creator) 216 | self.standardTypes = [ 217 | ("type", [ 218 | ("size", "uintptr"), 219 | ("ptrdata", "uintptr"), 220 | ("hash", "__int32"), 221 | ("flag", "__int8"), 222 | ("align", "__int8"), 223 | ("fieldAlign", "__int8"), 224 | ("kind", "kind"), 225 | ("alg", "*void"), 226 | ("gcdata", "*unsigned char"), 227 | ("string", "__int32"), 228 | ("ptrtothis", "__int32"), 229 | ]) 230 | ] 231 | 232 | #this types depends on type structure so should be created after 233 | self.commonTypes += [ 234 | ("uncommonType", [("pkgPath", "__int32"), ("mcount", "__int16"), ("unused1", "__int16"),("moff", "__int32"), ("unused2", "__int16")]), 235 | ("method__", [("name", "__int32"), ("mtyp", "__int32"),("ifn","__int32"), ("tfn", "__int32")]), 236 | ("structField",[ 237 | ("Name", "void *"), 238 | ("typ", "*type"), 239 | ("offset", "uintptr"), 240 | ]), 241 | ("structType", [ 242 | ("type","type"), 243 | ("pkgPath", "void *"), 244 | ("fields", "slice") 245 | ]), 246 | ("imethod", [ 247 | ("name", "__int32"), 248 | ("pkgPath", "__int32"), 249 | ]), 250 | ("interfaceType",[ 251 | ("type", "type"), 252 | ("pkgPath", "void *"), 253 | ("methods", "slice") 254 | ]), 255 | ("funcType", [ 256 | ("type", "type"), 257 | ("incount","__int16"), 258 | ("outcount", "__int16") 259 | ]), 260 | ("mapType", [ 261 | ("type", "type"), 262 | ("key","*type"), 263 | ("elem","*type"), 264 | ("bucket", "*type"), 265 | ("hmap", "*type"), 266 | ("keysize","__int8"), 267 | ("indirectkey","__int8"), 268 | ("valuesize","__int8"), 269 | ("indirectvalue","__int8"), 270 | ("bucketsize","__int16"), 271 | ("reflexivekey","__int8"), 272 | ("needkeyupdate","__int8"), 273 | ]) 274 | ] 275 | 276 | creator.createTypes(self.standardTypes) 277 | creator.createTypes(self.commonTypes) 278 | 279 | 280 | class Go12Types(GoTypes_l7): 281 | 282 | def __init__(self, creator): 283 | super(Go12Types, self).__init__(creator) 284 | self.types = [ 285 | ("type", [ 286 | ("size", "uintptr"), 287 | ("hash", "__int32"), 288 | ("_unused", "__int8"), 289 | ("align", "__int8"), 290 | ("fieldAlign", "__int8"), 291 | ("kind", "kind"), 292 | ("alg", "*void"), 293 | ("gc", "void *"), 294 | ("string", "*string"), 295 | ("UncommonType","*int"), 296 | ("ptrtothis", "*type"), 297 | ]), 298 | ] 299 | creator.createTypes(self.types) 300 | creator.createTypes(self.commonTypes) 301 | 302 | 303 | class Go14Types(GoTypes_l7): 304 | 305 | def __init__(self, creator): 306 | super(Go14Types, self).__init__(creator) 307 | self.types = [ 308 | ("type", [ 309 | ("size", "uintptr"), 310 | ("hash", "__int32"), 311 | ("_unused", "__int8"), 312 | ("align", "__int8"), 313 | ("fieldAlign", "__int8"), 314 | ("kind", "kind"), 315 | ("alg", "*void"), 316 | ("gcdata", "void *[2]"), 317 | ("string", "*string"), 318 | ("UncommonType","*uncommonType"), 319 | ("ptrtothis", "*type"), 320 | ("zero", "void *") 321 | ]), 322 | ] 323 | creator.createTypes(self.types) 324 | creator.createTypes(self.commonTypes) 325 | 326 | 327 | class Go15Types(GoTypes_l7): 328 | 329 | def __init__(self, creator): 330 | super(Go15Types, self).__init__(creator) 331 | self.types = [ 332 | ("type", [ 333 | ("size", "uintptr"), 334 | ("ptrdata", "uintptr"), 335 | ("hash", "__int32"), 336 | ("_unused", "__int8"), 337 | ("align", "__int8"), 338 | ("fieldAlign", "__int8"), 339 | ("kind", "kind"), 340 | ("alg", "*void"), 341 | ("gcdata", "*unsigned char"), 342 | ("string", "*string"), 343 | ("UncommonType","*uncommonType"), 344 | ("ptrtothis", "*type"), 345 | ("zero", "void *") 346 | ]) 347 | ] 348 | creator.createTypes(self.types) 349 | creator.createTypes(self.commonTypes) 350 | 351 | 352 | class Go16Types(GoTypes_l7): 353 | 354 | def __init__(self, creator): 355 | super(Go16Types, self).__init__(creator) 356 | self.types = [ 357 | ("type", [ 358 | ("size", "uintptr"), 359 | ("ptrdata", "uintptr"), 360 | ("hash", "__int32"), 361 | ("_unused", "__int8"), 362 | ("align", "__int8"), 363 | ("fieldAlign", "__int8"), 364 | ("kind", "kind"), 365 | ("alg", "*void"), 366 | ("gcdata", "*unsigned char"), 367 | ("string", "*string"), 368 | ("UncommonType","*uncommonType"), 369 | ("ptrtothis", "*type"), 370 | ]) 371 | ] 372 | creator.createTypes(self.types) 373 | creator.createTypes(self.commonTypes) 374 | 375 | 376 | class TypeProcessing(object): 377 | 378 | def __init__(self, pos, endpos, step, settings): 379 | self.pos = pos 380 | self.end = endpos 381 | self.stepper = step 382 | self.type_addr = [] 383 | self.settings = settings 384 | self.kind_types = { 385 | "CHAN": self.makeChanType, 386 | "ARRAY": self.makeArrType, 387 | "SLICE": self.makeSliceType, 388 | "STRUCT": self.makeStructType, 389 | "PTR" : self.makePtrType, 390 | "INTERFACE": self.makeInterface, 391 | "FUNC": self.makeFunc, 392 | "MAP": self.makeMap, 393 | } 394 | 395 | 396 | def __iter__(self): 397 | return self 398 | 399 | def __next__(self): 400 | if self.pos >= self.end: 401 | raise StopIteration 402 | value = self.stepper.ptr(self.pos) 403 | self.pos += self.stepper.size 404 | return self.handle_offset(value) 405 | 406 | def getDword(self, sid, addr, name): 407 | name_off = idc.get_member_offset(sid, name) 408 | return idc.get_wide_dword(addr+name_off) 409 | 410 | def getPtr(self, sid, addr, name): 411 | name_off = idc.get_member_offset(sid, name) 412 | return self.stepper.ptr(addr+name_off) 413 | 414 | def getPtrToThis(self, sid, offset): 415 | return self.getPtr(sid, offset, "ptrtothis") 416 | 417 | def getOffset(self, offset): 418 | return offset 419 | 420 | def make_arr(self, addr, arr_size, struc_size, type): 421 | res = idc.make_array(addr, arr_size) 422 | if res == False: 423 | ida_bytes.del_items(addr, arr_size*struc_size, ida_bytes.DELIT_SIMPLE) 424 | idc.SetType(addr, type) 425 | idc.make_array(addr, arr_size) 426 | 427 | 428 | def getName(self, offset): 429 | sid = ida_struct.get_struc_id("type") 430 | string_addr = offset + idc.get_member_offset(sid, "string") 431 | ptr = self.stepper.ptr(string_addr) 432 | idc.SetType(ptr, "string") 433 | name = self.stepper.ptr(ptr) 434 | return idc.GetString(name) 435 | 436 | def getKindEnumName(self, addr): 437 | struc_id = ida_struct.get_struc_id("type") 438 | offset_kind = idc.get_member_offset(struc_id, "kind") 439 | kind = idc.get_wide_byte(addr + offset_kind) & 0x1f 440 | return self.settings.typer.standardEnums[0][1][kind] 441 | 442 | 443 | def handle_offset(self, offset): 444 | #Check if we already parse this 445 | if offset in self.type_addr: 446 | return 447 | print("Processing: %x" % offset) 448 | self.type_addr.append(offset) 449 | 450 | #Set type and get name 451 | idc.SetType(offset, "type") 452 | name = self.getName(offset) 453 | idc.set_cmt(offset, name, 0) 454 | 455 | #get kind name 456 | kind_name = self.getKindEnumName(offset) 457 | print(kind_name) 458 | if name[0] == "*" and kind_name != "PTR": 459 | name = name[1:] 460 | name = Utils.relaxName(name) 461 | Utils.rename(offset, name) 462 | self.betterTypePlease(offset) 463 | sid = ida_struct.get_struc_id("type") 464 | addr = self.getPtrToThis(sid, offset) 465 | if addr != 0: 466 | addr = self.getOffset(addr) 467 | self.handle_offset(addr) 468 | return 469 | if kind_name != "FUNC": 470 | self.processUncommon(sid, offset) 471 | 472 | def betterTypePlease(self, offset): 473 | kind_name = self.getKindEnumName(offset) 474 | if kind_name in self.kind_types: 475 | self.kind_types[kind_name](offset) 476 | 477 | def makeChanType(self, offset): 478 | idc.SetType(offset, "chanType") 479 | sid = ida_struct.get_struc_id("chanType") 480 | addr = self.getPtr(sid, offset, "elem") 481 | self.handle_offset(addr) 482 | 483 | def makeSliceType(self, offset): 484 | idc.SetType(offset, "sliceType") 485 | sid = ida_struct.get_struc_id("sliceType") 486 | addr = self.getPtr(sid, offset, "elem") 487 | self.handle_offset(addr) 488 | 489 | def makeArrType(self, offset): 490 | idc.SetType(offset, "arrayType") 491 | sid = ida_struct.get_struc_id("arrayType") 492 | addr = self.getPtr(sid, offset, "elem") 493 | self.handle_offset(addr) 494 | addr = self.getPtr(sid, offset, "slice") 495 | self.handle_offset(addr) 496 | 497 | def makePtrType(self, offset): 498 | idc.SetType(offset, "ptrType") 499 | sid = ida_struct.get_struc_id("ptrType") 500 | addr = self.getPtr(sid, offset, "elem") 501 | self.handle_offset(addr) 502 | 503 | def makeStructType(self, offset): 504 | idc.SetType(offset, "structType") 505 | sid = ida_struct.get_struc_id("structType") 506 | slice_id = ida_struct.get_struc_id("slice") 507 | offset_elem = idc.get_member_offset(sid, "fields") 508 | inner_offset = idc.get_member_offset(slice_id, "data") 509 | addr = self.stepper.ptr(offset_elem + offset + inner_offset) 510 | 511 | inner_offset = idc.get_member_offset(slice_id, "len") 512 | size = self.stepper.ptr(offset+offset_elem+inner_offset) 513 | if size == 0: 514 | return 515 | idc.SetType(addr, "structField") 516 | sz = ida_struct.get_struc_size(ida_struct.get_struc_id("structField")) 517 | self.make_arr(addr, size, sz, "structField") 518 | sid_type = ida_struct.get_struc_id("type") 519 | size_new_struct = self.getPtr(sid_type, offset, "size") 520 | for i in range(size): 521 | self.processStructField(addr, i*sz) 522 | name = self.getName(offset) 523 | while name[0] == "*": 524 | name = name[1:] 525 | name = Utils.relaxName(name) 526 | name = "ut_" + name 527 | self.createUserTypeStruct(addr, name, size, size_new_struct) 528 | 529 | def processStructField(self, addr, index): 530 | offset = addr + index 531 | sid = ida_struct.get_struc_id("structField") 532 | ptr = self.getPtr(sid, offset, "Name") 533 | if ptr != 0: 534 | idc.SetType(ptr, "string") 535 | fieldName = idc.GetString(self.stepper.ptr(ptr)) 536 | Utils.rename(ptr, fieldName) 537 | ptr = self.getPtr(sid, offset, "typ") 538 | self.handle_offset(ptr) 539 | 540 | 541 | def getStructFieldOffset(self, sid, addr): 542 | return self.getPtr(sid, addr, "offset") 543 | 544 | def createUserTypeStruct(self, addr, name, size, self_size): 545 | fields = [] 546 | sid = ida_struct.get_struc_id("structField") 547 | sz = ida_struct.get_struc_size(sid) 548 | sid_type = ida_struct.get_struc_id("type") 549 | fields = [] 550 | curr_offset = 0 551 | idc.set_cmt(addr, name, 0) 552 | for i in range(size): 553 | fieldname = self.nameFromOffset(self.getPtr(sid, addr+i*sz,"Name")) 554 | type_addr = self.getPtr(sid, addr+i*sz, "typ") 555 | typename = self.getType(type_addr) 556 | size = self.getPtr(sid_type, type_addr, "size") 557 | if fieldname == "" or fieldname is None: 558 | fieldname = "unused_"+Utils.id_generator() 559 | offset = self.getStructFieldOffset(sid, addr+i*sz) 560 | print(f"Get offset: {offset:x}") 561 | if offset != curr_offset: 562 | print("Offset missmatch.Got %d expected %d. Adding padding..." % (curr_offset, offset)) 563 | if offset < curr_offset: 564 | raise("Too many bytes already") 565 | while offset != curr_offset: 566 | fields.append(("padding", "char")) 567 | curr_offset += 1 568 | curr_offset += size 569 | if size != 0: 570 | offset_kind = idc.get_member_offset(sid_type, "kind") 571 | kind_of_type = self.getKindEnumName(type_addr) 572 | print(kind_of_type) 573 | if kind_of_type == "STRUCT_": #Disabled for now 574 | name_type = self.getName(type_addr) 575 | while name_type[0] == "*": 576 | name_type = name_type[1:] 577 | name_type = Utils.relaxName(name_type) 578 | name_type = "ut_" + name_type 579 | #print("setting type %s" % name_type) 580 | fields.append((fieldname, name_type)) 581 | elif kind_of_type == "STRING": 582 | fields.append((fieldname, "string")) 583 | elif kind_of_type == "SLICE": 584 | fields.append((fieldname, "slice")) 585 | elif kind_of_type == "INTERFACE": 586 | fields.append((fieldname, "__iface")) 587 | else: 588 | fields.append((fieldname, "char [%d]" % size)) 589 | if curr_offset != self_size: 590 | print("%x: Structure size mismatch: %x" % (addr, curr_offset)) 591 | if self_size < curr_offset: 592 | raise("Too many bytes already") 593 | while self_size != curr_offset: 594 | fields.append(("padding", "char")) 595 | curr_offset += 1 596 | new_type = [(name, fields)] 597 | self.settings.structCreator.createTypes(new_type) 598 | new_type_sid = ida_struct.get_struc_id(name) 599 | sz = ida_struct.get_struc_size(new_type_sid) 600 | if sz != self_size: 601 | print("%x" % addr ) 602 | raise("Error at creating structure") 603 | 604 | def getType(self, addr): 605 | print("%x" % addr) 606 | sid = ida_struct.get_struc_id("type") 607 | name = self.getName(addr) 608 | if self.getKindEnumName(addr) != "PTR": 609 | while name[0] == "*": 610 | name = name[1:] 611 | return name 612 | 613 | def makeInterface(self, offset): 614 | idc.SetType(offset, "interfaceType") 615 | ifaceid = ida_struct.get_struc_id("interfaceType") 616 | meth_offs = idc.get_member_offset(ifaceid, "methods") 617 | slice_id = ida_struct.get_struc_id("slice") 618 | size_off = idc.get_member_offset(slice_id, "len") 619 | size = self.stepper.ptr(offset + meth_offs + size_off) 620 | if size != 0: 621 | addr = self.getPtr(slice_id, offset + meth_offs, "data") 622 | idc.SetType(addr, "imethod") 623 | sz = ida_struct.get_struc_size(ida_struct.get_struc_id("imethod")) 624 | self.make_arr(addr, size, sz, "imethod") 625 | names = self.processIMethods(addr, size) 626 | # For now only for go1.7 627 | if names is None: 628 | return 629 | name = self.getName(offset) 630 | while name[0] == "*": 631 | name = name[1:] 632 | name = Utils.relaxName(name) 633 | name = "user_interface_" + name 634 | # TODO: this is for go1.7 need additional check for other versions 635 | fields = [("inter", "void *"), ("type", "void *"), ("link", "void *"), ("bad", "__int32"), 636 | ("unused", "__int32")] 637 | for i in names: 638 | fields.append((i, "void *")) 639 | itype = [(name, fields)] 640 | self.settings.structCreator.createTypes(itype) 641 | 642 | def processIMethods(self, addr, size): 643 | return None 644 | 645 | def makeFunc(self, offset): 646 | idc.SetType(offset, "funcType") 647 | self.parseFuncType(offset) 648 | 649 | def parseFuncType(self, offset): 650 | return 651 | 652 | def makeMap(self, offset): 653 | return # TODO:fix 654 | 655 | 656 | class TypeProcessing17(TypeProcessing): 657 | 658 | def __init__(self, pos, endpos, step, settings, base_type): 659 | super(TypeProcessing17, self).__init__(pos, endpos, step, settings) 660 | self.robase = base_type 661 | 662 | def __next__(self): 663 | if self.pos >= self.end: 664 | raise StopIteration 665 | value = idc.get_wide_dword(self.pos) 666 | self.pos += 4 667 | value = self.getOffset(value) 668 | return self.handle_offset(value) 669 | 670 | def getOffset(self, offset): 671 | return self.robase + offset 672 | 673 | 674 | def get_str(self, pos, len): 675 | out = "" 676 | for i in range(len): 677 | out += chr(idc.get_wide_byte(pos+i)) 678 | return out 679 | 680 | def getName(self, offset): 681 | sid = ida_struct.get_struc_id("type") 682 | name_off = self.getDword(sid, offset, "string") 683 | string_addr = self.getOffset(name_off) + 3 684 | ln = idc.get_wide_byte(string_addr-1) 685 | return self.get_str(string_addr, ln) 686 | 687 | def nameFromOffset(self, offset): 688 | addr = offset 689 | return self.get_str(addr + 3, idc.get_wide_byte(addr + 2)) 690 | 691 | def getPtrToThis(self, sid, offset): 692 | memb_offs = idc.get_member_offset(sid, "ptrtothis") 693 | return idc.get_wide_dword(offset + memb_offs) 694 | 695 | def processStructField(self, addr, index): 696 | offset = addr + index 697 | sid = ida_struct.get_struc_id("structField") 698 | ptr = self.getPtr(sid, offset, "Name") 699 | ln = idc.get_wide_byte(ptr + 2) 700 | fieldName = self.get_str(ptr + 3, ln) 701 | Utils.rename(ptr, fieldName) 702 | ptr = self.getPtr(sid, offset, "typ") 703 | self.handle_offset(ptr) 704 | 705 | def processIMethods(self, offst, size): 706 | sz = ida_struct.get_struc_size(ida_struct.get_struc_id("imethod")) 707 | comm = [] 708 | for i in range(size): 709 | comm.append(self.processIMethod(offst + i * sz)) 710 | idc.set_cmt(offst, "\n".join(comm), 0) 711 | return comm 712 | 713 | def processIMethod(self, offst): 714 | sid = ida_struct.get_struc_id("imethod") 715 | name = self.getDword(sid, offst, "name") 716 | name += self.robase 717 | name = self.get_str(name + 3, idc.get_wide_byte(name + 2)) 718 | return name 719 | 720 | def processMethods(self, offst): 721 | sid = ida_struct.get_struc_id("method__") 722 | name = self.getDword(sid, offst, "name") 723 | name += self.robase 724 | name = self.get_str(name + 3, idc.get_wide_byte(name + 2)) 725 | type_meth = self.getDword(sid, offst, "mtyp") 726 | type_meth_addr1 = self.robase + type_meth 727 | func_body1 = self.getDword(sid, offst, "ifn") 728 | func_addr1 = self.text_addr + func_body1 729 | func_body2 = self.getDword(sid, offst, "tfn") 730 | func_addr2 = self.text_addr + func_body1 731 | return "%s %x %x %x" % (name, type_meth_addr1, func_addr1, func_addr2) 732 | 733 | def makeMap(self, offset): 734 | idc.SetType(offset, "mapType") 735 | sid = ida_struct.get_struc_id("mapType") 736 | addr = self.getPtr(sid, offset, "key") 737 | self.handle_offset(addr) 738 | addr = self.getPtr(sid, offset, "elem") 739 | self.handle_offset(addr) 740 | addr = self.getPtr(sid, offset, "bucket") 741 | self.handle_offset(addr) 742 | addr = self.getPtr(sid, offset, "hmap") 743 | self.handle_offset(addr) 744 | 745 | def parseFuncType(self, offset): 746 | return 747 | sid = ida_struct.get_struc_id("funcType") 748 | in_size = idc.Word(offset + idc.get_member_offset(sid, "incount")) 749 | out_size = idc.Word(offset + idc.get_member_offset(sid, "outcount")) 750 | sz = ida_struct.get_struc_size(sid) 751 | for i in range(in_size + out_size): 752 | idc.SetType(offset + sz + i * self.stepper.size, "type *") 753 | 754 | 755 | class TypeProcessing19(TypeProcessing17): 756 | 757 | def __init__(self, pos, endpos, step, settings, base_type): 758 | super(TypeProcessing19, self).__init__(pos, endpos, step, settings, base_type) 759 | self.robase = base_type 760 | 761 | def getStructFieldOffset(self, sid, addr): 762 | return (self.getPtr(sid, addr, "offset") >> 1) 763 | 764 | class TypeProcessing116(TypeProcessing19): 765 | 766 | def __init__(self, pos, endpos, step, settings, base_type): 767 | super(TypeProcessing116, self).__init__(pos, endpos, step, settings, base_type) 768 | self.robase = base_type 769 | 770 | def getStructFieldOffset(self, sid, addr): 771 | return (self.getPtr(sid, addr, "offset") >> 1) 772 | 773 | def makeMap(self, offset): 774 | idc.SetType(offset, "mapType") 775 | sid = ida_struct.get_struc_id("mapType") 776 | addr = self.getPtr(sid, offset, "key") 777 | self.handle_offset(addr) 778 | addr = self.getPtr(sid, offset, "elem") 779 | self.handle_offset(addr) 780 | addr = self.getPtr(sid, offset, "bucket") 781 | self.handle_offset(addr) 782 | 783 | class TypeProcessing117(TypeProcessing116): 784 | def __init__(self, pos, endpos, step, settings, base_type): 785 | super(TypeProcessing117, self).__init__(pos, endpos, step, settings, base_type) 786 | self.robase = base_type 787 | self.basetypes = dict() 788 | self.basetypes['BOOL'] = 'unsigned __int8' 789 | self.basetypes['UINT8'] = 'unsigned __int8' 790 | self.basetypes['INT8'] = 'signed __int8' 791 | self.basetypes['UINT16'] = 'unsigned __int16' 792 | self.basetypes['INT16'] = 'signed __int16' 793 | self.basetypes['UINT32'] = 'unsigned __int32' 794 | self.basetypes['INT32'] = 'signed __int32' 795 | self.basetypes['UINT64'] = 'unsigned __int64' 796 | self.basetypes['INT64'] = 'signed __int64' 797 | self.basetypes['UINT'] = 'unsigned __int64' 798 | self.basetypes['INT'] = 'signed __int64' 799 | self.basetypes['UINTPTR'] = 'unsigned __int64 *' 800 | self.basetypes['FLOAT32'] = 'float' 801 | self.basetypes['FLOAT64'] = 'double' 802 | 803 | def get_str_from_struct(self, ea): 804 | str_sz = idc.get_wide_byte(ea+1) 805 | str_ea = ea + 2 806 | 807 | sz, ea = self.get_str_sz(ea) 808 | return self.get_str(ea, sz) 809 | 810 | @staticmethod 811 | def get_str_sz(ea): 812 | print('getting str for {:x}'.format(ea)) 813 | ea += 1 814 | c = idc.get_wide_byte(ea) 815 | ea += 1 816 | numbits = 0 817 | sz = c & 0x7f 818 | numbits += 7 819 | while c & 0x80: 820 | c = idc.get_wide_byte(ea) 821 | ea += 1 822 | sz |= (c & 0x7f) << numbits 823 | numbits += 7 824 | 825 | return sz, ea 826 | return self.get_str(ea, sz) 827 | 828 | 829 | def makeMap(self, offset): 830 | idc.SetType(offset, "mapType") 831 | sid = ida_struct.get_struc_id("mapType") 832 | addr = self.getPtr(sid, offset, "key") 833 | self.handle_offset(addr) 834 | addr = self.getPtr(sid, offset, "elem") 835 | self.handle_offset(addr) 836 | addr = self.getPtr(sid, offset, "bucket") 837 | self.handle_offset(addr) 838 | 839 | def processStructField(self, addr, index): 840 | offset = addr + index 841 | sid = ida_struct.get_struc_id("structField") 842 | ptr = self.getPtr(sid, offset, "Name") 843 | ln = idc.get_wide_byte(ptr + 1) 844 | fieldName = self.get_str(ptr + 2, ln) 845 | Utils.rename(ptr, fieldName) 846 | ptr = self.getPtr(sid, offset, "typ") 847 | self.handle_offset(ptr) 848 | 849 | def nameFromOffset(self, offset): 850 | return self.get_str_from_struct(offset) 851 | 852 | def getName(self, offset): 853 | sid = ida_struct.get_struc_id("type") 854 | name_off = self.getDword(sid, offset, "string") 855 | string_addr = self.getOffset(name_off) 856 | return self.get_str_from_struct(string_addr) 857 | 858 | def processIMethod(self, offst): 859 | sid = ida_struct.get_struc_id("imethod") 860 | name = self.getDword(sid, offst, "name") 861 | name += self.robase 862 | return self.get_str_from_struct(name) 863 | 864 | def makeInterface(self, offset): 865 | print('creating interface {:x}'.format(offset)) 866 | idc.SetType(offset, "interfaceType") 867 | ifaceid = ida_struct.get_struc_id("interfaceType") 868 | meth_offs = idc.get_member_offset(ifaceid, "methods") 869 | slice_id = ida_struct.get_struc_id("slice") 870 | size_off = idc.get_member_offset(slice_id, "len") 871 | size = self.stepper.ptr(offset + meth_offs + size_off) 872 | 873 | name = self.getName(offset) 874 | while name[0] == "*": 875 | name = name[1:] 876 | name = Utils.relaxName(name) 877 | itab_name = "itab_" + name 878 | iface_name = 'iface_' + name 879 | 880 | names = [] 881 | if size > 0: 882 | addr = self.getPtr(slice_id, offset + meth_offs, "data") 883 | idc.SetType(addr, "imethod") 884 | sz = ida_struct.get_struc_size(ida_struct.get_struc_id("imethod")) 885 | self.make_arr(addr, size, sz, "imethod") 886 | names = self.processIMethods(addr, size) 887 | if names is None: 888 | return 889 | 890 | # Reference - #https://github.com/teh-cmc/go-internals/blob/master/chapter2_interfaces/README.md#anatomy-of-an-interface 891 | itab_fields = [("inter", "void *"), ("type", "void *"), ("hash", "__int32"), 892 | ("unused", "__int32")] 893 | for i in names: 894 | itab_fields.append((i, "void *")) 895 | 896 | itype = [(itab_name, itab_fields)] 897 | self.settings.structCreator.createTypes(itype) 898 | iface_fields = [('tab', f'{itab_name} *'), ('data', 'void *')] 899 | itype = [(iface_name, iface_fields)] 900 | self.settings.structCreator.createTypes(itype) 901 | 902 | 903 | def createUserTypeStruct(self, addr, name, size, self_size): 904 | print('creating struct {}'.format(name)) 905 | fields = [] 906 | sid = ida_struct.get_struc_id("structField") 907 | sz = ida_struct.get_struc_size(sid) 908 | sid_type = ida_struct.get_struc_id("type") 909 | fields = [] 910 | curr_offset = 0 911 | idc.set_cmt(addr, name, 0) 912 | for i in range(size): 913 | print('field in {:x}'.format(addr+i*sz)) 914 | fieldname = self.nameFromOffset(self.getPtr(sid, addr+i*sz,"Name")) 915 | type_addr = self.getPtr(sid, addr+i*sz, "typ") 916 | typename = self.getType(type_addr) 917 | size = self.getPtr(sid_type, type_addr, "size") 918 | if fieldname == "" or fieldname is None: 919 | fieldname = "unused_"+Utils.id_generator() 920 | offset = self.getStructFieldOffset(sid, addr+i*sz) 921 | print(f"Get offset: {offset:x}") 922 | if offset != curr_offset: 923 | print("Offset missmatch.Got %d expected %d. Adding padding..." % (curr_offset, offset)) 924 | if offset < curr_offset: 925 | raise("Too many bytes already") 926 | while offset != curr_offset: 927 | fields.append(("padding", "char")) 928 | curr_offset += 1 929 | curr_offset += size 930 | print('fieldname = {}'.format(fieldname)) 931 | if size != 0: 932 | fieldtype = None 933 | offset_kind = idc.get_member_offset(sid_type, "kind") 934 | kind_of_type = self.getKindEnumName(type_addr) 935 | print(kind_of_type) 936 | if kind_of_type == "STRUCT": 937 | name_type = self.getName(type_addr) 938 | while name_type[0] == "*": 939 | name_type = name_type[1:] 940 | name_type = Utils.relaxName(name_type) 941 | name_type = "ut_" + name_type 942 | 943 | if ida_struct.get_struc_id(name_type) != idc.BADADDR: 944 | print("setting type %s" % name_type) 945 | fieldtype = name_type 946 | 947 | elif kind_of_type == "STRING": 948 | fieldtype = "string" 949 | 950 | elif kind_of_type == "SLICE": 951 | fieldtype = "slice" 952 | 953 | elif kind_of_type == "INTERFACE": 954 | name_type = self.getName(type_addr) 955 | while name_type[0] == "*": 956 | name_type = name_type[1:] 957 | name_type = Utils.relaxName(name_type) 958 | name_type = "iface_" + name_type 959 | 960 | if ida_struct.get_struc_id(name_type) != idc.BADADDR: 961 | fieldtype = name_type 962 | 963 | elif kind_of_type == "CHAN": 964 | name_type = 'ut_runtime_hchan' 965 | ptr_name_type = f'{name_type} *' 966 | 967 | if ida_struct.get_struc_id(name_type) != idc.BADADDR: 968 | fieldtype = ptr_name_type 969 | 970 | elif kind_of_type == "MAP": 971 | name_type = 'ut_runtime_hmap' 972 | ptr_name_type = f'{name_type} *' 973 | if ida_struct.get_struc_id(name_type) != idc.BADADDR: 974 | fieldtype = ptr_name_type 975 | 976 | elif kind_of_type == "FUNC": 977 | fieldtype = 'void *' 978 | 979 | elif kind_of_type == "PTR": 980 | name_type = self.getName(type_addr) 981 | while name_type[0] == "*": 982 | name_type = name_type[1:] 983 | name_type = Utils.relaxName(name_type) 984 | name_type = "ut_" + name_type 985 | ptr_name_type = f'{name_type} *' 986 | 987 | if ida_struct.get_struc_id(name_type) != idc.BADADDR: 988 | print("setting ptr type %s" % name_type) 989 | fieldtype = ptr_name_type 990 | 991 | elif kind_of_type in self.basetypes: 992 | fieldtype = self.basetypes[kind_of_type] 993 | 994 | if fieldtype is None: 995 | if size == 1: 996 | fieldtype = 'char' 997 | else: 998 | fieldtype = "char [%d]" % size 999 | 1000 | fields.append((fieldname, fieldtype)) 1001 | 1002 | if curr_offset != self_size: 1003 | print("%x: Structure size mismatch: %x" % (addr, curr_offset)) 1004 | if self_size < curr_offset: 1005 | raise("Too many bytes already") 1006 | while self_size != curr_offset: 1007 | fields.append(("padding", "char")) 1008 | curr_offset += 1 1009 | new_type = [(name, fields)] 1010 | self.settings.structCreator.createTypes(new_type) 1011 | new_type_sid = ida_struct.get_struc_id(name) 1012 | sz = ida_struct.get_struc_size(new_type_sid) 1013 | if sz != self_size: 1014 | print("%x" % addr ) 1015 | raise Exception("Error at creating structure {}. {:x}!={:x}, fields={}".format(name, sz, self_size, fields)) 1016 | --------------------------------------------------------------------------------