Skip to content

Commit

Permalink
fix: ipsw macho info --all-fileset-entries --json cmd to output an …
Browse files Browse the repository at this point in the history
…array of JSON for the fileset and all it's entries 🐟
  • Loading branch information
blacktop committed Aug 22, 2024
1 parent dc6cf31 commit 64878f2
Showing 1 changed file with 58 additions and 21 deletions.
79 changes: 58 additions & 21 deletions cmd/ipsw/cmd/macho/macho_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import (
"github.com/fatih/color"
"github.com/fullsailor/pkcs7"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"golang.org/x/exp/slices"
)
Expand Down Expand Up @@ -194,6 +195,7 @@ var machoInfoCmd = &cobra.Command{
showStrings := viper.GetBool("macho.info.strings")
showSplitSeg := viper.GetBool("macho.info.split-seg")
showBitCode := viper.GetBool("macho.info.bit-code")
asJSON := viper.GetBool("macho.info.json")

doDemangle := viper.GetBool("macho.info.demangle")

Expand All @@ -216,6 +218,18 @@ var machoInfoCmd = &cobra.Command{
}
}

if options > onlyLoadCommands {
var setFlags []string
cmd.Flags().VisitAll(func(f *pflag.Flag) {
if f.Changed {
if !slices.Contains([]string{"all-fileset-entries", "fileset-entry", "json", "verbose"}, f.Name) {
setFlags = append(setFlags, f.Name)
}
}
})
log.Warnf("--json flag is set; other flag(s) [ %s ] not currently supported (if needed create an Github issue)", "--"+strings.Join(setFlags, ", --"))
}

machoPath := filepath.Clean(args[0])

if info, err := os.Stat(machoPath); os.IsNotExist(err) {
Expand All @@ -228,7 +242,12 @@ var machoInfoCmd = &cobra.Command{
}

if ok, err := magic.IsMachO(machoPath); !ok {
return fmt.Errorf(err.Error())
return err
}

folder := filepath.Dir(machoPath) // default to folder of macho file
if len(extractPath) > 0 {
folder = extractPath
}

// first check for fat file
Expand All @@ -242,13 +261,14 @@ var machoInfoCmd = &cobra.Command{
return err
}
} else {
defer fat.Close()

var arches []string
var shortArches []string
for _, arch := range fat.Arches {
arches = append(arches, fmt.Sprintf("%s, %s", arch.CPU, arch.SubCPU.String(arch.CPU)))
shortArches = append(shortArches, strings.ToLower(arch.SubCPU.String(arch.CPU)))
}

if len(selectedArch) > 0 {
found := false
for i, opt := range shortArches {
Expand All @@ -272,11 +292,6 @@ var machoInfoCmd = &cobra.Command{
}
}

folder := filepath.Dir(machoPath) // default to folder of macho file
if len(extractPath) > 0 {
folder = extractPath
}

if dumpCert {
if cs := m.CodeSignature(); cs != nil {
if len(m.CodeSignature().CMSSignature) > 0 {
Expand Down Expand Up @@ -395,22 +410,21 @@ var machoInfoCmd = &cobra.Command{
// Fileset MachO type
if len(filesetEntry) > 0 {
if m.FileTOC.FileHeader.Type == types.MH_FILESET {
var dcf *fixupchains.DyldChainedFixups
if m.HasFixups() {
dcf, err = m.DyldChainedFixups()
if err != nil {
return fmt.Errorf("failed to parse fixups from in memory MachO: %v", err)
}
}

baseAddress := m.GetBaseAddress()
m, err = m.GetFileSetFileByName(filesetEntry)
if err != nil {
return fmt.Errorf("failed to parse entry %s: %v", filesetEntry, err)
}

if extractfilesetEntry {
if err := m.Export(filepath.Join(folder, filesetEntry), dcf, baseAddress, nil); err != nil { // TODO: do I want to add any extra syms?
var dcf *fixupchains.DyldChainedFixups
if m.HasFixups() {
dcf, err = m.DyldChainedFixups()
if err != nil {
return fmt.Errorf("failed to parse fixups from in memory MachO: %v", err)
}
}
baseAddress := m.GetBaseAddress()
// TODO: do I want to add any extra syms?
if err := m.Export(filepath.Join(folder, filesetEntry), dcf, baseAddress, nil); err != nil {
return fmt.Errorf("failed to export entry MachO %s; %v", filesetEntry, err)
}
log.Infof("Created %s", filepath.Join(folder, filesetEntry))
Expand All @@ -420,28 +434,51 @@ var machoInfoCmd = &cobra.Command{
}
} else if viper.GetBool("macho.info.all-fileset-entries") {
if m.FileTOC.FileHeader.Type == types.MH_FILESET {
filesetEntries := []*macho.File{m}
for _, fe := range m.FileSets() {
mfe, err := m.GetFileSetFileByName(fe.EntryID)
if err != nil {
return fmt.Errorf("failed to parse entry %s: %v", filesetEntry, err)
}
fmt.Printf("\n%s\n\n%s\n", fe.EntryID, mfe.FileTOC.String())
if asJSON {
filesetEntries = append(filesetEntries, mfe)
} else {
fmt.Printf("\n%s\n\n%s\n", fe.EntryID, mfe.FileTOC.String())
}
}
if asJSON {
dat, err := json.Marshal(filesetEntries)
if err != nil {
return fmt.Errorf("failed to marshal MachO fileset entries as JSON: %v", err)
}
fmt.Println(string(dat))
}
return nil
} else {
return fmt.Errorf("MachO type is not MH_FILESET (cannot use --fileset-entry)")
}
}

if showHeader && !showLoadCommands {
fmt.Println(m.FileHeader.String())
if asJSON {
dat, err := m.FileHeader.MarshalJSON()
if err != nil {
return fmt.Errorf("failed to marshal MachO header as JSON: %v", err)
}
fmt.Println(string(dat))
return nil
} else {
fmt.Println(m.FileHeader.String())
}
}
if showLoadCommands || options == 0 {
if viper.GetBool("macho.info.json") {
if asJSON {
dat, err := m.FileTOC.MarshalJSON()
if err != nil {
return fmt.Errorf("failed to marshal MachO table of contents as JSON: %v", err)
}
fmt.Println(string(dat))
return nil
} else {
fmt.Println(m.FileTOC.String())
}
Expand Down

0 comments on commit 64878f2

Please sign in to comment.