mirror of
https://github.com/thunderbrewhq/binana.git
synced 2025-12-12 09:52:28 +00:00
feat(go): x64dbg can't parse types correctly without being in the correct order, but we can use Kahn topological sorting to avoid issues
This commit is contained in:
parent
df04015c59
commit
b6fb39c844
12 changed files with 475 additions and 35 deletions
2
go.sum
2
go.sum
|
|
@ -1,4 +1,6 @@
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
|
|
|
||||||
|
|
@ -40,4 +40,5 @@ func init() {
|
||||||
x64dbg_gen.Flags().StringP("base-address", "b", "00400000", "the base address of the module")
|
x64dbg_gen.Flags().StringP("base-address", "b", "00400000", "the base address of the module")
|
||||||
|
|
||||||
rootCmd.AddCommand(x64dbg_gen)
|
rootCmd.AddCommand(x64dbg_gen)
|
||||||
|
rootCmd.AddCommand(x64dbg_typesort)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
32
go/cmd/binana/cmd/x64dbg_typesort.go
Normal file
32
go/cmd/binana/cmd/x64dbg_typesort.go
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/thunderbrewhq/binana/go/x64dbg"
|
||||||
|
)
|
||||||
|
|
||||||
|
var x64dbg_typesort = &cobra.Command{
|
||||||
|
Use: "x64dbg-typesort [types.json file]",
|
||||||
|
Short: "sort a x64dbg types file",
|
||||||
|
Run: x64dbg_typesort_func,
|
||||||
|
}
|
||||||
|
|
||||||
|
func x64dbg_typesort_func(cmd *cobra.Command, args []string) {
|
||||||
|
types, err := x64dbg.LoadTypes(args[0])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = x64dbg.SortTypes(types); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder := json.NewEncoder(os.Stdout)
|
||||||
|
encoder.SetIndent("", " ")
|
||||||
|
if err = encoder.Encode(types); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -55,7 +55,7 @@ loop:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func cc_type_to_typedef(t cc.Type) (m x64dbg.Type) {
|
func cc_type_to_typedef(t cc.Type) (m x64dbg.AliasType) {
|
||||||
var s string
|
var s string
|
||||||
var arrsize int32 = 1
|
var arrsize int32 = 1
|
||||||
var array bool
|
var array bool
|
||||||
|
|
@ -156,7 +156,7 @@ func (profile *Profile) generate_x64dbg_types() (err error) {
|
||||||
if declarator, ok := node.(*cc.Declarator); ok {
|
if declarator, ok := node.(*cc.Declarator); ok {
|
||||||
if declarator.IsTypedefName {
|
if declarator.IsTypedefName {
|
||||||
if declarator.Type().Kind() != cc.Struct {
|
if declarator.Type().Kind() != cc.Struct {
|
||||||
var x64_type x64dbg.Type = cc_type_to_typedef(declarator.Type())
|
var x64_type x64dbg.AliasType = cc_type_to_typedef(declarator.Type())
|
||||||
x64_type.Name = scope_id.String()
|
x64_type.Name = scope_id.String()
|
||||||
if !slices.Contains(ignore_types, x64_type.Name) {
|
if !slices.Contains(ignore_types, x64_type.Name) {
|
||||||
x64_types.Types = append(x64_types.Types, x64_type)
|
x64_types.Types = append(x64_types.Types, x64_type)
|
||||||
|
|
@ -180,6 +180,7 @@ func (profile *Profile) generate_x64dbg_types() (err error) {
|
||||||
|
|
||||||
var x64_struct x64dbg.StructType
|
var x64_struct x64dbg.StructType
|
||||||
x64_struct.Name = struct_name.String()
|
x64_struct.Name = struct_name.String()
|
||||||
|
x64_struct.Size = int32(struct_type.Size())
|
||||||
|
|
||||||
for i := range struct_type.NumField() {
|
for i := range struct_type.NumField() {
|
||||||
struct_member := struct_type.FieldByIndex([]int{i})
|
struct_member := struct_type.FieldByIndex([]int{i})
|
||||||
|
|
@ -199,7 +200,7 @@ func (profile *Profile) generate_x64dbg_types() (err error) {
|
||||||
|
|
||||||
for i := range struct_member.Type().NumField() {
|
for i := range struct_member.Type().NumField() {
|
||||||
union_field := struct_member.Type().FieldByIndex([]int{i})
|
union_field := struct_member.Type().FieldByIndex([]int{i})
|
||||||
var x64_union_member x64dbg.Type = cc_type_to_typedef(union_field.Type())
|
var x64_union_member x64dbg.AliasType = cc_type_to_typedef(union_field.Type())
|
||||||
x64_union_member.Name = union_field.Name().String()
|
x64_union_member.Name = union_field.Name().String()
|
||||||
x64_union.Members = append(x64_union.Members, x64_union_member)
|
x64_union.Members = append(x64_union.Members, x64_union_member)
|
||||||
}
|
}
|
||||||
|
|
@ -210,11 +211,13 @@ func (profile *Profile) generate_x64dbg_types() (err error) {
|
||||||
x64_struct_member.Type = union_type_name
|
x64_struct_member.Type = union_type_name
|
||||||
x64_struct_member.Name = struct_member.Name().String()
|
x64_struct_member.Name = struct_member.Name().String()
|
||||||
x64_struct_member.Offset = int32(struct_member.Offset())
|
x64_struct_member.Offset = int32(struct_member.Offset())
|
||||||
|
// x64_struct_member.Offset = -1
|
||||||
x64_struct.Members = append(x64_struct.Members, x64_struct_member)
|
x64_struct.Members = append(x64_struct.Members, x64_struct_member)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
x64_struct_member := cc_type_to_struct_member_type(struct_member.Type())
|
x64_struct_member := cc_type_to_struct_member_type(struct_member.Type())
|
||||||
x64_struct_member.Name = struct_member.Name().String()
|
x64_struct_member.Name = struct_member.Name().String()
|
||||||
|
// x64_struct_member.Offset = -1
|
||||||
x64_struct_member.Offset = int32(struct_member.Offset())
|
x64_struct_member.Offset = int32(struct_member.Offset())
|
||||||
x64_struct.Members = append(x64_struct.Members, x64_struct_member)
|
x64_struct.Members = append(x64_struct.Members, x64_struct_member)
|
||||||
}
|
}
|
||||||
|
|
@ -225,6 +228,11 @@ func (profile *Profile) generate_x64dbg_types() (err error) {
|
||||||
|
|
||||||
types_file_path := filepath.Join(profile.Directory, "x32dbg", "types.json")
|
types_file_path := filepath.Join(profile.Directory, "x32dbg", "types.json")
|
||||||
|
|
||||||
|
err = x64dbg.SortTypes(&x64_types)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err = x64dbg.SaveTypes(types_file_path, &x64_types)
|
err = x64dbg.SaveTypes(types_file_path, &x64_types)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
17
go/x64dbg/alias_type.go
Normal file
17
go/x64dbg/alias_type.go
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
package x64dbg
|
||||||
|
|
||||||
|
type AliasType struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ArraySize int32 `json:"arrsize,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alias *AliasType) GetName() string {
|
||||||
|
return alias.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (alias *AliasType) Dependencies() []string {
|
||||||
|
return []string{
|
||||||
|
alias.Type,
|
||||||
|
}
|
||||||
|
}
|
||||||
23
go/x64dbg/function_type.go
Normal file
23
go/x64dbg/function_type.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package x64dbg
|
||||||
|
|
||||||
|
type FunctionType struct {
|
||||||
|
ReturnType string `json:"rettype"`
|
||||||
|
CallConvention string `json:"callconv"`
|
||||||
|
NoReturn bool `json:"noreturn"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Arguments []AliasType `json:"arguments,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (function *FunctionType) GetName() string {
|
||||||
|
return function.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (function *FunctionType) Dependencies() (s []string) {
|
||||||
|
if function.ReturnType != "" {
|
||||||
|
s = append(s, function.ReturnType)
|
||||||
|
}
|
||||||
|
for _, t := range function.Arguments {
|
||||||
|
s = append(s, t.Type)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
17
go/x64dbg/sort_types.go
Normal file
17
go/x64dbg/sort_types.go
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
package x64dbg
|
||||||
|
|
||||||
|
func SortTypes(types *Types) (err error) {
|
||||||
|
graph := new_type_dependency_graph()
|
||||||
|
if err = graph.Load(types); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var sorted *Types
|
||||||
|
sorted, err = graph.Save()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
*types = *sorted
|
||||||
|
return
|
||||||
|
}
|
||||||
26
go/x64dbg/struct_type.go
Normal file
26
go/x64dbg/struct_type.go
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
package x64dbg
|
||||||
|
|
||||||
|
type StructMemberType struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ArraySize int32 `json:"arrsize,omitempty"`
|
||||||
|
Offset int32 `json:"offset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructType struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size int32 `json:"size"`
|
||||||
|
Members []StructMemberType `json:"members,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (struct_ *StructType) GetName() string {
|
||||||
|
return struct_.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (struct_ *StructType) Dependencies() (s []string) {
|
||||||
|
for _, member := range struct_.Members {
|
||||||
|
s = append(s, member.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
257
go/x64dbg/type_dependency_graph.go
Normal file
257
go/x64dbg/type_dependency_graph.go
Normal file
|
|
@ -0,0 +1,257 @@
|
||||||
|
package x64dbg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
type type_dependency_graph struct {
|
||||||
|
all_types map[string]*type_graph_node
|
||||||
|
}
|
||||||
|
|
||||||
|
func (graph *type_dependency_graph) get(name string) *type_graph_node {
|
||||||
|
return graph.all_types[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
func new_type_dependency_graph() *type_dependency_graph {
|
||||||
|
t := new(type_dependency_graph)
|
||||||
|
t.all_types = make(map[string]*type_graph_node)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func new_type_graph_node() *type_graph_node {
|
||||||
|
t := new(type_graph_node)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (graph *type_dependency_graph) get_node_dependencies(t *type_graph_node) (nodes []*type_graph_node, err error) {
|
||||||
|
nodes = t.depends_on
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (graph *type_dependency_graph) check_sub_dependency_cycle(root_node, sub_node *type_graph_node) (err error) {
|
||||||
|
var sub_node_deps []*type_graph_node
|
||||||
|
sub_node_deps, err = graph.get_node_dependencies(sub_node)
|
||||||
|
for _, dependency_node := range sub_node_deps {
|
||||||
|
if dependency_node == root_node {
|
||||||
|
return fmt.Errorf("cycle detected with %s", root_node.t.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursively check for deeper dependency cycles
|
||||||
|
if err = graph.check_sub_dependency_cycle(root_node, dependency_node); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (graph *type_dependency_graph) check_root_dependency_cycle(node *type_graph_node) (err error) {
|
||||||
|
var node_deps []*type_graph_node
|
||||||
|
node_deps, err = graph.get_node_dependencies(node)
|
||||||
|
for _, dependency_node := range node_deps {
|
||||||
|
// check for obvious self-referential
|
||||||
|
if dependency_node == node {
|
||||||
|
return fmt.Errorf("immediate %s->%s self-reference", node.t.GetName(), node.t.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursively check for deeper dependency cycles
|
||||||
|
if err = graph.check_sub_dependency_cycle(node, dependency_node); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (graph *type_dependency_graph) remove_edge(dependency, dependent *type_graph_node) (err error) {
|
||||||
|
dependent_index := slices.Index(dependent.depends_on, dependency)
|
||||||
|
if dependent_index == -1 {
|
||||||
|
err = fmt.Errorf("dependency %s not found in dependent %s", dependency.t.GetName(), dependent.t.GetName())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dependency_index := slices.Index(dependency.is_depended_on_by, dependent)
|
||||||
|
|
||||||
|
if dependency_index == -1 {
|
||||||
|
err = fmt.Errorf("dependent %s not found in dependency %s", dependent.t.GetName(), dependency.t.GetName())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dependent.depends_on = slices.Delete(dependent.depends_on, dependent_index, dependent_index+1)
|
||||||
|
dependency.is_depended_on_by = slices.Delete(dependency.is_depended_on_by, dependency_index, dependency_index+1)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (graph *type_dependency_graph) Load(types *Types) (err error) {
|
||||||
|
// combine all types into an array
|
||||||
|
var all_types []*type_graph_node
|
||||||
|
|
||||||
|
type_exists := map[string]bool{}
|
||||||
|
|
||||||
|
for _, alias_type := range types.Types {
|
||||||
|
t := new_type_graph_node()
|
||||||
|
at := alias_type
|
||||||
|
t.t = &at
|
||||||
|
|
||||||
|
if !type_exists[t.String()] {
|
||||||
|
type_exists[t.String()] = true
|
||||||
|
all_types = append(all_types, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, struct_type := range types.Structs {
|
||||||
|
t := new_type_graph_node()
|
||||||
|
st := struct_type
|
||||||
|
t.t = &st
|
||||||
|
|
||||||
|
if !type_exists[t.String()] {
|
||||||
|
type_exists[t.String()] = true
|
||||||
|
all_types = append(all_types, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, union_type := range types.Unions {
|
||||||
|
t := new_type_graph_node()
|
||||||
|
ut := union_type
|
||||||
|
t.t = &ut
|
||||||
|
|
||||||
|
if !type_exists[t.String()] {
|
||||||
|
type_exists[t.String()] = true
|
||||||
|
all_types = append(all_types, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, func_type := range types.Functions {
|
||||||
|
t := new_type_graph_node()
|
||||||
|
ft := func_type
|
||||||
|
t.t = &ft
|
||||||
|
|
||||||
|
if !type_exists[t.String()] {
|
||||||
|
type_exists[t.String()] = true
|
||||||
|
all_types = append(all_types, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load types into map
|
||||||
|
graph.all_types = make(map[string]*type_graph_node)
|
||||||
|
for _, t := range all_types {
|
||||||
|
graph.all_types[t.t.GetName()] = t
|
||||||
|
}
|
||||||
|
|
||||||
|
// build graph
|
||||||
|
for _, t := range all_types {
|
||||||
|
for _, dependency_name := range t.t.Dependencies() {
|
||||||
|
if is_type_name_builtin(dependency_name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dependency_type := graph.get(dependency_name)
|
||||||
|
if dependency_type == nil {
|
||||||
|
err = fmt.Errorf("unknown dependency name %s", dependency_name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !slices.Contains(t.depends_on, dependency_type) {
|
||||||
|
t.depends_on = append(t.depends_on, dependency_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !slices.Contains(dependency_type.is_depended_on_by, t) {
|
||||||
|
dependency_type.is_depended_on_by = append(dependency_type.is_depended_on_by, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for cycles
|
||||||
|
for _, t := range all_types {
|
||||||
|
if err = graph.check_root_dependency_cycle(t); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type type_dependency_sorter struct {
|
||||||
|
graph *type_dependency_graph
|
||||||
|
type_names []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func new_type_dependency_sorter(graph *type_dependency_graph) *type_dependency_sorter {
|
||||||
|
sorter := new(type_dependency_sorter)
|
||||||
|
sorter.graph = graph
|
||||||
|
for k := range sorter.graph.all_types {
|
||||||
|
sorter.type_names = append(sorter.type_names, k)
|
||||||
|
}
|
||||||
|
sort.Strings(sorter.type_names)
|
||||||
|
return sorter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sorter *type_dependency_sorter) sort() (sorted []*type_graph_node, err error) {
|
||||||
|
// first, peel off types with no dependencies.
|
||||||
|
var s []*type_graph_node
|
||||||
|
var l []*type_graph_node
|
||||||
|
|
||||||
|
for _, type_name := range sorter.type_names {
|
||||||
|
node := sorter.graph.all_types[type_name]
|
||||||
|
//
|
||||||
|
if len(node.depends_on) == 0 {
|
||||||
|
s = append(s, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for len(s) != 0 {
|
||||||
|
n := s[0]
|
||||||
|
s = s[1:]
|
||||||
|
|
||||||
|
l = append(l, n)
|
||||||
|
|
||||||
|
n_dependents := make([]*type_graph_node, len(n.is_depended_on_by))
|
||||||
|
copy(n_dependents, n.is_depended_on_by)
|
||||||
|
for i := range n_dependents {
|
||||||
|
m := n_dependents[i]
|
||||||
|
|
||||||
|
if err = sorter.graph.remove_edge(n, m); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m.depends_on) == 0 {
|
||||||
|
s = append(s, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sorted = l
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (graph *type_dependency_graph) Save() (types *Types, err error) {
|
||||||
|
sorter := new_type_dependency_sorter(graph)
|
||||||
|
|
||||||
|
var sorted []*type_graph_node
|
||||||
|
sorted, err = sorter.sort()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
types = new(Types)
|
||||||
|
|
||||||
|
for _, t := range sorted {
|
||||||
|
switch xt := t.t.(type) {
|
||||||
|
case *AliasType:
|
||||||
|
types.Types = append(types.Types, *xt)
|
||||||
|
case *StructType:
|
||||||
|
types.Structs = append(types.Structs, *xt)
|
||||||
|
case *UnionType:
|
||||||
|
types.Unions = append(types.Unions, *xt)
|
||||||
|
case *FunctionType:
|
||||||
|
types.Functions = append(types.Functions, *xt)
|
||||||
|
default:
|
||||||
|
panic(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
51
go/x64dbg/type_node.go
Normal file
51
go/x64dbg/type_node.go
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
package x64dbg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type type_graph_set []*type_graph_node
|
||||||
|
|
||||||
|
type graph_type interface {
|
||||||
|
GetName() string
|
||||||
|
Dependencies() []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type type_graph_node struct {
|
||||||
|
t graph_type
|
||||||
|
depends_on type_graph_set
|
||||||
|
is_depended_on_by type_graph_set
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *type_graph_node) String() string {
|
||||||
|
return t.t.GetName()
|
||||||
|
}
|
||||||
|
|
||||||
|
var builtins = []string{
|
||||||
|
"char",
|
||||||
|
"bool",
|
||||||
|
"long",
|
||||||
|
"short",
|
||||||
|
"long long",
|
||||||
|
"int",
|
||||||
|
"float",
|
||||||
|
"double",
|
||||||
|
"char*",
|
||||||
|
"void*",
|
||||||
|
"int8_t",
|
||||||
|
"int16_t",
|
||||||
|
"int32_t",
|
||||||
|
"int64_t",
|
||||||
|
"uint8_t",
|
||||||
|
"uint16_t",
|
||||||
|
"uint32_t",
|
||||||
|
"uint64_t",
|
||||||
|
}
|
||||||
|
|
||||||
|
func is_type_name_builtin(t string) bool {
|
||||||
|
if strings.HasSuffix(t, "*") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return slices.Contains(builtins, t)
|
||||||
|
}
|
||||||
|
|
@ -5,39 +5,9 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Type struct {
|
// Describes the format of an x64dbg type information file
|
||||||
Type string `json:"type"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
ArraySize int32 `json:"arrsize,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type StructMemberType struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
ArraySize int32 `json:"arrsize,omitempty"`
|
|
||||||
Offset int32 `json:"offset,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type StructType struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Members []StructMemberType `json:"members,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UnionType struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Members []Type `json:"members,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FunctionType struct {
|
|
||||||
ReturnType string `json:"rettype"`
|
|
||||||
CallConvention string `json:"callconv"`
|
|
||||||
NoReturn bool `json:"noreturn"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Arguments []Type `json:"arguments,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Types struct {
|
type Types struct {
|
||||||
Types []Type `json:"types,omitempty"`
|
Types []AliasType `json:"types,omitempty"`
|
||||||
Structs []StructType `json:"structs,omitempty"`
|
Structs []StructType `json:"structs,omitempty"`
|
||||||
Unions []UnionType `json:"unions,omitempty"`
|
Unions []UnionType `json:"unions,omitempty"`
|
||||||
Functions []FunctionType `json:"functions,omitempty"`
|
Functions []FunctionType `json:"functions,omitempty"`
|
||||||
|
|
@ -59,3 +29,21 @@ func SaveTypes(name string, types *Types) (err error) {
|
||||||
err = file.Close()
|
err = file.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoadTypes(name string) (types *Types, err error) {
|
||||||
|
var file *os.File
|
||||||
|
file, err = os.Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
types = new(Types)
|
||||||
|
|
||||||
|
e := json.NewDecoder(file)
|
||||||
|
if err = e.Decode(types); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = file.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
||||||
18
go/x64dbg/union_type.go
Normal file
18
go/x64dbg/union_type.go
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
package x64dbg
|
||||||
|
|
||||||
|
type UnionType struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Members []AliasType `json:"members,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (union *UnionType) GetName() string {
|
||||||
|
return union.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (union *UnionType) Dependencies() (s []string) {
|
||||||
|
for _, member := range union.Members {
|
||||||
|
s = append(s, member.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue