v3 candidate
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package disasm
|
||||
|
||||
import (
|
||||
"github.com/andydixon/nexus/internal/leviathan/document"
|
||||
"github.com/andydixon/nexus/internal/leviathan/parsers"
|
||||
)
|
||||
|
||||
// ImageAnalysis is a metadata-seeded analysis across file-backed executable
|
||||
// regions in an ELF or PE image.
|
||||
type ImageAnalysis struct {
|
||||
Info *parsers.ExecutableInfo `json:"info"`
|
||||
Programs []*Program `json:"programs"`
|
||||
Truncated bool `json:"truncated"`
|
||||
}
|
||||
|
||||
// DiscoverExecutable analyzes executable regions using header entries,
|
||||
// symbols and exports as roots. Budgets apply across the whole image.
|
||||
func DiscoverExecutable(d *document.Document, maxBytes int64, maxFunctions, maxInstr int) (*ImageAnalysis, error) {
|
||||
info, err := parsers.InspectExecutable(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if maxBytes <= 0 || maxBytes > 32<<20 {
|
||||
maxBytes = 8 << 20
|
||||
}
|
||||
if maxFunctions <= 0 || maxFunctions > 4096 {
|
||||
maxFunctions = 512
|
||||
}
|
||||
if maxInstr <= 0 || maxInstr > 1_000_000 {
|
||||
maxInstr = 131_072
|
||||
}
|
||||
analysis := &ImageAnalysis{Info: info}
|
||||
remainingBytes := maxBytes
|
||||
remainingFunctions := maxFunctions
|
||||
remainingInstr := maxInstr
|
||||
for _, region := range info.Regions {
|
||||
if remainingBytes <= 0 || remainingFunctions <= 0 || remainingInstr <= 0 {
|
||||
analysis.Truncated = true
|
||||
break
|
||||
}
|
||||
length := region.Size
|
||||
if length > 4<<20 {
|
||||
length = 4 << 20
|
||||
analysis.Truncated = true
|
||||
}
|
||||
if length > remainingBytes {
|
||||
length = remainingBytes
|
||||
analysis.Truncated = true
|
||||
}
|
||||
if length <= 0 {
|
||||
continue
|
||||
}
|
||||
buf, err := d.Range(region.Offset, length)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
seeds := make([]Seed, 0)
|
||||
for _, seed := range info.Seeds {
|
||||
if seed.Offset >= region.Offset && seed.Offset < region.Offset+length {
|
||||
seeds = append(seeds, Seed{Name: seed.Name, Entry: seed.Offset})
|
||||
}
|
||||
}
|
||||
if len(seeds) == 0 {
|
||||
seeds = append(seeds, Seed{Name: region.Name, Entry: region.Offset})
|
||||
}
|
||||
program := DiscoverFunctionsFromSeeds(buf, region.Offset, info.Arch, seeds, remainingFunctions, remainingInstr)
|
||||
analysis.Programs = append(analysis.Programs, program)
|
||||
remainingBytes -= length
|
||||
remainingFunctions -= len(program.Functions)
|
||||
remainingInstr -= program.Instructions
|
||||
analysis.Truncated = analysis.Truncated || program.Truncated
|
||||
}
|
||||
return analysis, nil
|
||||
}
|
||||
Reference in New Issue
Block a user