in auditbeat/module/file_integrity/exeobjparser.go [57:258]
func (fields exeObjParser) Parse(dst mapstr.M, path string) (err error) {
if dst == nil {
return errors.New("cannot use nil dst for file parser")
}
defer func() {
switch r := recover().(type) {
case nil:
case error:
// This will catch runtime.Error panics differentially.
// These are the most likely panics during the analysis.
err = fmt.Errorf("error panic during executable parser analysis of %s: %w", path, r)
default:
err = fmt.Errorf("panic during executable parser analysis of %s: %v", path, r)
}
}()
f, err := toutoumomoma.Open(path)
if err != nil {
if err == toutoumomoma.ErrUnknownFormat {
return nil
}
return err
}
defer f.Close()
typ := strings.ToLower(f.Type())
if typ == "mach-o" {
typ = "macho"
}
var details mapstr.M
d, err := dst.GetValue(typ)
if err != nil {
if err != mapstr.ErrKeyNotFound {
return fmt.Errorf("invalid destination key: %q not found in map", typ)
}
details = make(mapstr.M)
dst[typ] = details
} else {
switch d := d.(type) {
case mapstr.M:
details = d
default:
return fmt.Errorf("cannot write %s details to %T", typ, d)
}
}
if all := wantFields(fields, "file."+typ+".sections"); all || wantFields(fields,
"file."+typ+".sections.name",
"file."+typ+".sections.virtual_size",
"file."+typ+".sections.physical_size",
"file."+typ+".sections.entropy",
"file."+typ+".sections.var_entropy",
) {
sections, err := f.Sections()
if err != nil {
return err
}
var (
name *string
size *uint64
fileSize *uint64
entropy *float64
varEntropy *float64
wantName, wantSize, wantFileSize, wantEntropy, wantVariance bool
)
if !all {
wantName = wantFields(fields, "file."+typ+".sections.name")
wantSize = wantFields(fields, "file."+typ+".sections.virtual_size")
wantFileSize = wantFields(fields, "file."+typ+".sections.physical_size")
wantEntropy = wantFields(fields, "file."+typ+".sections.entropy")
wantVariance = wantFields(fields, "file."+typ+".sections.var_entropy")
}
if len(sections) != 0 {
// TODO: Replace this []section with a []mapstr.M if additional
// section attributes are added from another parser.
stats := make([]objSection, len(sections))
for i, s := range sections {
s := s
if all {
name = &s.Name
size = &s.Size
entropy = &s.Entropy
varEntropy = &s.VarEntropy
} else {
if wantName {
name = &s.Name
}
if wantSize {
size = &s.Size
}
if wantFileSize {
fileSize = &s.FileSize
}
if wantEntropy {
entropy = &s.Entropy
}
if wantVariance {
varEntropy = &s.VarEntropy
}
}
stats[i] = objSection{
Name: name,
Size: size,
FileSize: fileSize,
Entropy: entropy,
VarEntropy: varEntropy,
}
}
details["sections"] = stats
}
}
if wantFields(fields,
"file.pe.imphash",
"file.macho.symhash",
"file."+typ+".import_hash",
"file."+typ+".imports",
"file."+typ+".imports_names_entropy",
"file."+typ+".imports_names_var_entropy",
) {
h, symbols, err := f.ImportHash()
if err != nil {
return err
}
imphash := Digest(h)
if wantFields(fields, "file."+typ+".import_hash") {
details["import_hash"] = imphash
}
switch typ {
case "pe":
if wantFields(fields, "file.pe.imphash") {
details["imphash"] = imphash
}
case "macho":
if wantFields(fields, "file.macho.symhash") {
details["symhash"] = imphash
}
}
if len(symbols) != 0 {
if wantFields(fields, "file."+typ+".imports") {
details["imports"] = symbols
}
wantEntropy := wantFields(fields, "file."+typ+".imports_names_entropy")
wantVariance := wantFields(fields, "file."+typ+".imports_names_var_entropy")
if wantEntropy || wantVariance {
entropy, varEntropy := toutoumomoma.NameEntropy(symbols)
if wantEntropy {
details["imports_names_entropy"] = entropy
}
if wantVariance {
details["imports_names_var_entropy"] = varEntropy
}
}
}
}
if wantFields(fields,
"file."+typ+".go_import_hash",
"file."+typ+".go_imports",
"file."+typ+".go_imports_names_entropy",
"file."+typ+".go_imports_names_var_entropy",
) {
h, symbols, err := f.GoSymbolHash(false)
if err != nil {
if err == toutoumomoma.ErrNotGoExecutable {
return nil
}
return err
}
if wantFields(fields, "file."+typ+".go_import_hash") {
details["go_import_hash"] = Digest(h)
}
if len(symbols) != 0 {
if wantFields(fields, "file."+typ+".go_imports") {
details["go_imports"] = symbols
}
wantEntropy := wantFields(fields, "file."+typ+".go_imports_names_entropy")
wantVariance := wantFields(fields, "file."+typ+".go_imports_names_variance")
if wantEntropy || wantVariance {
entropy, varEntropy := toutoumomoma.NameEntropy(symbols)
if wantEntropy {
details["go_imports_names_entropy"] = entropy
}
if wantVariance {
details["go_imports_names_var_entropy"] = varEntropy
}
}
}
}
if wantFields(fields, "file."+typ+".go_stripped") {
stripped, err := f.Stripped()
if err != nil {
return err
}
details["go_stripped"] = stripped
}
return nil
}