toutoumomoma

package module
v0.0.0-...-76e39db Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 26, 2024 License: BSD-3-Clause Imports: 13 Imported by: 3

README

toutoumomoma go.dev reference

toutoumomoma provides functions that may help you to answer the question of an executable, “是偷偷摸摸吗?

  • Stripped: scan files that may be executable and report whether they are a Go executable that has had its symbols stripped.

  • ImportHash: calculate the imphash of an executable with dynamic imports.

  • GoSymbolHash: calculate an imphash analogue for Go executables compiled by the gc-compiler.

    The GoSymbolHash 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 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 Go 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. GoSymbolHash may be calculated including or excluding standard library imports.

  • Sections: provide section size and entropy statistics for an executable.

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

Examples

Constants

This section is empty.

Variables

View Source
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

func GoSymbolHash(path string, stdlib bool) (hash []byte, imports []string, err error)

GoSymbolHash is a convenience wrapper around File.GoSymbolHash.

func ImportHash

func ImportHash(path string) (hash []byte, imports []string, err error)

ImportHash is a convenience wrapper around File.ImportHash.

func NameEntropy

func NameEntropy(symbols []string) (entropy, variance float64)

NameEntropy returns the entropy and entropy variance for the given import symbols names as a set.

func Stripped

func Stripped(path string) (sneaky bool, err error)

Stripped is a convenience wrapper around File.Stripped.

Types

type File

type File struct {
	// contains filtered or unexported fields
}

File holds an executable object file.

func NewFile

func NewFile(r io.ReaderAt) (*File, error)

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

func Open(path string) (*File, error)

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

func (f *File) Close() error

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

func (f *File) GoSymbolHash(stdlib bool) (hash []byte, imports []string, err error)

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

func (f *File) ImportHash() (hash []byte, imports []string, err error)

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

func (f *File) Sections() ([]Section, error)

Sections returns the names and sizes of object file sections in the order that they appear in file.

func (*File) Stripped

func (f *File) Stripped() (sneaky bool, err error)

Stripped examines the file and returns whether it is likely to be a Go executable that has had its symbols stripped.

func (*File) Type

func (f *File) Type() string

Type returns the type of the executable object file. It will be one of, "elf", "mach-o" or "pe".

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.

func Sections

func Sections(path string) ([]Section, error)

Sections is a convenience wrapper around File.Sections.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL