forked from security/hakurei
152 lines
3.2 KiB
Go
152 lines
3.2 KiB
Go
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)
|
|
}
|
|
}
|