diff --git a/go/profile/ida_generate_files.go b/go/profile/ida_generate_files.go index 3bf2962..51e927f 100644 --- a/go/profile/ida_generate_files.go +++ b/go/profile/ida_generate_files.go @@ -9,64 +9,144 @@ import ( "github.com/thunderbrewhq/binana/go/symfile" ) -func (profile *Profile) generate_symbols_idc() (err error) { +type idac_import_batch struct { + tab int + fd *os.File +} +// Include/import +func (b *idac_import_batch) I(global bool, filename string) (err error) { var ( - f *os.File + hq_global = [2]rune{'<', '>'} + hq_local = [2]rune{'"', '"'} ) - f, err = os.Create(filepath.Join(profile.Directory, "ida", "import_symbols.idc")) + hq := hq_local + if global { + hq = hq_global + } + _, err = fmt.Fprintf(b.fd, "#include %c%s%c\n", hq[0], filename, hq[1]) + return +} + +func (b *idac_import_batch) T(tabs int) { + b.tab = tabs +} + +// Print +func (b *idac_import_batch) P(f string, list ...any) (err error) { + for range b.tab { + if _, err = fmt.Fprint(b.fd, "\t"); err != nil { + return + } + } + _, err = fmt.Fprintf(b.fd, f, list...) + if err != nil { + return + } + _, err = fmt.Fprint(b.fd, "\n") + return +} + +// Newline n times +func (b *idac_import_batch) N(n int) (err error) { + for range n { + if _, err = fmt.Fprint(b.fd, "\n"); err != nil { + return + } + } + + return +} + +func (b *idac_import_batch) Close() (err error) { + err = b.fd.Close() + return +} + +func (profile *Profile) create_idac_import_batch(name string) (b *idac_import_batch, err error) { + b = new(idac_import_batch) + b.fd, err = os.Create(filepath.Join(profile.Directory, "ida", "batch", name+".idc")) if err != nil { return } - fmt.Fprintf(f, "#include \n") - fmt.Fprintf(f, "\n") - fmt.Fprintf(f, "#include \"import_data_types.idc\"\n") - fmt.Fprintf(f, "static main() {\n") - fmt.Fprintf(f, " // Make names\n") + return +} +func (profile *Profile) generate_symbols_idc() (err error) { + // symbols + var b *idac_import_batch + b, err = profile.create_idac_import_batch("import_symbols") + if err != nil { + return + } + b.I(true, "idc.idc") + b.N(1) + b.P("static import_symbols() {") + b.T(1) + b.P("// Set/create names") for _, symbol := range profile.SymbolTable.Entries { quoted_name := strconv.Quote(symbol.Name) address := fmt.Sprintf("0x%08X", symbol.StartAddress) - fmt.Fprintf(f, " set_name(%s, %s);\n", address, quoted_name) + b.P("set_name(%s, %s);", address, quoted_name) } + b.T(0) + b.P("}") - fmt.Fprintf(f, " // Make functions\n") + b.Close() - for _, function_symbol := range profile.SymbolTable.Entries { - if function_symbol.Kind == symfile.Function { - address := fmt.Sprintf("0x%08X", function_symbol.StartAddress) - fmt.Fprintf(f, " set_func_start(%s, %s);\n", address, address) - if function_symbol.EndAddress != 0 { - end_address := fmt.Sprintf("0x%08X", function_symbol.EndAddress) - fmt.Fprintf(f, " set_func_end(%s, %s);\n", address, end_address) - } - } - } - fmt.Fprintf(f, " // Apply data types\n") - fmt.Fprintf(f, " import_data_types();\n") - fmt.Fprintf(f, "}\n") - - f.Close() - - f, err = os.Create(filepath.Join(profile.Directory, "ida", "import_data_types.idc")) + // data label types + b, err = profile.create_idac_import_batch("import_data_types") if err != nil { return } - fmt.Fprintf(f, "#include \n") - fmt.Fprintf(f, "\n") - fmt.Fprintf(f, "static import_data_types() {\n") - + b.I(true, "idc.idc") + b.N(1) + b.P("static import_data_types() {") + b.T(1) + b.P("// Give types to data labels") for _, symbol := range profile.SymbolTable.Entries { if symbol.DataType != "" { quoted_data_type := strconv.Quote(symbol.DataType) address := fmt.Sprintf("0x%08X", symbol.StartAddress) - fmt.Fprintf(f, " apply_type(%s, %s);\n", address, quoted_data_type) + b.P("apply_type(%s, %s);", address, quoted_data_type) } } + b.T(0) + b.P("}") - fmt.Fprintf(f, "}\n") + b.Close() + + // functions + b, err = profile.create_idac_import_batch("import_functions") + if err != nil { + return + } + + b.I(true, "idc.idc") + b.N(1) + b.P("static import_functions() {") + b.T(1) + b.P("// Import function addresses and comments") + b.P(`msg("Importing function addresses and comments");`) + for _, function_symbol := range profile.SymbolTable.Entries { + if function_symbol.Kind == symfile.Function { + address := fmt.Sprintf("0x%08X", function_symbol.StartAddress) + b.P("set_func_start(%s, %s);", address, address) + if function_symbol.EndAddress != 0 { + end_address := fmt.Sprintf("0x%08X", function_symbol.EndAddress) + b.P("set_func_end(%s, %s);", address, end_address) + } + if function_symbol.Comment != "" { + b.P("set_func_cmt(%s, %s, 0);", address, strconv.Quote(function_symbol.Comment)) + } + } + } + b.T(0) + b.P("}") + + b.Close() return } diff --git a/go/x64dbg/type_dependency_graph.go b/go/x64dbg/type_dependency_graph.go index b2948ae..c625ef5 100644 --- a/go/x64dbg/type_dependency_graph.go +++ b/go/x64dbg/type_dependency_graph.go @@ -150,7 +150,7 @@ func (graph *type_dependency_graph) Load(types *Types) (err error) { dependency_type := graph.get(dependency_name) if dependency_type == nil { - err = fmt.Errorf("unknown dependency name %s", dependency_name) + err = fmt.Errorf("unknown dependency name '%s' from type '%s'", dependency_name, t.t.GetName()) return }