format go code

This commit is contained in:
nganhkhoa 2023-06-26 15:28:16 +07:00
parent b8d8343835
commit 2eede8f9b2
12 changed files with 542 additions and 544 deletions

View File

@ -18,4 +18,3 @@ func (action *removeExports) withFat(ff *FatFile) error {
func NewRemoveExportsAction() *removeExports {
return &removeExports{}
}

View File

@ -20,4 +20,3 @@ func (action *removeImports) withFat(ff *FatFile) error {
func NewRemoveImportsAction() *removeImports {
return &removeImports{}
}

View File

@ -1,7 +1,7 @@
package action
import (
"fmt"
"fmt"
// log "github.com/sirupsen/logrus"
. "ios-wrapper/internal/wrapper/ofile"
@ -11,52 +11,52 @@ import (
type saveImports struct{}
func (action *saveImports) withMacho(mf *MachoFile) error {
calculateHash := func(name string) uint32 {
var h uint32 = 0x811c9dc5
for _, s := range name {
h ^= uint32(s)
h *= 0x01000193
}
return h
}
calculateHash := func(name string) uint32 {
var h uint32 = 0x811c9dc5
for _, s := range name {
h ^= uint32(s)
h *= 0x01000193
}
return h
}
mc := mf.Context()
mc := mf.Context()
symbols := []*protomodel.MachoInfo_BindSymbol{}
fmt.Println("struct imported_symbol {const char* name; const char* lib; uint32_t hash; int segment_i; uint64_t offset;};")
fmt.Println("const char* lib_to_resolve = \"main\";")
fmt.Println("struct imported_symbol imported_table[] = {")
for _, symbol := range mc.CollectBindSymbols() {
if symbol.Type() != "lazy" {
continue
}
dylib_hash := calculateHash(symbol.Dylib())
seg := mc.Segments()[symbol.Segment()]
fmt.Println("struct imported_symbol {const char* name; const char* lib; uint32_t hash; int segment_i; uint64_t offset;};")
fmt.Println("const char* lib_to_resolve = \"main\";")
fmt.Println("struct imported_symbol imported_table[] = {")
for _, symbol := range mc.CollectBindSymbols() {
if symbol.Type() != "lazy" {
continue
}
dylib_hash := calculateHash(symbol.Dylib())
seg := mc.Segments()[symbol.Segment()]
var offset uint64
var offset uint64
if symbol.Address() >= seg.Vmaddr() {
// this is virtual address
offset = symbol.Address() - seg.Vmaddr()
} else {
// this is file address
offset = symbol.Address() - seg.Fileoff()
}
if symbol.Address() >= seg.Vmaddr() {
// this is virtual address
offset = symbol.Address() - seg.Vmaddr()
} else {
// this is file address
offset = symbol.Address() - seg.Fileoff()
}
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.Segment(), offset);
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.Segment(), offset)
symbols = append(symbols,
&protomodel.MachoInfo_BindSymbol{
Name: symbol.Name(),
Libname: symbol.Dylib(),
Libhash: dylib_hash,
Segment: symbol.Segment(),
Offset: offset,
Name: symbol.Name(),
Libname: symbol.Dylib(),
Libhash: dylib_hash,
Segment: symbol.Segment(),
Offset: offset,
})
}
fmt.Println("};")
fmt.Printf("uint32_t nimports = %d;\n", len(symbols));
}
fmt.Println("};")
fmt.Printf("uint32_t nimports = %d;\n", len(symbols))
mf.Info().Symbols = symbols
return nil
}
@ -68,4 +68,3 @@ func (action *saveImports) withFat(ff *FatFile) error {
func NewSaveImportsAction() *saveImports {
return &saveImports{}
}

View File

@ -4,7 +4,7 @@ import (
"fmt"
"io/ioutil"
"os"
"strings"
"strings"
"github.com/alecthomas/kong"
log "github.com/sirupsen/logrus"
@ -65,10 +65,10 @@ func Cli() {
fat.FatJoin(arg.Macho, arg.Out)
return
} else if command == "bcell2header" {
arg := cli.BcellToHeader
bcell2header(arg.Bcell, arg.Out)
return
}
arg := cli.BcellToHeader
bcell2header(arg.Bcell, arg.Out)
return
}
var pc ProgramContext
var ofile OFile = nil
@ -106,23 +106,23 @@ func Cli() {
pc.outfile = arg.Out
pc.bcellfile = arg.Bcell
case "pepe":
case "pepe":
arg := cli.Pepe
ofile = NewOFile(arg.OFile)
if arg.FullRemoval {
pc.remove_exports = true
pc.remove_symbol_table = true
pc.remove_imports = true
pc.remove_inits = true
pc.remove_codesign = true
pc.remove_others = true
}
if arg.FullRemoval {
pc.remove_exports = true
pc.remove_symbol_table = true
pc.remove_imports = true
pc.remove_inits = true
pc.remove_codesign = true
pc.remove_others = true
}
pc.remove_imports = arg.RemoveBindSymbols
pc.remove_codesign = arg.RemoveCodeSign
pc.remove_codesign = arg.RemoveCodeSign
pc.remove_inits = arg.RemoveInitFunctions
pc.remove_others = arg.RemoveOthers
pc.remove_exports = arg.RemoveExports
pc.remove_symbol_table = arg.RemoveSymbolTable
pc.remove_others = arg.RemoveOthers
pc.remove_exports = arg.RemoveExports
pc.remove_symbol_table = arg.RemoveSymbolTable
pc.dylib_to_add = arg.Dylibs
pc.rpath_to_add = arg.Rpath
pc.outfile = arg.Out
@ -195,7 +195,7 @@ func displayBcell(bfile string) {
}
fmt.Printf(" | Bind Symbols:\n")
for _, symbol := range info.Symbols {
lib := strings.Replace(symbol.Libname, "/System/Library/Frameworks/", "", 1)
lib := strings.Replace(symbol.Libname, "/System/Library/Frameworks/", "", 1)
fmt.Printf(" | %s offset=0x%x segmentID=0x%x\n", symbol.Name, symbol.Offset, symbol.Segment)
fmt.Printf(" | from=%s\n", lib)
}
@ -255,7 +255,7 @@ func bcell2header(bfile string, header string) {
}
fmt.Printf(" | Bind Symbols:\n")
for _, symbol := range info.Symbols {
lib := strings.Replace(symbol.Libname, "/System/Library/Frameworks/", "", 1)
lib := strings.Replace(symbol.Libname, "/System/Library/Frameworks/", "", 1)
fmt.Printf(" | %s offset=0x%x segmentID=0x%x\n", symbol.Name, symbol.Offset, symbol.Segment)
fmt.Printf(" | from=%s\n", lib)
}

View File

@ -26,7 +26,7 @@ type RemoveCodesignArgument struct {
type RemoveImportsArgument struct {
Out string `short:"o" required name:"outfile" help:"Modified Mach-O/Fat binary output file" type:"path"`
Bcell string `short:"b" required help:"bcell.dat output file" type:"path"`
Bcell string `short:"b" required help:"bcell.dat output file" type:"path"`
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
}
@ -56,26 +56,26 @@ type LipoArgument struct {
}
type PepeArgument struct {
Out string `short:"o" required name:"outfile" help:"Output file after transformation" type:"path"`
Bcell string `short:"b" required help:"bcell.dat output file" type:"path"`
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
Dylibs []string `short:"l" help:"Add more LC_DYLIB"`
Rpath []string `short:"r" help:"Add more LC_RPATH"`
RemoveCodeSign bool `default:"false" negatable:"" help:"Remove LC_CODE_SIGNATURE"`
RemoveExports bool `default:"false" negatable:"" help:"Clear the export table/trie"`
RemoveSymbolTable bool `default:"true" negatable:"" help:"Remove LC_SYMTAB and LC_DYSYMTAB"`
RemoveOthers bool `default:"false" negatable:"" help:"Remove LC_FUNCTION_STARTS, LC_DATA_IN_CODE, ..."`
RemoveID bool `default:"false" negatable:"" help:"(TODO) Remove LC_ID_DYLIB"`
RemoveInitFunctions bool `default:"false" name:"remove-inits" negatable:"" help:"Clear MOD_INIT_FUNC section"`
RemoveBindSymbols bool `default:"false" name:"remove-imports" negatable:"" help:"Remove all bind symbols information"`
RemoveObjCString bool `default:"false" negatable:"" help:"(TODO) Remove references, string litteral to Objctive-C strings"`
RebuildLinkEdit bool `default:"false" negatable:"" help:"(TODO) Rebuild the LINKEDIT section"`
FullRemoval bool `default:"false" help:"Apply every removal possible"`
Out string `short:"o" required name:"outfile" help:"Output file after transformation" type:"path"`
Bcell string `short:"b" required help:"bcell.dat output file" type:"path"`
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
Dylibs []string `short:"l" help:"Add more LC_DYLIB"`
Rpath []string `short:"r" help:"Add more LC_RPATH"`
RemoveCodeSign bool `default:"false" negatable:"" help:"Remove LC_CODE_SIGNATURE"`
RemoveExports bool `default:"false" negatable:"" help:"Clear the export table/trie"`
RemoveSymbolTable bool `default:"true" negatable:"" help:"Remove LC_SYMTAB and LC_DYSYMTAB"`
RemoveOthers bool `default:"false" negatable:"" help:"Remove LC_FUNCTION_STARTS, LC_DATA_IN_CODE, ..."`
RemoveID bool `default:"false" negatable:"" help:"(TODO) Remove LC_ID_DYLIB"`
RemoveInitFunctions bool `default:"false" name:"remove-inits" negatable:"" help:"Clear MOD_INIT_FUNC section"`
RemoveBindSymbols bool `default:"false" name:"remove-imports" negatable:"" help:"Remove all bind symbols information"`
RemoveObjCString bool `default:"false" negatable:"" help:"(TODO) Remove references, string litteral to Objctive-C strings"`
RebuildLinkEdit bool `default:"false" negatable:"" help:"(TODO) Rebuild the LINKEDIT section"`
FullRemoval bool `default:"false" help:"Apply every removal possible"`
}
type BcellToHeaderArgument struct {
Out string `short:"o" required name:"outfile" help:"Header file name to output to" type:"path"`
Bcell string `short:"b" required help:"Input bcell.dat file" type:"existingfile"`
Out string `short:"o" required name:"outfile" help:"Header file name to output to" type:"path"`
Bcell string `short:"b" required help:"Input bcell.dat file" type:"existingfile"`
}
type Argument struct {
@ -89,13 +89,13 @@ type Argument struct {
Addr2Line Addr2LineArgument `cmd name:"addr2line" help:"Resolve crash address from DWARF file"`
Lipo LipoArgument `cmd help:"split Fat binary or join Mach-O binares"`
Pepe PepeArgument `cmd help:"custom command"`
BcellToHeader BcellToHeaderArgument `cmd name:"bcell2header" help:"Build C header file from bcell file"`
AddSection struct {
Out string `short:"o" required name:"outfile" help:"Output file after transformation"`
Data string `arg help:"Input data file to fill in this section, or null if not provided" type:"existingfile"`
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
Segment string `required help:"Segment name"`
Section string `required help:"Section name"`
Size int `required help:"Size of segment/section"`
} `cmd:"" default:"false" help:"(TODO) Add a new segment with 1 section, segment starts at the end of last segment"`
BcellToHeader BcellToHeaderArgument `cmd name:"bcell2header" help:"Build C header file from bcell file"`
AddSection struct {
Out string `short:"o" required name:"outfile" help:"Output file after transformation"`
Data string `arg help:"Input data file to fill in this section, or null if not provided" type:"existingfile"`
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
Segment string `required help:"Segment name"`
Section string `required help:"Section name"`
Size int `required help:"Size of segment/section"`
} `cmd:"" default:"false" help:"(TODO) Add a new segment with 1 section, segment starts at the end of last segment"`
}

View File

@ -35,16 +35,16 @@ func (printer *InfoPrinter) Print() {
}
symbols := mc.CollectBindSymbols()
for _, sym := range symbols {
fmt.Printf(
"%s (%s)\n\tStub=0x%x Address=0x%x\n\tDylib=%s\n",
sym.Name(),
sym.Type(),
sym.Stub(),
sym.Address(),
sym.Dylib(),
)
}
for _, sym := range symbols {
fmt.Printf(
"%s (%s)\n\tStub=0x%x Address=0x%x\n\tDylib=%s\n",
sym.Name(),
sym.Type(),
sym.Stub(),
sym.Address(),
sym.Dylib(),
)
}
fmt.Println("======")
}

View File

@ -38,12 +38,12 @@ func (uc *UserConfig) Protomodel() *protomodel.Config {
}
type ProgramContext struct {
remove_inits bool
remove_inits bool
remove_codesign bool
remove_imports bool
remove_others bool
remove_exports bool
remove_symbol_table bool
remove_others bool
remove_exports bool
remove_symbol_table bool
dylib_to_add []string
rpath_to_add []string
@ -96,18 +96,18 @@ func (pc *ProgramContext) Process(ofile OFile) {
}
if pc.remove_imports {
pc.AddAction(NewSaveImportsAction())
pc.AddAction(NewRemoveImportsAction())
pc.AddAction(NewRemoveImportsAction())
}
if pc.remove_symbol_table {
if pc.remove_symbol_table {
pc.AddAction(NewRemoveClassicSymbolAction())
}
if pc.remove_exports {
pc.AddAction(NewRemoveExportsAction())
}
}
if pc.remove_exports {
pc.AddAction(NewRemoveExportsAction())
}
ExperimentalFeature("Remove Unnecessary Info", func() {
if pc.remove_others {
pc.AddAction(NewRemoveUnnecessaryInfoAction())
}
if pc.remove_others {
pc.AddAction(NewRemoveUnnecessaryInfoAction())
}
})
pc.AddAction(NewAddRpathAction(pc.rpath_to_add))
pc.AddAction(NewAddDylibAction(pc.dylib_to_add))

View File

@ -4,9 +4,9 @@ import (
"bytes"
"encoding/binary"
"fmt"
"unsafe"
"unsafe"
// "bufio"
"io"
"io"
log "github.com/sirupsen/logrus"
@ -19,7 +19,7 @@ import "C"
type ImportSymbol struct {
name string
typ string
typ string
dylib string
segment uint32
segment_offset uint32
@ -30,7 +30,7 @@ type ImportSymbol struct {
pnum uint32
stub uint64
next int // only for LC_DYLD_CHAINED_FIXUPS
next int // only for LC_DYLD_CHAINED_FIXUPS
}
func (sym *ImportSymbol) Name() string {
@ -70,140 +70,140 @@ func (mc *MachoContext) CollectBindSymbols() []*ImportSymbol {
}
func (mc *MachoContext) findSegmentIndexAt(address uint64) int {
for i, segment := range mc.Segments() {
if segment.Fileoff() <= address && segment.Fileoff() + segment.Filesize() > address {
return i
}
}
return -1
for i, segment := range mc.Segments() {
if segment.Fileoff() <= address && segment.Fileoff()+segment.Filesize() > address {
return i
}
}
return -1
}
// New convention using LC_DYLD_CHAINED_FIXUPS
func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
start := mc.fixups.dataoff
size := mc.fixups.datasize
buf := mc.buf[start:start+size]
start := mc.fixups.dataoff
size := mc.fixups.datasize
buf := mc.buf[start : start+size]
// all pointers used are based from this **buf**
// until buf is freed, all pointers are valid
// remember to copy before moving out
header := (*C.uchar)(unsafe.Pointer(&buf[0]))
imports_table := C.GetImportsTable(header);
// all pointers used are based from this **buf**
// until buf is freed, all pointers are valid
// remember to copy before moving out
header := (*C.uchar)(unsafe.Pointer(&buf[0]))
imports_table := C.GetImportsTable(header)
// for i := 0; i < int(imports_table.size); i++ {
// s := C.GetImportsAt(&imports_table, C.int(i))
// name := C.GoString(s.name)
// symbol.dylib := string(mc.dylibs[int(s.lib_ordinal)-1].name[:])
// symbol_table = append(symbol_table, symbol)
// fmt.Printf("id=%d lib=%s name=%s\n", i, dylib, name)
// }
// for i := 0; i < int(imports_table.size); i++ {
// s := C.GetImportsAt(&imports_table, C.int(i))
// name := C.GoString(s.name)
// symbol.dylib := string(mc.dylibs[int(s.lib_ordinal)-1].name[:])
// symbol_table = append(symbol_table, symbol)
// fmt.Printf("id=%d lib=%s name=%s\n", i, dylib, name)
// }
var syms []*ImportSymbol
var sym ImportSymbol
segment_i := 0
for {
var fix C.struct_SegmentFix
fix_ptr := (*C.struct_SegmentFix)(unsafe.Pointer(&fix))
status := int(C.GetSegmentFixAt(header, C.uint(segment_i), fix_ptr))
segment_i += 1
if status == 2 {
break;
}
if status == 3 {
continue
}
// fmt.Printf("segment=%x format=%x page_count=%d\n", fix.segment, fix.format, fix.page_count)
// fmt.Printf("pages=%x\n", fix.pages)
pages := ([]C.ushort)(unsafe.Slice(fix.pages, fix.page_count))
for page_i := 0; page_i < int(fix.page_count); page_i++ {
// fmt.Printf(" page offset=%x\n", pages[page_i])
segment_i := 0
for {
var fix C.struct_SegmentFix
fix_ptr := (*C.struct_SegmentFix)(unsafe.Pointer(&fix))
status := int(C.GetSegmentFixAt(header, C.uint(segment_i), fix_ptr))
segment_i += 1
if status == 2 {
break
}
if status == 3 {
continue
}
// fmt.Printf("segment=%x format=%x page_count=%d\n", fix.segment, fix.format, fix.page_count)
// fmt.Printf("pages=%x\n", fix.pages)
pages := ([]C.ushort)(unsafe.Slice(fix.pages, fix.page_count))
for page_i := 0; page_i < int(fix.page_count); page_i++ {
// fmt.Printf(" page offset=%x\n", pages[page_i])
address := int64(fix.segment) + int64(pages[page_i])
mc.file.Seek(address, io.SeekStart)
address := int64(fix.segment) + int64(pages[page_i])
mc.file.Seek(address, io.SeekStart)
code := make([]byte, 8)
code := make([]byte, 8)
for {
mc.file.Read(code)
v := mc.byteorder.Uint64(code)
for {
mc.file.Read(code)
v := mc.byteorder.Uint64(code)
var bind C.int
var ret1 C.ulonglong
var ret2 C.ulonglong
next := C.ParseFixValue(C.int(fix.format), C.ulonglong(v),
&bind, &ret1, &ret2)
var bind C.int
var ret1 C.ulonglong
var ret2 C.ulonglong
next := C.ParseFixValue(C.int(fix.format), C.ulonglong(v),
&bind, &ret1, &ret2)
if bind == 1 {
s := C.GetImportsAt(&imports_table, C.int(ret1))
name := C.GoString(s.name)
dylib := string(mc.dylibs[int(s.lib_ordinal)-1].name[:])
if bind == 1 {
s := C.GetImportsAt(&imports_table, C.int(ret1))
name := C.GoString(s.name)
dylib := string(mc.dylibs[int(s.lib_ordinal)-1].name[:])
fmt.Printf("// 0x%x bind=%d (%s)%s\n", address, bind, dylib, name)
fmt.Printf("// 0x%x bind=%d (%s)%s\n", address, bind, dylib, name)
sym.address = uint64(address)
sym.name = name
sym.dylib = dylib
sym.typ = "lazy"
sym.address = uint64(address)
sym.name = name
sym.dylib = dylib
sym.typ = "lazy"
sym.segment = uint32(mc.findSegmentIndexAt(uint64(address)))
sym.file_address = uint64(address)
sym.next = int(next)
new_sym := sym
syms = append(syms, &new_sym)
} else {
fmt.Printf("// 0x%x rebase=%d target=0x%x high8=0x%x\n", address, bind, ret1, ret2)
}
sym.segment = uint32(mc.findSegmentIndexAt(uint64(address)))
sym.file_address = uint64(address)
sym.next = int(next)
new_sym := sym
syms = append(syms, &new_sym)
} else {
fmt.Printf("// 0x%x rebase=%d target=0x%x high8=0x%x\n", address, bind, ret1, ret2)
}
if int(next) == 0 {
break
}
// because the pointer move up 8 bytes already so we minus 8
address += int64(next * 4)
mc.file.Seek(int64(next * 4) - 8, io.SeekCurrent)
}
mc.file.Seek(0, io.SeekStart)
}
}
if int(next) == 0 {
break
}
// because the pointer move up 8 bytes already so we minus 8
address += int64(next * 4)
mc.file.Seek(int64(next*4)-8, io.SeekCurrent)
}
mc.file.Seek(0, io.SeekStart)
}
}
return syms
}
// Old convention using LC_DYLD_INFO_ONLY section and bytecode runner
func (mc *MachoContext) CollectBindSymbolsLegacy() []*ImportSymbol {
noLazy := (func() []*ImportSymbol {
start := mc.dyldinfo.bind_off
size := mc.dyldinfo.bind_size
end := start + size
buf := bytes.NewBuffer(mc.buf[start:end])
return mc.readBindStream(buf, "no lazy")
})()
noLazy := (func() []*ImportSymbol {
start := mc.dyldinfo.bind_off
size := mc.dyldinfo.bind_size
end := start + size
buf := bytes.NewBuffer(mc.buf[start:end])
return mc.readBindStream(buf, "no lazy")
})()
lazy := (func() []*ImportSymbol {
start := mc.dyldinfo.lazy_bind_off
size := mc.dyldinfo.lazy_bind_size
end := start + size
buf := bytes.NewBuffer(mc.buf[start:end])
return mc.readBindStream(buf, "lazy")
})()
lazy := (func() []*ImportSymbol {
start := mc.dyldinfo.lazy_bind_off
size := mc.dyldinfo.lazy_bind_size
end := start + size
buf := bytes.NewBuffer(mc.buf[start:end])
return mc.readBindStream(buf, "lazy")
})()
weak := (func() []*ImportSymbol {
start := mc.dyldinfo.weak_bind_off
size := mc.dyldinfo.weak_bind_size
end := start + size
buf := bytes.NewBuffer(mc.buf[start:end])
return mc.readBindStream(buf, "weak")
})()
weak := (func() []*ImportSymbol {
start := mc.dyldinfo.weak_bind_off
size := mc.dyldinfo.weak_bind_size
end := start + size
buf := bytes.NewBuffer(mc.buf[start:end])
return mc.readBindStream(buf, "weak")
})()
var symbols []*ImportSymbol
symbols = append(symbols, noLazy...)
symbols = append(symbols, lazy...)
symbols = append(symbols, weak...)
var symbols []*ImportSymbol
symbols = append(symbols, noLazy...)
symbols = append(symbols, lazy...)
symbols = append(symbols, weak...)
return symbols
return symbols
}
func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportSymbol {
size := buf.Len()
size := buf.Len()
if size == 0 {
return []*ImportSymbol{}
}
@ -237,7 +237,7 @@ func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportS
case BIND_OPCODE_DO_BIND:
if sym.name != "" {
new_sym := sym
new_sym.typ = typ
new_sym.typ = typ
syms = append(syms, &new_sym)
// fmt.Printf("Offset 0x%x: Symbol %+v\n", symoffset, sym)
@ -246,7 +246,7 @@ func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportS
"symbol": sym.name,
}).Trace("Bind")
sym.name = ""
sym.address += 8
sym.address += 8
}
offset += 1
break
@ -275,9 +275,9 @@ func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportS
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
sym.name, _ = buf.ReadString(0)
// ReadString input the 0x00 byte to buffer
// while we are string so we can remove that
sym.name = sym.name[:len(sym.name)-1]
// ReadString input the 0x00 byte to buffer
// while we are string so we can remove that
sym.name = sym.name[:len(sym.name)-1]
offset += uint(len(sym.name))
break
@ -301,12 +301,12 @@ func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportS
offset += br
break
case BIND_OPCODE_SET_TYPE_IMM:
fmt.Println("// symbol type", imm)
break
case BIND_OPCODE_SET_TYPE_IMM:
fmt.Println("// symbol type", imm)
break
default:
fmt.Println("BIND OPCODE NOT SUPPORTED", op, imm)
fmt.Println("BIND OPCODE NOT SUPPORTED", op, imm)
break
}
}

View File

@ -1,11 +1,11 @@
package macho
import (
"bytes"
"fmt"
"io"
"math/rand"
"time"
"bytes"
"math/rand"
"time"
log "github.com/sirupsen/logrus"
@ -272,93 +272,93 @@ func (mc *MachoContext) UpdateHeaderRemoveLcmd(size uint32) {
func (mc *MachoContext) RemoveBindSymbols() {
if !mc.WriteEnabled() {
return
}
return
}
rand.Seed(time.Now().UnixNano())
rand.Seed(time.Now().UnixNano())
if mc.dyldinfo == nil {
mc.removeBindSymbolsModern()
} else {
mc.removeBindSymbolsLegacy()
}
mc.ReworkForObjc()
mc.ReworkForObjc()
// due to some limitations when design this tool
// we write the c code to stdout lol
for _, symbol := range mc.CollectBindSymbols() {
if symbol.Type() != "lazy" {
continue
}
// due to some limitations when design this tool
// we write the c code to stdout lol
for _, symbol := range mc.CollectBindSymbols() {
if symbol.Type() != "lazy" {
continue
}
if mc.dyldinfo != nil {
// for legacy resolve the opcodes can be rewritten as 0x00
mc.file.WriteAt(make([]byte, 8), int64(symbol.file_address))
} else {
// for modern resolve the opcodes must not be rewritten as 0x00
// because it contains 2 types of opcodes, BIND and REBASE
// we only fix BIND and leave REBASE intact
// However, each opcodes has a *next* field to the next opcode
// So if we want to leave the header intact (contains pointers, size)
// We should rewrite this as REBASE opcode (so no symbol lookup happens)
// and it can continue
if mc.dyldinfo != nil {
// for legacy resolve the opcodes can be rewritten as 0x00
mc.file.WriteAt(make([]byte, 8), int64(symbol.file_address))
} else {
// for modern resolve the opcodes must not be rewritten as 0x00
// because it contains 2 types of opcodes, BIND and REBASE
// we only fix BIND and leave REBASE intact
// However, each opcodes has a *next* field to the next opcode
// So if we want to leave the header intact (contains pointers, size)
// We should rewrite this as REBASE opcode (so no symbol lookup happens)
// and it can continue
// we can write random values, because the loader just do
// (high8 << 56 | target) - mach_header
// or something, so no symbol lookup and no error at runtime
target := rand.Int()
high8 := rand.Int()
value := C.MakeRebaseFixupOpcode(C.int(symbol.next), C.ulonglong(target), C.ulonglong(high8))
v := make([]byte, 8)
mc.byteorder.PutUint64(v, uint64(value))
mc.file.WriteAt(v, int64(symbol.file_address))
}
}
// we can write random values, because the loader just do
// (high8 << 56 | target) - mach_header
// or something, so no symbol lookup and no error at runtime
target := rand.Int()
high8 := rand.Int()
value := C.MakeRebaseFixupOpcode(C.int(symbol.next), C.ulonglong(target), C.ulonglong(high8))
v := make([]byte, 8)
mc.byteorder.PutUint64(v, uint64(value))
mc.file.WriteAt(v, int64(symbol.file_address))
}
}
}
func (mc *MachoContext) removeBindSymbolsModern() {
// we don't mess up the chain
// we clear the imports table, and the raw opcodes
// clearing imports table disables static analysis
// clearing opcodes forces runtime manual mapping
// we don't mess up the chain
// we clear the imports table, and the raw opcodes
// clearing imports table disables static analysis
// clearing opcodes forces runtime manual mapping
// imports item are defined by mc.fixups.imports_format
// basic case is dyld_chained_import, 4 bytes
// imports item are defined by mc.fixups.imports_format
// basic case is dyld_chained_import, 4 bytes
start := mc.fixups.dataoff
size := mc.fixups.datasize
fixups := new(Fixups)
fixups.Deserialize(mc, mc.buf[start:start+size])
start := mc.fixups.dataoff
size := mc.fixups.datasize
fixups := new(Fixups)
fixups.Deserialize(mc, mc.buf[start:start+size])
start = mc.fixups.dataoff + fixups.imports_offset
size = fixups.imports_count * 4
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
mc.file.WriteAt(make([]byte, size), int64(start))
start = mc.fixups.dataoff + fixups.imports_offset
size = fixups.imports_count * 4
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
mc.file.WriteAt(make([]byte, size), int64(start))
// string reference are at the end of this section
start = mc.fixups.dataoff + fixups.symbols_offset
size = mc.fixups.Datasize() - fixups.symbols_offset
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
mc.file.WriteAt(make([]byte, size), int64(start))
// string reference are at the end of this section
start = mc.fixups.dataoff + fixups.symbols_offset
size = mc.fixups.Datasize() - fixups.symbols_offset
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
mc.file.WriteAt(make([]byte, size), int64(start))
fixups.imports_count = 0
mc.file.WriteAt(fixups.Serialize(mc), int64(mc.fixups.dataoff))
fixups.imports_count = 0
mc.file.WriteAt(fixups.Serialize(mc), int64(mc.fixups.dataoff))
}
func (mc *MachoContext) removeBindSymbolsLegacy() {
start := mc.dyldinfo.lazy_bind_off
size := mc.dyldinfo.lazy_bind_size
// set lazy opcodes to 0x00 == DO_BIND
// but no symbol state to bind
mc.file.WriteAt(make([]byte, size), int64(start))
start := mc.dyldinfo.lazy_bind_off
size := mc.dyldinfo.lazy_bind_size
// set lazy opcodes to 0x00 == DO_BIND
// but no symbol state to bind
mc.file.WriteAt(make([]byte, size), int64(start))
}
func (mc *MachoContext) ReworkForObjc() {
text_start := 0
data_end := 0
lc_main_offset := int64(0)
text_start := 0
data_end := 0
lc_main_offset := int64(0)
ptr := int64(0)
ptr := int64(0)
if mc.Is64bit() {
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
} else {
@ -366,218 +366,217 @@ func (mc *MachoContext) ReworkForObjc() {
}
for _, cmd := range mc.commands {
if cmd.Cmd() == LC_MAIN {
lc_main_offset = ptr + 8
ptr += int64(cmd.Cmdsize())
continue
}
if cmd.Cmd() != LC_SEGMENT_64 {
ptr += int64(cmd.Cmdsize())
if cmd.Cmd() == LC_MAIN {
lc_main_offset = ptr + 8
ptr += int64(cmd.Cmdsize())
continue
}
var segment = cmd.(*Segment64)
if cmd.Cmd() != LC_SEGMENT_64 {
ptr += int64(cmd.Cmdsize())
continue
}
var segment = cmd.(*Segment64)
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__TEXT")) == 0 {
section_ptr := ptr + 0x40 + 8
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__text")) == 0 {
text_start = int(section.Offset())
}
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__init_offsets")) == 0 {
// mc.file.WriteAt([]byte("__init_offsetx"), section_ptr)
// edit flags to not S_MOD_INIT_FUNC
mc.file.WriteAt([]byte{0, 0, 0, 0}, section_ptr + 0x40)
}
section_ptr += 16 * 2 + 8 * 2 + 4 * 8
}
}
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA_CONST")) == 0 {
section_ptr := ptr + 0x40 + 8
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_classlist")) == 0 {
mc.file.WriteAt([]byte("__objc_classbruh"), section_ptr)
}
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_nlclslist")) == 0 {
mc.file.WriteAt([]byte("__objc_nlclsbruh"), section_ptr)
}
section_ptr += 16 * 2 + 8 * 2 + 4 * 8
}
}
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 {
// end of __DATA segment, should have enough space for a pointer
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__TEXT")) == 0 {
section_ptr := ptr + 0x40 + 8
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__text")) == 0 {
text_start = int(section.Offset())
}
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__init_offsets")) == 0 {
// mc.file.WriteAt([]byte("__init_offsetx"), section_ptr)
// edit flags to not S_MOD_INIT_FUNC
mc.file.WriteAt([]byte{0, 0, 0, 0}, section_ptr+0x40)
}
section_ptr += 16*2 + 8*2 + 4*8
}
}
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA_CONST")) == 0 {
section_ptr := ptr + 0x40 + 8
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_classlist")) == 0 {
mc.file.WriteAt([]byte("__objc_classbruh"), section_ptr)
}
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_nlclslist")) == 0 {
mc.file.WriteAt([]byte("__objc_nlclsbruh"), section_ptr)
}
section_ptr += 16*2 + 8*2 + 4*8
}
}
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 {
// end of __DATA segment, should have enough space for a pointer
// __bss section is dynamically allocated at the end to or something, hmmge
// assume that it order correctly, which it should if compiled and not modified
sections := segment.Sections()
last := sections[len(sections) - 1]
data_end = int(last.Offset()) + int(last.Size())
// __bss section is dynamically allocated at the end to or something, hmmge
// assume that it order correctly, which it should if compiled and not modified
sections := segment.Sections()
last := sections[len(sections)-1]
data_end = int(last.Offset()) + int(last.Size())
if (last.Offset() == 0) {
before_last := sections[len(sections) - 2]
data_end += int(before_last.Offset()) + int(before_last.Size())
}
}
ptr += int64(cmd.Cmdsize())
if last.Offset() == 0 {
before_last := sections[len(sections)-2]
data_end += int(before_last.Offset()) + int(before_last.Size())
}
}
ptr += int64(cmd.Cmdsize())
}
mc.file.Seek(0, io.SeekStart)
mc.file.Seek(0, io.SeekStart)
// dummy value past the end of __DATA segment (logical size),
// its physical size is still a page
// mc.file.WriteAt([]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}, int64(0x81d8))
// dummy value past the end of __DATA segment (logical size),
// its physical size is still a page
// mc.file.WriteAt([]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}, int64(0x81d8))
// we use 2 registers, x8 x9
// stack values:
// [ return address, header, argc, argv, env, apple ]
// we need to store the return address, and parameters passed to main
// we also store our header address to not calculate many times
// we use 2 registers, x8 x9
// stack values:
// [ return address, header, argc, argv, env, apple ]
// we need to store the return address, and parameters passed to main
// we also store our header address to not calculate many times
/*
adr x8, 0
sub sp, sp, #0x30
str x30, [sp]
movz x9, #0x3d68 ; offset at this point
sub x8, x8, x9
str x8, [sp, #0x8]
str x0, [sp, #0x10]
str x1, [sp, #0x18]
str x2, [sp, #0x20]
str x3, [sp, #0x28]
/*
adr x8, 0
sub sp, sp, #0x30
str x30, [sp]
movz x9, #0x3d68 ; offset at this point
sub x8, x8, x9
str x8, [sp, #0x8]
str x0, [sp, #0x10]
str x1, [sp, #0x18]
str x2, [sp, #0x20]
str x3, [sp, #0x28]
movz x9, #0x81d8 ; offset to end of __DATA
add x9, x8, x9
ldr x9, [x9]
blr x9
ldr x8, [sp, #0x8]
ldr x0, [sp, #0x10]
ldr x1, [sp, #0x18]
ldr x2, [sp, #0x20]
ldr x3, [sp, #0x28]
movz x9, #0x3e3c ; offset to original main
add x9, x8, x9
blr x9
ldr x30, [sp]
add sp, sp, #0x10
ret
*/
movz x9, #0x81d8 ; offset to end of __DATA
add x9, x8, x9
ldr x9, [x9]
blr x9
ldr x8, [sp, #0x8]
ldr x0, [sp, #0x10]
ldr x1, [sp, #0x18]
ldr x2, [sp, #0x20]
ldr x3, [sp, #0x28]
movz x9, #0x3e3c ; offset to original main
add x9, x8, x9
blr x9
ldr x30, [sp]
add sp, sp, #0x10
ret
*/
// TODO: fix to work with offset larger than 0xffff
shellcode := []uint32{
0x10000008,
0xD100C3FF,
0xF90003FE,
0, // movz_shellcode_offset,
0xCB090108,
0xF90007E8,
0xF9000BE0,
0xF9000FE1,
0xF90013E2,
0xF90017E3,
0, // movz_data_end_offset,
0x8B090109,
0xF9400129,
0xD63F0120,
0xF94007E8,
0xF9400BE0,
0xF9400FE1,
0xF94013E2,
0xF94017E3,
0, // movz_main_offset,
0x8B090109,
0xD63F0120,
0xF94003FE,
0x910043FF,
0xD65F03C0,
}
// TODO: fix to work with offset larger than 0xffff
shellcode := []uint32{
0x10000008,
0xD100C3FF,
0xF90003FE,
0, // movz_shellcode_offset,
0xCB090108,
0xF90007E8,
0xF9000BE0,
0xF9000FE1,
0xF90013E2,
0xF90017E3,
0, // movz_data_end_offset,
0x8B090109,
0xF9400129,
0xD63F0120,
0xF94007E8,
0xF9400BE0,
0xF9400FE1,
0xF94013E2,
0xF94017E3,
0, // movz_main_offset,
0x8B090109,
0xD63F0120,
0xF94003FE,
0x910043FF,
0xD65F03C0,
}
ins_size_byte := 4
shellcode_offset := text_start - (ins_size_byte * len(shellcode))
main_offset := int(mc.entryoff)
ins_size_byte := 4
shellcode_offset := text_start - (ins_size_byte * len(shellcode))
main_offset := int(mc.entryoff)
encode_movz := func(v int) uint32 {
return uint32(uint32(v)<<5 | uint32(0x694)<<21 | uint32(0x09))
}
encode_movz := func(v int) uint32 {
return uint32(uint32(v)<<5 | uint32(0x694)<<21 | uint32(0x09))
}
movz_shellcode_offset := encode_movz(shellcode_offset)
movz_main_offset := encode_movz(main_offset)
movz_data_end_offset := encode_movz(data_end)
movz_shellcode_offset := encode_movz(shellcode_offset)
movz_main_offset := encode_movz(main_offset)
movz_data_end_offset := encode_movz(data_end)
shellcode[3] = movz_shellcode_offset
shellcode[10] = movz_data_end_offset
shellcode[19] = movz_main_offset
shellcode[3] = movz_shellcode_offset
shellcode[10] = movz_data_end_offset
shellcode[19] = movz_main_offset
fmt.Printf("// shellcode_offset=%x\n", shellcode_offset)
fmt.Printf("// main_offset=%x\n", main_offset)
fmt.Printf("// data_end=%x\n", data_end)
fmt.Printf("// movz_shellcode_offset=%x\n", movz_shellcode_offset)
fmt.Printf("// movz_main_offset=%x\n", movz_main_offset)
fmt.Printf("// movz_data_end_offset=%x\n", movz_data_end_offset)
fmt.Printf("// lc_main_offset=%x\n", lc_main_offset)
fmt.Printf("// shellcode_offset=%x\n", shellcode_offset)
fmt.Printf("// main_offset=%x\n", main_offset)
fmt.Printf("// data_end=%x\n", data_end)
fmt.Printf("// movz_shellcode_offset=%x\n", movz_shellcode_offset)
fmt.Printf("// movz_main_offset=%x\n", movz_main_offset)
fmt.Printf("// movz_data_end_offset=%x\n", movz_data_end_offset)
fmt.Printf("// lc_main_offset=%x\n", lc_main_offset)
offset := int64(shellcode_offset)
{
// fix main to point to our newly created shellcode
bs := make([]byte, 8)
mc.byteorder.PutUint64(bs, uint64(offset))
mc.file.WriteAt(bs, int64(lc_main_offset))
}
offset := int64(shellcode_offset)
{
// fix main to point to our newly created shellcode
bs := make([]byte, 8)
mc.byteorder.PutUint64(bs, uint64(offset))
mc.file.WriteAt(bs, int64(lc_main_offset))
}
bs := make([]byte, 4)
for _, ins := range shellcode {
mc.byteorder.PutUint32(bs, ins)
mc.file.WriteAt(bs, offset)
offset += 4
}
bs := make([]byte, 4)
for _, ins := range shellcode {
mc.byteorder.PutUint32(bs, ins)
mc.file.WriteAt(bs, offset)
offset += 4
}
}
func (mc *MachoContext) RemoveSymbolTable() {
// try to remove symtab and dysymtab
mc.removeSymtabCommand()
mc.removeDySymtabCommand()
// try to remove symtab and dysymtab
mc.removeSymtabCommand()
mc.removeDySymtabCommand()
}
func (mc *MachoContext) removeSymtabCommand() {
ptr := int64(0)
ptr := int64(0)
if mc.Is64bit() {
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
} else {
ptr, _ = mc.file.Seek(int64(Header_size), io.SeekStart)
}
var symtab_fix *Symtab
var symtab_fix *Symtab
for _, cmd := range mc.commands {
if cmd.Cmd() != LC_SYMTAB {
ptr += int64(cmd.Cmdsize())
ptr += int64(cmd.Cmdsize())
continue
}
var symtab = cmd.(*Symtab)
symtab_fix = symtab
var symtab = cmd.(*Symtab)
symtab_fix = symtab
// erase strings referenced
start := int64(symtab_fix.stroff)
size := symtab_fix.strsize
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
mc.file.WriteAt(make([]byte, size), start)
// erase strings referenced
start := int64(symtab_fix.stroff)
size := symtab_fix.strsize
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
mc.file.WriteAt(make([]byte, size), start)
// erase nlist64 symbol items
start = int64(symtab_fix.symoff)
size = symtab_fix.nsyms * 16
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
mc.file.WriteAt(make([]byte, size), start)
// erase nlist64 symbol items
start = int64(symtab_fix.symoff)
size = symtab_fix.nsyms * 16
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
mc.file.WriteAt(make([]byte, size), start)
symtab_fix.symoff = 0
symtab_fix.nsyms = 0
symtab_fix.stroff = 0
symtab_fix.strsize = 0
symtab_fix.symoff = 0
symtab_fix.nsyms = 0
symtab_fix.stroff = 0
symtab_fix.strsize = 0
mc.file.Seek(ptr, io.SeekStart)
mc.file.Write(symtab_fix.Serialize(mc))
break
break
}
mc.file.Seek(0, io.SeekStart)
mc.file.Seek(0, io.SeekStart)
}
func (mc *MachoContext) removeDySymtabCommand() {
ptr := int64(0)
ptr := int64(0)
if mc.Is64bit() {
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
} else {
@ -585,33 +584,33 @@ func (mc *MachoContext) removeDySymtabCommand() {
}
for _, cmd := range mc.commands {
if cmd.Cmd() != LC_DYSYMTAB {
ptr += int64(cmd.Cmdsize())
ptr += int64(cmd.Cmdsize())
continue
}
var dysymtab = cmd.(*DySymtab)
dysymtab_fix := dysymtab
dysymtab_fix.indirectsymoff = 0
dysymtab_fix.nindirectsyms = 0
var dysymtab = cmd.(*DySymtab)
dysymtab_fix := dysymtab
dysymtab_fix.indirectsymoff = 0
dysymtab_fix.nindirectsyms = 0
mc.file.Seek(ptr, io.SeekStart)
mc.file.Write(dysymtab_fix.Serialize(mc))
}
}
func (mc *MachoContext) RemoveExportTrie() {
var start int64
var size int
if mc.dyldinfo != nil {
// legacy export trie
start = int64(mc.dyldinfo.export_off)
size = int(mc.dyldinfo.export_size)
mc.file.WriteAt(make([]byte, size), start)
} else if mc.exports != nil {
// modern export trie
start = int64(mc.exports.dataoff)
size = int(mc.exports.datasize)
mc.file.WriteAt(make([]byte, size), start)
} else {
// no export trie (??)
// should never occur unless this binary is modified
}
var start int64
var size int
if mc.dyldinfo != nil {
// legacy export trie
start = int64(mc.dyldinfo.export_off)
size = int(mc.dyldinfo.export_size)
mc.file.WriteAt(make([]byte, size), start)
} else if mc.exports != nil {
// modern export trie
start = int64(mc.exports.dataoff)
size = int(mc.exports.datasize)
mc.file.WriteAt(make([]byte, size), start)
} else {
// no export trie (??)
// should never occur unless this binary is modified
}
}

View File

@ -397,13 +397,13 @@ func (lcmd *DyldInfo) Deserialize(mc *MachoContext, buf []byte) {
}
type Fixups struct {
fixups_version uint32
starts_offset uint32
imports_offset uint32
symbols_offset uint32
fixups_version uint32
starts_offset uint32
imports_offset uint32
symbols_offset uint32
imports_count uint32
imports_format uint32
symbols_format uint32
symbols_format uint32
}
func (lcmd *Fixups) Serialize(mc *MachoContext) []byte {
@ -516,25 +516,25 @@ func (lcmd *Symtab) Deserialize(mc *MachoContext, buf []byte) {
}
type DySymtab struct {
c LoadCmd
ilocalsym uint32
nlocalsym uint32
iextdefsym uint32
nextdefsym uint32
iundefsym uint32
nundefsym uint32
tocoff uint32
ntoc uint32
modtaboff uint32
nmodtab uint32
extrefsymoff uint32
nextrefsyms uint32
indirectsymoff uint32
nindirectsyms uint32
extreloff uint32
nextrel uint32
localrefoff uint32
nlocref uint32
c LoadCmd
ilocalsym uint32
nlocalsym uint32
iextdefsym uint32
nextdefsym uint32
iundefsym uint32
nundefsym uint32
tocoff uint32
ntoc uint32
modtaboff uint32
nmodtab uint32
extrefsymoff uint32
nextrefsyms uint32
indirectsymoff uint32
nindirectsyms uint32
extreloff uint32
nextrel uint32
localrefoff uint32
nlocref uint32
}
func (lcmd *DySymtab) Cmd() uint32 {
@ -558,20 +558,20 @@ func (lcmd *DySymtab) Serialize(mc *MachoContext) []byte {
binary.Write(buf, mc.byteorder, lcmd.nlocalsym)
binary.Write(buf, mc.byteorder, lcmd.iextdefsym)
binary.Write(buf, mc.byteorder, lcmd.nextdefsym)
binary.Write(buf, mc.byteorder, lcmd.iundefsym)
binary.Write(buf, mc.byteorder, lcmd.nundefsym)
binary.Write(buf, mc.byteorder, lcmd.tocoff)
binary.Write(buf, mc.byteorder, lcmd.ntoc)
binary.Write(buf, mc.byteorder, lcmd.modtaboff)
binary.Write(buf, mc.byteorder, lcmd.nmodtab)
binary.Write(buf, mc.byteorder, lcmd.extrefsymoff)
binary.Write(buf, mc.byteorder, lcmd.nextrefsyms)
binary.Write(buf, mc.byteorder, lcmd.indirectsymoff)
binary.Write(buf, mc.byteorder, lcmd.nindirectsyms)
binary.Write(buf, mc.byteorder, lcmd.extreloff)
binary.Write(buf, mc.byteorder, lcmd.nextrel)
binary.Write(buf, mc.byteorder, lcmd.localrefoff)
binary.Write(buf, mc.byteorder, lcmd.nlocref)
binary.Write(buf, mc.byteorder, lcmd.iundefsym)
binary.Write(buf, mc.byteorder, lcmd.nundefsym)
binary.Write(buf, mc.byteorder, lcmd.tocoff)
binary.Write(buf, mc.byteorder, lcmd.ntoc)
binary.Write(buf, mc.byteorder, lcmd.modtaboff)
binary.Write(buf, mc.byteorder, lcmd.nmodtab)
binary.Write(buf, mc.byteorder, lcmd.extrefsymoff)
binary.Write(buf, mc.byteorder, lcmd.nextrefsyms)
binary.Write(buf, mc.byteorder, lcmd.indirectsymoff)
binary.Write(buf, mc.byteorder, lcmd.nindirectsyms)
binary.Write(buf, mc.byteorder, lcmd.extreloff)
binary.Write(buf, mc.byteorder, lcmd.nextrel)
binary.Write(buf, mc.byteorder, lcmd.localrefoff)
binary.Write(buf, mc.byteorder, lcmd.nlocref)
return buf.Bytes()
}
@ -583,18 +583,18 @@ func (lcmd *DySymtab) Deserialize(mc *MachoContext, buf []byte) {
binary.Read(r, mc.byteorder, &lcmd.nlocalsym)
binary.Read(r, mc.byteorder, &lcmd.iextdefsym)
binary.Read(r, mc.byteorder, &lcmd.nextdefsym)
binary.Read(r, mc.byteorder, &lcmd.iundefsym)
binary.Read(r, mc.byteorder, &lcmd.nundefsym)
binary.Read(r, mc.byteorder, &lcmd.tocoff)
binary.Read(r, mc.byteorder, &lcmd.ntoc)
binary.Read(r, mc.byteorder, &lcmd.modtaboff)
binary.Read(r, mc.byteorder, &lcmd.nmodtab)
binary.Read(r, mc.byteorder, &lcmd.extrefsymoff)
binary.Read(r, mc.byteorder, &lcmd.nextrefsyms)
binary.Read(r, mc.byteorder, &lcmd.indirectsymoff)
binary.Read(r, mc.byteorder, &lcmd.nindirectsyms)
binary.Read(r, mc.byteorder, &lcmd.extreloff)
binary.Read(r, mc.byteorder, &lcmd.nextrel)
binary.Read(r, mc.byteorder, &lcmd.localrefoff)
binary.Read(r, mc.byteorder, &lcmd.nlocref)
binary.Read(r, mc.byteorder, &lcmd.iundefsym)
binary.Read(r, mc.byteorder, &lcmd.nundefsym)
binary.Read(r, mc.byteorder, &lcmd.tocoff)
binary.Read(r, mc.byteorder, &lcmd.ntoc)
binary.Read(r, mc.byteorder, &lcmd.modtaboff)
binary.Read(r, mc.byteorder, &lcmd.nmodtab)
binary.Read(r, mc.byteorder, &lcmd.extrefsymoff)
binary.Read(r, mc.byteorder, &lcmd.nextrefsyms)
binary.Read(r, mc.byteorder, &lcmd.indirectsymoff)
binary.Read(r, mc.byteorder, &lcmd.nindirectsyms)
binary.Read(r, mc.byteorder, &lcmd.extreloff)
binary.Read(r, mc.byteorder, &lcmd.nextrel)
binary.Read(r, mc.byteorder, &lcmd.localrefoff)
binary.Read(r, mc.byteorder, &lcmd.nlocref)
}

View File

@ -29,11 +29,11 @@ type MachoContext struct {
linkedits []*LinkEdit
segments []Segment
symtab *Symtab
dysymtab *DySymtab
dysymtab *DySymtab
dyldinfo *DyldInfo
fixups *LinkEdit
exports *LinkEdit
dyldinfo *DyldInfo
fixups *LinkEdit
exports *LinkEdit
}
func (mc *MachoContext) FileSize() uint32 {
@ -235,12 +235,12 @@ func (mc *MachoContext) Parse(r *bufio.Reader) error {
lcmd.Deserialize(mc, command_buf)
mc.commands = append(mc.commands, lcmd)
mc.linkedits = append(mc.linkedits, lcmd)
if lcmd.Cmd() == LC_DYLD_CHAINED_FIXUPS {
mc.fixups = lcmd
}
if lcmd.Cmd() == LC_DYLD_EXPORTS_TRIE {
mc.exports = lcmd
}
if lcmd.Cmd() == LC_DYLD_CHAINED_FIXUPS {
mc.fixups = lcmd
}
if lcmd.Cmd() == LC_DYLD_EXPORTS_TRIE {
mc.exports = lcmd
}
break
case LC_SYMTAB:
@ -248,12 +248,14 @@ func (mc *MachoContext) Parse(r *bufio.Reader) error {
lcmd.Deserialize(mc, command_buf)
mc.commands = append(mc.commands, lcmd)
mc.symtab = lcmd
break
case LC_DYSYMTAB:
lcmd := new(DySymtab)
lcmd.Deserialize(mc, command_buf)
mc.commands = append(mc.commands, lcmd)
mc.dysymtab = lcmd
break
default:
lcmd := new(LoadCmd)

View File

@ -82,7 +82,7 @@ func (mc *MachoContext) CollectSymbols() []*Symbol {
binary.Read(symtab_buffer, mc.byteorder, &value64)
} else {
// always use value64
var value32 uint32
var value32 uint32
binary.Read(symtab_buffer, mc.byteorder, &value32)
value64 = uint64(value32)
}