forked from security/hakurei
cmd/irdump: basic disassembler
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"hakurei.app/command"
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -17,10 +16,12 @@ func main() {
|
||||
var (
|
||||
flagOutput string
|
||||
flagReal bool
|
||||
flagHeader bool
|
||||
flagForce bool
|
||||
)
|
||||
c := command.New(os.Stderr, log.Printf, "irdump", func(args []string) (err error) {
|
||||
var input *os.File
|
||||
if len(args) < 1 {
|
||||
if len(args) != 1 {
|
||||
return errors.New("irdump requires 1 argument")
|
||||
}
|
||||
if input, err = os.Open(args[0]); err != nil {
|
||||
@@ -38,12 +39,8 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
inputData := bytes.NewBuffer(nil)
|
||||
if _, err = io.Copy(inputData, input); err != nil {
|
||||
return
|
||||
}
|
||||
var out string
|
||||
if out, err = Disassemble(inputData.Bytes(), flagReal); err != nil {
|
||||
if out, err = pkg.Disassemble(input, flagReal, flagHeader, flagForce); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = output.WriteString(out); err != nil {
|
||||
@@ -57,12 +54,18 @@ func main() {
|
||||
).Flag(
|
||||
&flagReal,
|
||||
"r", command.BoolFlag(false),
|
||||
"skip label generation; idents print real value")
|
||||
"skip label generation; idents print real value",
|
||||
).Flag(
|
||||
&flagHeader,
|
||||
"h", command.BoolFlag(false),
|
||||
"display artifact headers",
|
||||
).Flag(
|
||||
&flagForce,
|
||||
"f", command.BoolFlag(false),
|
||||
"force display (skip validations)",
|
||||
)
|
||||
|
||||
c.MustParse(os.Args[1:], func(err error) {
|
||||
log.Fatal(err)
|
||||
})
|
||||
}
|
||||
func Disassemble(ir []byte, real bool) (string, error) {
|
||||
return "hello world", nil
|
||||
}
|
||||
|
||||
151
internal/pkg/asm.go
Normal file
151
internal/pkg/asm.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Disassemble(r io.Reader, real bool, showHeader bool, force bool) (s string, err error) {
|
||||
var values [][2]string
|
||||
sb := new(strings.Builder)
|
||||
header := true
|
||||
for err == nil {
|
||||
if header {
|
||||
var kind uint64
|
||||
var size uint64
|
||||
hsb := new(strings.Builder)
|
||||
|
||||
if kind, err = nextUint64(r); err != nil {
|
||||
break
|
||||
}
|
||||
if size, err = nextUint64(r); err != nil {
|
||||
break
|
||||
}
|
||||
for i := 0; uint64(i) < size; i++ {
|
||||
var did Checksum
|
||||
var dkind uint64
|
||||
if dkind, err = nextUint64(r); err != nil {
|
||||
break
|
||||
}
|
||||
if did, err = nextIdent(r); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
hsb.WriteString(fmt.Sprintf("\t\t\t%s\t%s\n", intToKind(dkind), Encode(did)))
|
||||
}
|
||||
header = false
|
||||
if showHeader {
|
||||
values = append(values, [2]string{"head", fmt.Sprintf("%s [\n%s]", intToKind(kind), hsb.String())})
|
||||
}
|
||||
}
|
||||
var k uint32
|
||||
if k, err = nextUint32(r); err != nil {
|
||||
break
|
||||
}
|
||||
kind := IRValueKind(k)
|
||||
switch kind {
|
||||
case IRKindEnd:
|
||||
var a uint32
|
||||
if a, err = nextUint32(r); err != nil {
|
||||
break
|
||||
}
|
||||
if a&1 != 0 {
|
||||
var sum Checksum
|
||||
if sum, err = nextIdent(r); err != nil {
|
||||
break
|
||||
}
|
||||
values = append(values, [2]string{"end", Encode(sum)})
|
||||
} else {
|
||||
values = append(values, [2]string{"end", ""})
|
||||
}
|
||||
header = true
|
||||
continue
|
||||
|
||||
case IRKindIdent:
|
||||
// discard ancillary
|
||||
if _, err = nextUint32(r); err != nil {
|
||||
break
|
||||
}
|
||||
var sum Checksum
|
||||
if sum, err = nextIdent(r); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
values = append(values, [2]string{"id", Encode(sum)})
|
||||
continue
|
||||
case IRKindUint32:
|
||||
var i uint32
|
||||
if i, err = nextUint32(r); err != nil {
|
||||
break
|
||||
}
|
||||
values = append(values, [2]string{"int", strconv.FormatUint(uint64(i), 10)})
|
||||
case IRKindString:
|
||||
var l uint32
|
||||
if l, err = nextUint32(r); err != nil {
|
||||
break
|
||||
}
|
||||
s := make([]byte, l+(wordSize-(l)%wordSize)%wordSize)
|
||||
if _, err = r.Read(s); err != nil {
|
||||
break
|
||||
}
|
||||
values = append(values, [2]string{"str", fmt.Sprintf("\"%s\"", string(s[:l]))})
|
||||
continue
|
||||
default:
|
||||
var i uint32
|
||||
if i, err = nextUint32(r); err != nil {
|
||||
break
|
||||
}
|
||||
values = append(values, [2]string{fmt.Sprintf("$%x", uint32(kind)), strconv.FormatUint(uint64(i), 10)})
|
||||
}
|
||||
}
|
||||
if err != io.EOF {
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
for i := 0; i < len(values); i++ {
|
||||
sb.WriteString(fmt.Sprintf("%s\t\t%s\n", values[i][0], values[i][1]))
|
||||
}
|
||||
return sb.String(), err
|
||||
}
|
||||
func nextUint32(r io.Reader) (uint32, error) {
|
||||
i := make([]byte, 4)
|
||||
_, err := r.Read(i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return binary.LittleEndian.Uint32(i), nil
|
||||
}
|
||||
func nextUint64(r io.Reader) (uint64, error) {
|
||||
i := make([]byte, 8)
|
||||
_, err := r.Read(i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return binary.LittleEndian.Uint64(i), nil
|
||||
}
|
||||
func nextIdent(r io.Reader) (Checksum, error) {
|
||||
i := make([]byte, 48)
|
||||
if _, err := r.Read(i); err != nil {
|
||||
return Checksum{}, err
|
||||
}
|
||||
return Checksum(i), nil
|
||||
}
|
||||
func intToKind(i uint64) string {
|
||||
switch Kind(i) {
|
||||
case KindHTTPGet:
|
||||
return "http_get"
|
||||
case KindTar:
|
||||
return "tar"
|
||||
case KindExec:
|
||||
return "exec"
|
||||
case KindExecNet:
|
||||
return "exec_net"
|
||||
case KindFile:
|
||||
return "file"
|
||||
default:
|
||||
return fmt.Sprintf("$%d", i-KindCustomOffset)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user