Skip to content

Commit

Permalink
Merge pull request #1 from vsoch/add/disasm
Browse files Browse the repository at this point in the history
Adding support for disasm!
  • Loading branch information
vsoch committed Oct 9, 2021
2 parents e8f6648 + d33454d commit 2fc0bb5
Show file tree
Hide file tree
Showing 8 changed files with 605 additions and 35 deletions.
51 changes: 50 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,23 @@ Symbols (and I found an entry to where the Dwarf is).

## Usage

To run and preview the output, do:
To build the gosmeagle binary, you can do:

```bash
$ make
```

You can also interact as follows:

```bash
$ go run main.go
```

### Parse

Parsing means outputting a corpus to JSON.

```bash
$ go run main.go parse libtest.so
```
```
Expand Down Expand Up @@ -66,6 +79,42 @@ $ go run main.go parse libtest.so --pretty
]
}
```

### Disasm

Disassembling means printing Assembly.

```bash
$ go run main.go disasm libtest.so
```
```bash
TEXT register_tm_clones(SB)

TEXT __do_global_dtors_aux(SB)

TEXT frame_dummy(SB)

TEXT bigcall(SB)
0x1120 f3 ?
0x1121 0f ?
0x1122 1e ?
0x1123 fa CLI // cli
0x1124 4883ec10 SUBQ $0x10, SP // sub $0x10,%rsp
0x1128 4989c9 MOVQ CX, R9 // mov %rcx,%r9
0x112b 31c0 XORL AX, AX // xor %eax,%eax
0x112d 4889f1 MOVQ SI, CX // mov %rsi,%rcx
0x1130 ff742418 PUSHQ 0x18(SP) // pushq 0x18(%rsp)
0x1134 488d35c50e0000 LEAQ 0xec5(IP), SI // lea 0xec5(%rip),%rsi
0x113b ff742428 PUSHQ 0x28(SP) // pushq 0x28(%rsp)
0x113f 4150 PUSHL R8 // push %r8
0x1141 4989d0 MOVQ DX, R8 // mov %rdx,%r8
0x1144 4889fa MOVQ DI, DX // mov %rdi,%rdx
0x1147 bf01000000 MOVL $0x1, DI // mov $0x1,%edi
0x114c e8fffeffff CALL 0x1050 // callq 0x1050
0x1151 4883c428 ADDQ $0x28, SP // add $0x28,%rsp
0x1155 c3 RET // retq
```

Note that this library is under development, so stay tuned!

## Background
Expand Down
34 changes: 34 additions & 0 deletions cli/disasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cli

import (
"github.com/DataDrake/cli-ng/v2/cmd"
"github.com/vsoch/gosmeagle/corpus"
"os"
"regexp"
)

// Args and flags for generate
type DisasmArgs struct {
Binary []string `desc:"A binary to dissassemble."`
}
type DisasmFlags struct{}

var Disasm = cmd.Sub{
Name: "disasm",
Alias: "d",
Short: "Disassemble a binary.",
Flags: &DisasmFlags{},
Args: &DisasmArgs{},
Run: RunDisasm,
}

func init() {
cmd.Register(&Disasm)
}

func RunDisasm(r *cmd.Root, c *cmd.Sub) {
args := c.Args.(*DisasmArgs)
disasm := corpus.GetDisasm(args.Binary[0])
var symRE *regexp.Regexp
disasm.Print(os.Stdout, symRE, 0, ^uint64(0), true, true)
}
4 changes: 2 additions & 2 deletions cli/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ func init() {
func RunParser(r *cmd.Root, c *cmd.Sub) {
args := c.Args.(*ParserArgs)
flags := c.Flags.(*ParserFlags)
corpus := corpus.GetCorpus(args.Binary[0])
corpus.ToJson(flags.Pretty)
C := corpus.GetCorpus(args.Binary[0])
C.ToJson(flags.Pretty)
}
56 changes: 49 additions & 7 deletions corpus/corpus.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import (
"github.com/vsoch/gosmeagle/descriptor"
"github.com/vsoch/gosmeagle/parsers/file"
"github.com/vsoch/gosmeagle/parsers/x86_64"
"io/ioutil"
"log"
"os"
"reflect"
)

// A corpus holds a library name, a list of Functions and variables
// TODO should this be a list of Locations instead?
type Corpus struct {
Library string `json:"library"`
Functions []descriptor.FunctionDescription `json:"functions,omitempty"`
Variables []descriptor.VariableDescription `json:"variables,omitempty"`
Library string `json:"library"`
Locations []map[string]descriptor.LocationDescription `json:"locations,omitempty"`
}

// Get a corpus from a filename
Expand All @@ -34,6 +34,43 @@ func GetCorpus(filename string) Corpus {
return corpus
}

// Get assembly for a filename
func GetDisasm(filename string) *file.Disasm {

f, err := file.Open(filename)
if err != nil {
log.Fatal(err)
}
defer f.Close()

// Populate the corpus depending on the Architecture
disasm, err := f.Disasm()
if err != nil {
log.Fatalf("Cannot disassemble binary: %x", err)
}
return disasm
}

// Load a corpus from Json
func Load(filename string) Corpus {

jsonFile, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
defer jsonFile.Close()

// Read as byte array
byteArray, err := ioutil.ReadAll(jsonFile)
if err != nil {
log.Fatalf("Cannot read %s\n", jsonFile)
}

c := Corpus{}
json.Unmarshal(byteArray, &c)
return c
}

func (c *Corpus) Parse(f *file.File) {

// Parse dwarf for each entry to use
Expand All @@ -43,7 +80,7 @@ func (c *Corpus) Parse(f *file.File) {
for _, e := range f.Entries {

// These are dynamic symbol table symbols
symbols, err := e.Symbols()
symbols, err := e.DynamicSymbols()
if err != nil {
log.Fatalf("Issue retriving symbols from %s", c.Library)
}
Expand Down Expand Up @@ -74,7 +111,10 @@ func (c *Corpus) parseFunction(f *file.File, symbol file.Symbol, entry *file.Dwa

switch f.GoArch() {
case "amd64":
c.Functions = append(c.Functions, x86_64.ParseFunction(f, symbol, entry))
newFunction := x86_64.ParseFunction(f, symbol, entry)
loc := map[string]descriptor.LocationDescription{}
loc["function"] = newFunction
c.Locations = append(c.Locations, loc)
default:
fmt.Printf("Unsupported architecture %s\n", f.GoArch())
}
Expand All @@ -89,7 +129,9 @@ func (c *Corpus) parseVariable(f *file.File, symbol file.Symbol, entry *file.Dwa
// Don't allow variables without name or type
variable := x86_64.ParseVariable(f, symbol, entry)
if !reflect.DeepEqual(variable, descriptor.VariableDescription{}) {
c.Variables = append(c.Variables, variable)
loc := map[string]descriptor.LocationDescription{}
loc["variable"] = variable
c.Locations = append(c.Locations, loc)
}
default:
fmt.Printf("Unsupported architecture %s\n", f.GoArch())
Expand Down
3 changes: 3 additions & 0 deletions descriptor/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ type Parameter interface {
GetName() string
}

// A General Location description holds a variable or function
type LocationDescription interface{}

// A function description has a list of parameters
type FunctionDescription struct {
Parameters []Parameter `json:"parameters,omitempty"`
Expand Down

0 comments on commit 2fc0bb5

Please sign in to comment.