Documentation ¶
Overview ¶
Package toutoumomoma reports whether a Go executable might be sneaky.
Example ¶
package main import ( "flag" "fmt" "log" "os" "github.com/elastic/toutoumomoma" ) func main() { stdlib := flag.Bool("stdlib", false, "include standard library in Go symbol hash") flag.Usage = func() { fmt.Fprintf(flag.CommandLine.Output(), "usage: %s [-stdlib] <path>\n", os.Args[0]) flag.PrintDefaults() } flag.Parse() if len(flag.Args()) != 1 { flag.Usage() os.Exit(2) } path := flag.Args()[0] f, err := toutoumomoma.Open(path) if err != nil { if err == toutoumomoma.ErrUnknownFormat { os.Exit(0) } log.Fatal(err) } defer f.Close() sneaky, err := f.Stripped() if err != nil { log.Fatal(err) } if sneaky { fmt.Println("stripped") } h, imports, err := f.ImportHash() if err != nil { log.Fatal(err) } fmt.Printf("imphash: %x\n", h) if len(imports) != 0 { for _, i := range imports { fmt.Printf("\t%s\n", i) } } h, symbols, err := f.GoSymbolHash(*stdlib) if err != nil { if err == toutoumomoma.ErrNotGoExecutable { os.Exit(0) } log.Fatal(err) } fmt.Printf("symhash: %x\n", h) if len(symbols) != 0 { for _, i := range symbols { fmt.Printf("\t%s\n", i) } } }
Output:
Index ¶
- Variables
- func GoSymbolHash(path string, stdlib bool) (hash []byte, imports []string, err error)
- func ImportHash(path string) (hash []byte, imports []string, err error)
- func NameEntropy(symbols []string) (entropy, variance float64)
- func Stripped(path string) (sneaky bool, err error)
- type File
- func (f *File) Close() error
- func (f *File) GoSymbolHash(stdlib bool) (hash []byte, imports []string, err error)
- func (f *File) ImportHash() (hash []byte, imports []string, err error)
- func (f *File) Sections() ([]Section, error)
- func (f *File) Stripped() (sneaky bool, err error)
- func (f *File) Type() string
- type Section
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrUnknownFormat is returned for files that are not recognized. ErrUnknownFormat = errors.New("unknown format") // ErrNotGoExecutable indicates a file was not a Go executable. ErrNotGoExecutable = errors.New("not a Go executable") )
Functions ¶
func GoSymbolHash ¶
GoSymbolHash is a convenience wrapper around File.GoSymbolHash.
func ImportHash ¶
ImportHash is a convenience wrapper around File.ImportHash.
func NameEntropy ¶
NameEntropy returns the entropy and entropy variance for the given import symbols names as a set.
Types ¶
type File ¶
type File struct {
// contains filtered or unexported fields
}
File holds an executable object file.
func NewFile ¶
NewFile creates a new File for accessing a binary object in an underlying reader. The binary is expected to start at position 0 in the ReaderAt.
If the in the reader is not an ELF, Mach-O or PE format executable, NewFile will return ErrUnknownFormat.
func Open ¶
Open opens the file at at the provided path.
If the file at path is not an ELF, Mach-O or PE format executable, Open will return ErrUnknownFormat. Files without execute permissions may be opened.
func (*File) Close ¶
Close closes the file. Close must be called if the File was created using Open. If NewFile was used to create the File, Close will close the underlying io.ReaderAt if it implements the io.Closer interface.
func (*File) GoSymbolHash ¶
GoSymbolHash returns the symbol hash of a Go executable and the list of symbols in the executable examined to generate the hash. If stdlib is true, symbols from the Go standard library are included, otherwise only third-party symbols are considered.
The algorithm is analogous to the algorithm described for ImportHash with the exception that Go's static symbols are used in place of the dynamic import symbols used by the ImportHash. The list of symbols referenced by the executable is obtained and the MD5 hash of the ordered list of symbols, separated by commas, is calculated. The order of the symbols is as exists in the executable and returned by the standard library debug packages The fully qualified import path of each symbol is included and while symbols used by ImportHash are canonicalised to lowercase, GoSymbolHash retains the case of the original symbol.
If the file is an executable, but not a gc-compiled Go executable, ErrNotGoExecutable will be returned.
func (*File) ImportHash ¶
ImportHash returns the import hash of an executable and the list of dynamic imports in the executable examined to generate the hash. For Windows PE format, the hash is calculated according to the algorithm described in the FireEye blog post https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html. For Linux, a similar construction is used with each imported symbol represented as library.symbol without trimming the extension from the library part, while Darwin imports are the list of symbols without a library prefix and is equivalent to the Anomali SymHash https://www.anomali.com/blog/symhash.
The algorithm obtains the list of imported function names and converts them to all lowercase. Any file extension is removed and then the MD5 hash of the ordered list of symbols, separated by commas, is calculated.
Darwin:
___error __exit _clock_gettime
Linux:
libc.so.6.free .agwrite libc.so.6.puts
Windows:
kernel32.writefile kernel32.writeconsolew kernel32.waitformultipleobjects
func (*File) Sections ¶
Sections returns the names and sizes of object file sections in the order that they appear in file.
type Section ¶
type Section struct { Name string // Name is the platform-specific name of the section. Size uint64 // Size of the uncompressed data of the section. FileSize uint64 // Size of the section data in the file. Entropy float64 // Entropy is the Shannon entropy of the section data in bits. VarEntropy float64 // VarEntropy is an estimate of the variance of the section entropy. Flags uint32 // Flags holds platform-specific section flags. }
Section holds basic executable section information.