mirror of
https://github.com/blacktop/ipsw.git
synced 2026-05-08 12:22:26 +00:00
116 lines
3.0 KiB
Go
116 lines
3.0 KiB
Go
package kernelcache
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/apex/log"
|
|
"github.com/blacktop/go-macho"
|
|
"github.com/blacktop/go-plist"
|
|
"github.com/blacktop/ipsw/internal/utils"
|
|
"github.com/dominikbraun/graph"
|
|
)
|
|
|
|
func InspectKM(m *macho.File, filter string, explicitOnly, asJSON bool) (string, error) {
|
|
if sec := m.Section("__PRELINK_INFO", "__info"); sec != nil {
|
|
dat, err := sec.Data()
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to read __PRELINK_INFO.__info section: %v", err)
|
|
}
|
|
|
|
var prelink PrelinkInfo
|
|
if err := plist.NewDecoder(bytes.NewReader(dat)).Decode(&prelink); err != nil {
|
|
return "", fmt.Errorf("failed to decode prelink info: %v", err)
|
|
}
|
|
|
|
if asJSON {
|
|
jsonPL, err := json.Marshal(prelink)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to marshal prelink info: %v", err)
|
|
}
|
|
return string(jsonPL), nil
|
|
}
|
|
|
|
var whitelist []string
|
|
|
|
if len(filter) == 0 { // NO FILTER (add all bundles to whitelist)
|
|
for _, bundle := range prelink.PrelinkInfoDictionary {
|
|
if explicitOnly {
|
|
whitelist = append(whitelist, fmt.Sprintf("-b %s", bundle.ID))
|
|
} else {
|
|
whitelist = append(whitelist, bundle.ID)
|
|
}
|
|
}
|
|
} else {
|
|
re, err := regexp.Compile(filter)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to compile filter regex: %v", err)
|
|
}
|
|
|
|
var filterlist []string
|
|
var blacklist []string
|
|
|
|
for _, bundle := range prelink.PrelinkInfoDictionary {
|
|
if re.MatchString(bundle.ID) {
|
|
filterlist = append(filterlist, bundle.ID)
|
|
}
|
|
}
|
|
|
|
g := graph.New(graph.StringHash, graph.Directed(), graph.PreventCycles())
|
|
|
|
// generate dependency graph
|
|
for _, bundle := range prelink.PrelinkInfoDictionary {
|
|
if len(bundle.OSBundleLibraries) > 0 {
|
|
g.AddVertex(bundle.ID)
|
|
for dependency := range bundle.OSBundleLibraries {
|
|
g.AddVertex(dependency)
|
|
if err := g.AddEdge(bundle.ID, dependency); err != nil {
|
|
return "", fmt.Errorf("failed to add edge: %v", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
blacklist = append(blacklist, filterlist...)
|
|
|
|
// blacklist all bundles that dependacy paths contain filtered bundles
|
|
for _, skip := range filterlist {
|
|
for _, bundle := range prelink.PrelinkInfoDictionary {
|
|
path, err := graph.ShortestPath(g, bundle.ID, skip)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if len(path) > 0 {
|
|
blacklist = append(blacklist, bundle.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
// whitelist all bundles that are not blacklisted
|
|
for _, bundle := range prelink.PrelinkInfoDictionary {
|
|
if utils.StrSliceContains(blacklist, bundle.ID) {
|
|
utils.Indent(log.WithFields(log.Fields{
|
|
"bundle": bundle.ID,
|
|
}).Info, 2)("Filtered")
|
|
continue
|
|
}
|
|
if explicitOnly {
|
|
whitelist = append(whitelist, fmt.Sprintf("-b %s", bundle.ID))
|
|
} else {
|
|
whitelist = append(whitelist, bundle.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
if explicitOnly {
|
|
return strings.Join(whitelist, " "), nil
|
|
}
|
|
return strings.Join(whitelist, "\n"), nil
|
|
}
|
|
|
|
return "", fmt.Errorf("failed to find __PRELINK_INFO.__info section")
|
|
}
|