Code Monkey home page Code Monkey logo

go-macho's Introduction

go-macho

Go Go Reference License

Package macho implements access to and creation of Mach-O object files.


Why 🤔

This package goes beyond the Go's debug/macho to:

  • Cover ALL load commands and architectures
  • Provide nice summary string output
  • Allow for creating custom MachO files
  • Parse Objective-C runtime information
  • Parse Swift runtime information
  • Read/Write code signature information
  • Parse fixup chain information

Install

$ go get github.com/blacktop/go-macho

Getting Started

package main

import "github.com/blacktop/go-macho"

func main() {
    m, err := macho.Open("/path/to/macho")
    if err != nil {
        panic(err)
    }
    defer m.Close()

    fmt.Println(m.FileTOC.String())
}

License

MIT Copyright (c) 2020-2024 blacktop

go-macho's People

Contributors

blacktop avatar gdbinit avatar jkt-signal avatar mwpcheung avatar saagarjha avatar t0rr3sp3dr0 avatar zchee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-macho's Issues

Possible typo in SourceVersion?

Hi. Recently we upgraded from 1.0.25 to 1.1.79, which introduces a breaking change to some code like this:

if v, ok := *machof.SourceVersion; ok {
    fmt.Println(v.SourceVersionCmd.Version)
}

I noticed in this line:

go-macho/cmds.go

Lines 1475 to 1480 in 9ee75aa

type SourceVersion struct {
LoadBytes
types.DylibCodeSignDrsCmd
Version string
}

The SourceVersion struct member is modified to types.DylibCodeSignDrsCmd from types.DylibCodeSignDrsCmd at here. Is this a typo, or we are using this field in wrong way?

Thanks.

symtab.Search() method doesn't work

Hi,

Current symtabl.Search() has an imply that the symtab is already sorted, in that case, it could use sort.search() binary search method for searching a specific symbol. However, symtab is not a sorted array.

Thanks,
Chengdong

Error during decoding some MachO: failed to read parseSymtab: invalid name in symbol table '40393' in record at byte 0xc78

What happened?

Go-macho cannot load and parse this MachO, but IDA Pro can.
It's a big file, so splitted it into two parts:
com.hotchaipro.matchsolitaire.001.txt
com.hotchaipro.matchsolitaire.002.txt

Please use them by

cat com.hotchaipro.matchsolitaire.001.txt com.hotchaipro.matchsolitaire.002.txt > com.hotchaipro.matchsolitaire

How can we reproduce this?

The MachO is enclosed above.

go-macho version

v1.1.193

Search

  • I did search for other open and closed issues before opening this

Code of Conduct

  • I agree to follow this project's Code of Conduct

Additional context

No response

Add (*macho.File).GetObjCNonLazyCategories()

Thank you for this awesome library. It is simply fantastic!

I was wondering if it would be possible to add a GetObjCNonLazyCategories function to the *macho.File type, to get the categories from the __DATA.__objc_nlclslist section.

Thank you so much for your precious time and for making this library open 😊
-- tux_mind

Optionally suppress output to stdout

When using this lib I'm seeing Unsupported code directory version Runtime, please notify author. Based on how the library is being integrated (in a TUI environment) this notice mangles other output. Would you consider adding an API flag to globally disable or redirect these notices to another location (say a buffer that the caller can control)?

... and awesome library, highest-of-fives 🙌 .

Function Starts parse

i want to parse Function Starts, to get all function address.
like Mach0View.
image
the Function Starts use leb128 to record offset.

Hopefully can support this feature, or tell me other ways to do it.

Failure to read objective c classes

The following code results in error being thrown:

package main

import (
	"fmt"
	"github.com/blacktop/go-macho"
	"os"
)

func main() {
	f, err := macho.Open(os.Args[1])
	if err != nil {
		panic(err)
	}
	defer f.Close()

	classes, err := f.GetObjCClasses()
	if err != nil {
		panic(err)
	}

	for _, class := range classes {
		fmt.Printf("%s\n", class.Name)
	}
}

The error is failed to read objc_class_t at vmaddr 0x100008ae8: failed to read super class objc_class_t at vmaddr: 0x100008ae8; MachO does not contain dyld chained fixups.

With grep, objective c classes could easily be obtained

$ nm ~/Desktop/test\ flags | grep _OBJC_CLASS_ 
0000000100008bb0 S _OBJC_CLASS_$_AppDelegate
                 U _OBJC_CLASS_$_NSObject
                 U _OBJC_CLASS_$_NSViewController
0000000100008b10 S _OBJC_CLASS_$_TestKlasa
0000000100008ae8 S _OBJC_CLASS_$_ViewController
00000001000089b8 s __OBJC_CLASS_PROTOCOLS_$_AppDelegate
0000000100008a60 s __OBJC_CLASS_RO_$_AppDelegate
00000001000080d8 s __OBJC_CLASS_RO_$_TestKlasa
0000000100008048 s __OBJC_CLASS_RO_$_ViewController

Running otool -l on the binary shows that LC_DYLD_CHAINED_FIXUPS and LC_DYLD_EXPORTS_TRIE are present.

$ otool -l ~/Desktop/test\ flags
...
Load command 5
      cmd LC_DYLD_CHAINED_FIXUPS
  cmdsize 16
  dataoff 49152
 datasize 480
Load command 6
      cmd LC_DYLD_EXPORTS_TRIE
  cmdsize 16
  dataoff 49632
 datasize 200
...

This has been tested on MacOS m1, 12.5.

Export() creates malformed MachOs with bad Segment/Section boundaries

          > > I understand that you are solving for a particular use case w/ Signal or something else, but there is an issue w/ the MachOs generated by the export.go `Export` func where it produces MachOs that IDA Pro doesn't like and complains about the Segment/Sections boundaries being wrong?

I'm happy to take a look! I'll have a bit less time (as you infer, my earlier contributions have been for use at Signal and were fixing gaps that blocked me) but I've greatly appreciated all the time you saved me by having this here, so happy to pay that forward a bit. Do you happen to have a useful repro/test case? I don't have IDA Pro, but if you could send me some simple binary you generated with Export and the same one made the official way, I can try to understand the difference.

So the most popular use case is to extract DYLIBs from the dyld_shared_cache to RE purposes (to make them actually linkable/usable would be a stretch goal for sure 😉 In ipsw I have a currently hidden command that does it. ipsw dsc extract It is called here (the second would be extracting KEXTs from the kernelcache, and I guess 3rd would be to make crazy malformed MachOs for security research 😈 )

A source of truth would be what XCode does which can be invoked by calling ipsw dsc split dyld_shared_cache docs this uses the same lib as XCode to pull out DYLIBs (this is to support lldb and does a minimal amount of fixups required) I wrote my Export function by looking at the source for the lib and REing it's binary etc. Found here

The ipsw dsc extract command goes WAY above and beyond what XCode does by rebuilding the MachO and adding the slide/rebase info, adding all the symbol (public/private) to the symtab etc etc described in the NOTE here

Incase you were unaware, the process of creating the shared_cache throws away a lot of information when combining the dylibs togethers to the process of 'extracting' them back out isn't trivial.

So far the best project to do this is https://github.com/arandomdev/DyldExtractor

My solution if also very close, I think only missing the ObjC runtime info fixups, but there is some error in the logic of the go-macho Export function that people have reported to me saying Ghidra/IDA complain about the MachO's header and Segment/Section boundaries??

So I guess the test rig would be using ipsw where you can clone go-macho to a folder next to it and uncomment this line in the go.mod to test out fixes etc.

Originally posted by @blacktop in #37 (comment)

Failed to parse swift macho using macho.GetSwiftTypes

A panic error occurs when using macho.GetSwiftTypes to read the swift information in the IOSSwiftApp002 file in the IOSSwiftApp002.app package.
panic error:
failed to read type at address 0x10000935c: failed to read type kind class flags(kind: class generic: false, unique: true, version: 0, kind_flags: metadata_init:singleton|vtable): failed to read swift field: failed to read swift field record mangled type name; failed to read indirect context descriptor: failed to read swift context descriptor: EOF [recovered]

Development and testing environment:
macOS xcode version 14.2, iPhone 14 Pro simulator
Source code:
IOSSwiftApp002_project_code.zip
The app package where the macho file is located:
IOSSwiftApp002_iPhone14Pro_simulator_app_package_.zip
go-macho version : 1.1.182

A memory overflow error occurred when calling the function GetSwiftTypes

When analyzing the macho file in the ios app package, a memory overflow error occurs when using the GetSwiftTypes function in swift.go to obtain swift information; the tracking and debugging problem occurs in the readType(offset) function: when typ.Kind is types.CDKindClass and cD.FieldOffsetVectorOffset != 0, after reading the information of typ.FieldOffsets, when reading the information of Methods of types.VTable, the address of Method will be mistaken for the size of Methods; resulting in a memory application error.
Is the way I use it wrong?
The macho in the ios app package and the information in the machoview software:
image

macos system version: macos Monterey 12.6.2
xcode version: 14.2
swift --version: Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)
Target: x86_64-apple-darwin21.6.0

Unparsed Requirement Set

A likely older implementation of LC_CODE_SIGNATURE is likely breaking codesign.ParseCodeSignature. The binary we encountered has a requirement set of 1 which translates to the host requirement set. It appears that requirement is currently not parsed and the fall through condition raises an error.

Entry Point:

return nil, fmt.Errorf("failed to ParseCodeSignature: %v", err)

Error Point:

return "", fmt.Errorf("failed to dump requirements set; found unsupported codesign requirement type %s, please notify author\n", reqs.Type)

Reference: Requirement Sets
host—Applied to the direct host of this code module. Each code module in the hosting path can have its own host requirement, where the hosting path is the chain of code signing hosts starting with the most specific code known to be running, and ending with the root of trust (the kernel). [1]

File: https://www.virustotal.com/gui/file/17befb10e9c3d399cebc8d23d2355e9e3522f4a2cb83d2c7bf2b2726cbd255e9/details

  1. https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/RequirementLang/RequirementLang.html``

Codesign adhoc should be idempotent

          Sorry, didn't see your comments last week. Yeah, I did see this in practice with a particularly large binary (Electron Framework, i.e. Google Chrome. It's big.). I could add a config flag to let us not add in extra overhead for the timestamp (that's a solid 8KiB just by itself) and reduce some of my fudge factor to get more in line with Apple-generated signature sizes.

Also if you keep adhoc codesigning a binary it just keeps growing that LINKEDIT segment

Oops, that's definitely a bug, we should be calculating based on the signature-less "before" size. I'll send you another PR.

Originally posted by @jkt-signal in #38 (comment)

Support for SEP-specific load commands

Is your feature request related to a problem? Please describe.

Upon the analysis of recent SEP firmwares, the following output can be found:

found NEW load command: LoadCmd(134217731) (please let the author know via https://github.com/blacktop/go-macho/issues)
found NEW load command: LoadCmd(134217729) (please let the author know via https://github.com/blacktop/go-macho/issues)
found NEW load command: LoadCmd(134217730) (please let the author know via https://github.com/blacktop/go-macho/issues)

Thus, these load commands will need to be implemented into go-macho.

Describe the solution you'd like

The implementation of these (most likely) SEP-specific load commands into go-macho.

Describe alternatives you've considered

Ignoring these SEP load commands if they are indecipherable.

Search

  • I did search for other open and closed issues before opening this

Code of Conduct

  • I agree to follow this project's Code of Conduct

Additional context

A example of a SEP firmware with Mach-Os containing these load commands can be found in the iOS build 21F90 on iPhone16,1.

Parse fail

test.zip

if info, err := m.GetObjCImageInfo(); err == nil {
fmt.Println(info.Flags)
} else if !errors.Is(err, macho.ErrObjcSectionNotFound) {
log.Error(err.Error())
}

Exposing functions and dylibs

We're looking to reduce the amount of code we need to maintain(fork of go-macho), and I was wondering if you'd be open to incorporating a feature that lists all functions and dylibs into the existing structure. This would enable us to extract the list of functions and dylibs directly from the Mach-O file.

The changes would primarily be in file.go, where we would extend the type File struct { to include Dylibs []*Dylib, along with appending new entries using f.Dylibs = append(f.Dylibs, l).

Additionally, it would be beneficial to have the following fields available in the file information:

DylibIDs: []*DylibID
Dylinkers: []*LoadDylinker
DyldEnvironments: []*DyldEnvironment
SourceVersions: []*SourceVersion
LinkerOptions: []*LinkerOption

1.1.198 release/tag?

What happened?

github.com/anchore/quill had this PR automatically opened by dependabot 2 weeks ago anchore/quill#349 to update to 1.1.198, so there was apparently a 1.1.198 tag at this time? Looking at https://github.com/blacktop/go-macho/tags, there's a 1.1.198 tag but this tag was pushed in the last 24 hours?

In light of the xz hack, I'm trying to understand if that's expected, or if something is off?

How can we reproduce this?

Trying to build github.com/anchore/quill with make build results in

  ⨯ release failed after 0s                  error=failed to build for linux_ppc64le: exit status 1: go: downloading github.com/blacktop/go-macho v1.1.198
verifying github.com/blacktop/[email protected]: checksum mismatch
	downloaded: h1:iCe8aO/oukUuksEuT7rgQOL/kDvMyxZjyc9dvYYUNEs=
	go.sum:     h1:XzLkto28L186FboxM7c7IUhQJvxCK/6J/RdQ6/SPOW4=

SECURITY ERROR
This download does NOT match an earlier download recorded in go.sum.
The bits may have been replaced on the origin server, or an attacker may
have intercepted the download attempt.

go-macho version

1.1.198

Search

  • I did search for other open and closed issues before opening this

Code of Conduct

  • I agree to follow this project's Code of Conduct

Additional context

No response

Report 'Unsupport code directory version' for fat MachO files

When analyzing a sample file (sha256: 906c55e45f37375c6ef8501a27f3e485bc75958ad4be73877000b30d14c99687), this error shows on calling OpenFat:

Unsupported code directory version Runtime, please notify author

Seems the error is caused at here. I read XNU's source code about it and found the corresponding struct.

However, when trying to implement it, it seems hard to decided if those fields should be read, since there does not have a good way to tell if those fields exists or not, unlike fields like scatterOffset and teamOffset which can be used to tell if types.CodeDirectory.Scatter and types.CodeDirectory.TeamID should be filled. Is there any recommendations so I can implement this part?

a small bug

objc.go line 1407

//this code caused all CFString64T of the return value the same value
cfstrings[idx].CFString64T =&cfstr 

change to follow to fix

cfstrings[idx].CFString64T =&cfStrTypes[idx];// &cfstr

Selector pointer inside the __objc_selrefs

Hi, first thank you for this awesome library. I would like to know if it is possible to include the original pointer inside the __objc_selrefs for the selectors, something like:

type Selector struct {
        SelRefsPointer uint64 // this field would be new one
        VMAddr uint64
        Name   string
}

My use-case for this is that I am disassembling binaries and inside the disassembly I see the addresses inside the __objc_selrefs and adding this new field would make it easier to do lookups.

facing error : "invalid magic number in record at byte 0x0"

I am trying to validate the existing application like firefox. It is failing with error: "invalid magic number in record at byte 0x0"
When I am trying with otool it is giving magic number as

Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
0xfeedfacf 16777223 3 0x00 2 34 4688 0x00a18085

Go is a very new language to me so could not understand much code. And Not sure what is causing this issue. can you help me in understanding and troubleshooting this.

Customized IPA re signature library, capable of making contacts [email protected] ,$1000+

Is your feature request related to a problem? Please describe.

Customized IPA re signature library, capable of making contacts [email protected] ,$1000+

Describe the solution you'd like

Customized IPA re signature library, capable of making contacts [email protected] ,$1000+

Describe alternatives you've considered

Customized IPA re signature library, capable of making contacts [email protected] ,$1000+

Search

  • I did search for other open and closed issues before opening this

Code of Conduct

  • I agree to follow this project's Code of Conduct

Additional context

No response

Handle Large Bit Fields

What happened?

We always set bit fields to unsigned int, but that fails when we have a bit field larger than 32 bits.

Width of bit-field 'i' (128 bits) exceeds the width of its type (32 bits)

How can we reproduce this?

Decompile this:

@implementation C : NSObject {
    __int128 i : 128;
}

@end

go-macho version

v1.1.208

Search

  • I did search for other open and closed issues before opening this

Code of Conduct

  • I agree to follow this project's Code of Conduct

Additional context

No response

get super class infomations fail

oc code

`

#import <UIKit/UIKit.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import <MobileCoreServices/UTCoreTypes.h>
@interface ViewController : UIViewController

@EnD

`

ipsw not display the super class infomations
ipsw macho info --obj

@interface ViewController : { // 0x2000095d0
/* instance methods */

-[ViewController viewDidLoad]; // 0x100005898
@EnD

Mac OS X Fragile Compatibility

Is your feature request related to a problem? Please describe.

The current implementation of go-macho only properly supports the non-fragile version of the Mac OS X Objective-C Runtime. Code that targeting the fragile version of the runtime may not be parsed correctly. In clang, the runtime can be defined through the -fobjc-runtime=${OBJC_RUNTIME} flag (https://clang.llvm.org/doxygen/classclang_1_1ObjCRuntime.html#af19fe070a7073df4ecc666b44137c4e5).

Describe the solution you'd like

Have a solution that is able to handle both runtime variants. If possible to distinguish the runtime used from the binary, implement full support, otherwise prioritize compatibility with the non-fragile runtime.

Describe alternatives you've considered

Not implement support for the Mac OS X Fragile Runtime and explicitly state that go-macho support the non-fragile runtime only. If possible, reject or warn about binaries using incompatible runtimes.

Search

  • I did search for other open and closed issues before opening this

Code of Conduct

  • I agree to follow this project's Code of Conduct

Additional context

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.