format go code
This commit is contained in:
parent
b8d8343835
commit
2eede8f9b2
@ -18,4 +18,3 @@ func (action *removeExports) withFat(ff *FatFile) error {
|
|||||||
func NewRemoveExportsAction() *removeExports {
|
func NewRemoveExportsAction() *removeExports {
|
||||||
return &removeExports{}
|
return &removeExports{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,4 +20,3 @@ func (action *removeImports) withFat(ff *FatFile) error {
|
|||||||
func NewRemoveImportsAction() *removeImports {
|
func NewRemoveImportsAction() *removeImports {
|
||||||
return &removeImports{}
|
return &removeImports{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package action
|
package action
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
// log "github.com/sirupsen/logrus"
|
// log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
. "ios-wrapper/internal/wrapper/ofile"
|
. "ios-wrapper/internal/wrapper/ofile"
|
||||||
@ -11,52 +11,52 @@ import (
|
|||||||
type saveImports struct{}
|
type saveImports struct{}
|
||||||
|
|
||||||
func (action *saveImports) withMacho(mf *MachoFile) error {
|
func (action *saveImports) withMacho(mf *MachoFile) error {
|
||||||
calculateHash := func(name string) uint32 {
|
calculateHash := func(name string) uint32 {
|
||||||
var h uint32 = 0x811c9dc5
|
var h uint32 = 0x811c9dc5
|
||||||
for _, s := range name {
|
for _, s := range name {
|
||||||
h ^= uint32(s)
|
h ^= uint32(s)
|
||||||
h *= 0x01000193
|
h *= 0x01000193
|
||||||
}
|
}
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
mc := mf.Context()
|
mc := mf.Context()
|
||||||
symbols := []*protomodel.MachoInfo_BindSymbol{}
|
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("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("const char* lib_to_resolve = \"main\";")
|
||||||
fmt.Println("struct imported_symbol imported_table[] = {")
|
fmt.Println("struct imported_symbol imported_table[] = {")
|
||||||
for _, symbol := range mc.CollectBindSymbols() {
|
for _, symbol := range mc.CollectBindSymbols() {
|
||||||
if symbol.Type() != "lazy" {
|
if symbol.Type() != "lazy" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dylib_hash := calculateHash(symbol.Dylib())
|
dylib_hash := calculateHash(symbol.Dylib())
|
||||||
seg := mc.Segments()[symbol.Segment()]
|
seg := mc.Segments()[symbol.Segment()]
|
||||||
|
|
||||||
var offset uint64
|
var offset uint64
|
||||||
|
|
||||||
if symbol.Address() >= seg.Vmaddr() {
|
if symbol.Address() >= seg.Vmaddr() {
|
||||||
// this is virtual address
|
// this is virtual address
|
||||||
offset = symbol.Address() - seg.Vmaddr()
|
offset = symbol.Address() - seg.Vmaddr()
|
||||||
} else {
|
} else {
|
||||||
// this is file address
|
// this is file address
|
||||||
offset = symbol.Address() - seg.Fileoff()
|
offset = symbol.Address() - seg.Fileoff()
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
|
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
|
||||||
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.Segment(), offset);
|
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.Segment(), offset)
|
||||||
|
|
||||||
symbols = append(symbols,
|
symbols = append(symbols,
|
||||||
&protomodel.MachoInfo_BindSymbol{
|
&protomodel.MachoInfo_BindSymbol{
|
||||||
Name: symbol.Name(),
|
Name: symbol.Name(),
|
||||||
Libname: symbol.Dylib(),
|
Libname: symbol.Dylib(),
|
||||||
Libhash: dylib_hash,
|
Libhash: dylib_hash,
|
||||||
Segment: symbol.Segment(),
|
Segment: symbol.Segment(),
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
fmt.Println("};")
|
fmt.Println("};")
|
||||||
fmt.Printf("uint32_t nimports = %d;\n", len(symbols));
|
fmt.Printf("uint32_t nimports = %d;\n", len(symbols))
|
||||||
mf.Info().Symbols = symbols
|
mf.Info().Symbols = symbols
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -68,4 +68,3 @@ func (action *saveImports) withFat(ff *FatFile) error {
|
|||||||
func NewSaveImportsAction() *saveImports {
|
func NewSaveImportsAction() *saveImports {
|
||||||
return &saveImports{}
|
return &saveImports{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
"github.com/alecthomas/kong"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -65,10 +65,10 @@ func Cli() {
|
|||||||
fat.FatJoin(arg.Macho, arg.Out)
|
fat.FatJoin(arg.Macho, arg.Out)
|
||||||
return
|
return
|
||||||
} else if command == "bcell2header" {
|
} else if command == "bcell2header" {
|
||||||
arg := cli.BcellToHeader
|
arg := cli.BcellToHeader
|
||||||
bcell2header(arg.Bcell, arg.Out)
|
bcell2header(arg.Bcell, arg.Out)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var pc ProgramContext
|
var pc ProgramContext
|
||||||
var ofile OFile = nil
|
var ofile OFile = nil
|
||||||
@ -106,23 +106,23 @@ func Cli() {
|
|||||||
pc.outfile = arg.Out
|
pc.outfile = arg.Out
|
||||||
pc.bcellfile = arg.Bcell
|
pc.bcellfile = arg.Bcell
|
||||||
|
|
||||||
case "pepe":
|
case "pepe":
|
||||||
arg := cli.Pepe
|
arg := cli.Pepe
|
||||||
ofile = NewOFile(arg.OFile)
|
ofile = NewOFile(arg.OFile)
|
||||||
if arg.FullRemoval {
|
if arg.FullRemoval {
|
||||||
pc.remove_exports = true
|
pc.remove_exports = true
|
||||||
pc.remove_symbol_table = true
|
pc.remove_symbol_table = true
|
||||||
pc.remove_imports = true
|
pc.remove_imports = true
|
||||||
pc.remove_inits = true
|
pc.remove_inits = true
|
||||||
pc.remove_codesign = true
|
pc.remove_codesign = true
|
||||||
pc.remove_others = true
|
pc.remove_others = true
|
||||||
}
|
}
|
||||||
pc.remove_imports = arg.RemoveBindSymbols
|
pc.remove_imports = arg.RemoveBindSymbols
|
||||||
pc.remove_codesign = arg.RemoveCodeSign
|
pc.remove_codesign = arg.RemoveCodeSign
|
||||||
pc.remove_inits = arg.RemoveInitFunctions
|
pc.remove_inits = arg.RemoveInitFunctions
|
||||||
pc.remove_others = arg.RemoveOthers
|
pc.remove_others = arg.RemoveOthers
|
||||||
pc.remove_exports = arg.RemoveExports
|
pc.remove_exports = arg.RemoveExports
|
||||||
pc.remove_symbol_table = arg.RemoveSymbolTable
|
pc.remove_symbol_table = arg.RemoveSymbolTable
|
||||||
pc.dylib_to_add = arg.Dylibs
|
pc.dylib_to_add = arg.Dylibs
|
||||||
pc.rpath_to_add = arg.Rpath
|
pc.rpath_to_add = arg.Rpath
|
||||||
pc.outfile = arg.Out
|
pc.outfile = arg.Out
|
||||||
@ -195,7 +195,7 @@ func displayBcell(bfile string) {
|
|||||||
}
|
}
|
||||||
fmt.Printf(" | Bind Symbols:\n")
|
fmt.Printf(" | Bind Symbols:\n")
|
||||||
for _, symbol := range info.Symbols {
|
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(" | %s offset=0x%x segmentID=0x%x\n", symbol.Name, symbol.Offset, symbol.Segment)
|
||||||
fmt.Printf(" | from=%s\n", lib)
|
fmt.Printf(" | from=%s\n", lib)
|
||||||
}
|
}
|
||||||
@ -255,7 +255,7 @@ func bcell2header(bfile string, header string) {
|
|||||||
}
|
}
|
||||||
fmt.Printf(" | Bind Symbols:\n")
|
fmt.Printf(" | Bind Symbols:\n")
|
||||||
for _, symbol := range info.Symbols {
|
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(" | %s offset=0x%x segmentID=0x%x\n", symbol.Name, symbol.Offset, symbol.Segment)
|
||||||
fmt.Printf(" | from=%s\n", lib)
|
fmt.Printf(" | from=%s\n", lib)
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ type RemoveCodesignArgument struct {
|
|||||||
|
|
||||||
type RemoveImportsArgument struct {
|
type RemoveImportsArgument struct {
|
||||||
Out string `short:"o" required name:"outfile" help:"Modified Mach-O/Fat binary output file" type:"path"`
|
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"`
|
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,26 +56,26 @@ type LipoArgument struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PepeArgument struct {
|
type PepeArgument struct {
|
||||||
Out string `short:"o" required name:"outfile" help:"Output file after transformation" type:"path"`
|
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"`
|
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"`
|
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
|
||||||
Dylibs []string `short:"l" help:"Add more LC_DYLIB"`
|
Dylibs []string `short:"l" help:"Add more LC_DYLIB"`
|
||||||
Rpath []string `short:"r" help:"Add more LC_RPATH"`
|
Rpath []string `short:"r" help:"Add more LC_RPATH"`
|
||||||
RemoveCodeSign bool `default:"false" negatable:"" help:"Remove LC_CODE_SIGNATURE"`
|
RemoveCodeSign bool `default:"false" negatable:"" help:"Remove LC_CODE_SIGNATURE"`
|
||||||
RemoveExports bool `default:"false" negatable:"" help:"Clear the export table/trie"`
|
RemoveExports bool `default:"false" negatable:"" help:"Clear the export table/trie"`
|
||||||
RemoveSymbolTable bool `default:"true" negatable:"" help:"Remove LC_SYMTAB and LC_DYSYMTAB"`
|
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, ..."`
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
RebuildLinkEdit bool `default:"false" negatable:"" help:"(TODO) Rebuild the LINKEDIT section"`
|
||||||
FullRemoval bool `default:"false" help:"Apply every removal possible"`
|
FullRemoval bool `default:"false" help:"Apply every removal possible"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BcellToHeaderArgument struct {
|
type BcellToHeaderArgument struct {
|
||||||
Out string `short:"o" required name:"outfile" help:"Header file name to output to" type:"path"`
|
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"`
|
Bcell string `short:"b" required help:"Input bcell.dat file" type:"existingfile"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Argument struct {
|
type Argument struct {
|
||||||
@ -89,13 +89,13 @@ type Argument struct {
|
|||||||
Addr2Line Addr2LineArgument `cmd name:"addr2line" help:"Resolve crash address from DWARF file"`
|
Addr2Line Addr2LineArgument `cmd name:"addr2line" help:"Resolve crash address from DWARF file"`
|
||||||
Lipo LipoArgument `cmd help:"split Fat binary or join Mach-O binares"`
|
Lipo LipoArgument `cmd help:"split Fat binary or join Mach-O binares"`
|
||||||
Pepe PepeArgument `cmd help:"custom command"`
|
Pepe PepeArgument `cmd help:"custom command"`
|
||||||
BcellToHeader BcellToHeaderArgument `cmd name:"bcell2header" help:"Build C header file from bcell file"`
|
BcellToHeader BcellToHeaderArgument `cmd name:"bcell2header" help:"Build C header file from bcell file"`
|
||||||
AddSection struct {
|
AddSection struct {
|
||||||
Out string `short:"o" required name:"outfile" help:"Output file after transformation"`
|
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"`
|
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"`
|
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
|
||||||
Segment string `required help:"Segment name"`
|
Segment string `required help:"Segment name"`
|
||||||
Section string `required help:"Section name"`
|
Section string `required help:"Section name"`
|
||||||
Size int `required help:"Size of segment/section"`
|
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"`
|
} `cmd:"" default:"false" help:"(TODO) Add a new segment with 1 section, segment starts at the end of last segment"`
|
||||||
}
|
}
|
||||||
|
@ -35,16 +35,16 @@ func (printer *InfoPrinter) Print() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
symbols := mc.CollectBindSymbols()
|
symbols := mc.CollectBindSymbols()
|
||||||
for _, sym := range symbols {
|
for _, sym := range symbols {
|
||||||
fmt.Printf(
|
fmt.Printf(
|
||||||
"%s (%s)\n\tStub=0x%x Address=0x%x\n\tDylib=%s\n",
|
"%s (%s)\n\tStub=0x%x Address=0x%x\n\tDylib=%s\n",
|
||||||
sym.Name(),
|
sym.Name(),
|
||||||
sym.Type(),
|
sym.Type(),
|
||||||
sym.Stub(),
|
sym.Stub(),
|
||||||
sym.Address(),
|
sym.Address(),
|
||||||
sym.Dylib(),
|
sym.Dylib(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("======")
|
fmt.Println("======")
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,12 @@ func (uc *UserConfig) Protomodel() *protomodel.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProgramContext struct {
|
type ProgramContext struct {
|
||||||
remove_inits bool
|
remove_inits bool
|
||||||
remove_codesign bool
|
remove_codesign bool
|
||||||
remove_imports bool
|
remove_imports bool
|
||||||
remove_others bool
|
remove_others bool
|
||||||
remove_exports bool
|
remove_exports bool
|
||||||
remove_symbol_table bool
|
remove_symbol_table bool
|
||||||
dylib_to_add []string
|
dylib_to_add []string
|
||||||
rpath_to_add []string
|
rpath_to_add []string
|
||||||
|
|
||||||
@ -96,18 +96,18 @@ func (pc *ProgramContext) Process(ofile OFile) {
|
|||||||
}
|
}
|
||||||
if pc.remove_imports {
|
if pc.remove_imports {
|
||||||
pc.AddAction(NewSaveImportsAction())
|
pc.AddAction(NewSaveImportsAction())
|
||||||
pc.AddAction(NewRemoveImportsAction())
|
pc.AddAction(NewRemoveImportsAction())
|
||||||
}
|
}
|
||||||
if pc.remove_symbol_table {
|
if pc.remove_symbol_table {
|
||||||
pc.AddAction(NewRemoveClassicSymbolAction())
|
pc.AddAction(NewRemoveClassicSymbolAction())
|
||||||
}
|
}
|
||||||
if pc.remove_exports {
|
if pc.remove_exports {
|
||||||
pc.AddAction(NewRemoveExportsAction())
|
pc.AddAction(NewRemoveExportsAction())
|
||||||
}
|
}
|
||||||
ExperimentalFeature("Remove Unnecessary Info", func() {
|
ExperimentalFeature("Remove Unnecessary Info", func() {
|
||||||
if pc.remove_others {
|
if pc.remove_others {
|
||||||
pc.AddAction(NewRemoveUnnecessaryInfoAction())
|
pc.AddAction(NewRemoveUnnecessaryInfoAction())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
pc.AddAction(NewAddRpathAction(pc.rpath_to_add))
|
pc.AddAction(NewAddRpathAction(pc.rpath_to_add))
|
||||||
pc.AddAction(NewAddDylibAction(pc.dylib_to_add))
|
pc.AddAction(NewAddDylibAction(pc.dylib_to_add))
|
||||||
|
@ -4,9 +4,9 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
// "bufio"
|
// "bufio"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ import "C"
|
|||||||
|
|
||||||
type ImportSymbol struct {
|
type ImportSymbol struct {
|
||||||
name string
|
name string
|
||||||
typ string
|
typ string
|
||||||
dylib string
|
dylib string
|
||||||
segment uint32
|
segment uint32
|
||||||
segment_offset uint32
|
segment_offset uint32
|
||||||
@ -30,7 +30,7 @@ type ImportSymbol struct {
|
|||||||
pnum uint32
|
pnum uint32
|
||||||
stub uint64
|
stub uint64
|
||||||
|
|
||||||
next int // only for LC_DYLD_CHAINED_FIXUPS
|
next int // only for LC_DYLD_CHAINED_FIXUPS
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sym *ImportSymbol) Name() string {
|
func (sym *ImportSymbol) Name() string {
|
||||||
@ -70,140 +70,140 @@ func (mc *MachoContext) CollectBindSymbols() []*ImportSymbol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) findSegmentIndexAt(address uint64) int {
|
func (mc *MachoContext) findSegmentIndexAt(address uint64) int {
|
||||||
for i, segment := range mc.Segments() {
|
for i, segment := range mc.Segments() {
|
||||||
if segment.Fileoff() <= address && segment.Fileoff() + segment.Filesize() > address {
|
if segment.Fileoff() <= address && segment.Fileoff()+segment.Filesize() > address {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// New convention using LC_DYLD_CHAINED_FIXUPS
|
// New convention using LC_DYLD_CHAINED_FIXUPS
|
||||||
func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
||||||
start := mc.fixups.dataoff
|
start := mc.fixups.dataoff
|
||||||
size := mc.fixups.datasize
|
size := mc.fixups.datasize
|
||||||
buf := mc.buf[start:start+size]
|
buf := mc.buf[start : start+size]
|
||||||
|
|
||||||
// all pointers used are based from this **buf**
|
// all pointers used are based from this **buf**
|
||||||
// until buf is freed, all pointers are valid
|
// until buf is freed, all pointers are valid
|
||||||
// remember to copy before moving out
|
// remember to copy before moving out
|
||||||
header := (*C.uchar)(unsafe.Pointer(&buf[0]))
|
header := (*C.uchar)(unsafe.Pointer(&buf[0]))
|
||||||
imports_table := C.GetImportsTable(header);
|
imports_table := C.GetImportsTable(header)
|
||||||
|
|
||||||
// for i := 0; i < int(imports_table.size); i++ {
|
// for i := 0; i < int(imports_table.size); i++ {
|
||||||
// s := C.GetImportsAt(&imports_table, C.int(i))
|
// s := C.GetImportsAt(&imports_table, C.int(i))
|
||||||
// name := C.GoString(s.name)
|
// name := C.GoString(s.name)
|
||||||
// symbol.dylib := string(mc.dylibs[int(s.lib_ordinal)-1].name[:])
|
// symbol.dylib := string(mc.dylibs[int(s.lib_ordinal)-1].name[:])
|
||||||
// symbol_table = append(symbol_table, symbol)
|
// symbol_table = append(symbol_table, symbol)
|
||||||
// fmt.Printf("id=%d lib=%s name=%s\n", i, dylib, name)
|
// fmt.Printf("id=%d lib=%s name=%s\n", i, dylib, name)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
var syms []*ImportSymbol
|
var syms []*ImportSymbol
|
||||||
var sym ImportSymbol
|
var sym ImportSymbol
|
||||||
|
|
||||||
segment_i := 0
|
segment_i := 0
|
||||||
for {
|
for {
|
||||||
var fix C.struct_SegmentFix
|
var fix C.struct_SegmentFix
|
||||||
fix_ptr := (*C.struct_SegmentFix)(unsafe.Pointer(&fix))
|
fix_ptr := (*C.struct_SegmentFix)(unsafe.Pointer(&fix))
|
||||||
status := int(C.GetSegmentFixAt(header, C.uint(segment_i), fix_ptr))
|
status := int(C.GetSegmentFixAt(header, C.uint(segment_i), fix_ptr))
|
||||||
segment_i += 1
|
segment_i += 1
|
||||||
if status == 2 {
|
if status == 2 {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if status == 3 {
|
if status == 3 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// fmt.Printf("segment=%x format=%x page_count=%d\n", fix.segment, fix.format, fix.page_count)
|
// fmt.Printf("segment=%x format=%x page_count=%d\n", fix.segment, fix.format, fix.page_count)
|
||||||
// fmt.Printf("pages=%x\n", fix.pages)
|
// fmt.Printf("pages=%x\n", fix.pages)
|
||||||
pages := ([]C.ushort)(unsafe.Slice(fix.pages, fix.page_count))
|
pages := ([]C.ushort)(unsafe.Slice(fix.pages, fix.page_count))
|
||||||
for page_i := 0; page_i < int(fix.page_count); page_i++ {
|
for page_i := 0; page_i < int(fix.page_count); page_i++ {
|
||||||
// fmt.Printf(" page offset=%x\n", pages[page_i])
|
// fmt.Printf(" page offset=%x\n", pages[page_i])
|
||||||
|
|
||||||
address := int64(fix.segment) + int64(pages[page_i])
|
address := int64(fix.segment) + int64(pages[page_i])
|
||||||
mc.file.Seek(address, io.SeekStart)
|
mc.file.Seek(address, io.SeekStart)
|
||||||
|
|
||||||
code := make([]byte, 8)
|
code := make([]byte, 8)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
mc.file.Read(code)
|
mc.file.Read(code)
|
||||||
v := mc.byteorder.Uint64(code)
|
v := mc.byteorder.Uint64(code)
|
||||||
|
|
||||||
var bind C.int
|
var bind C.int
|
||||||
var ret1 C.ulonglong
|
var ret1 C.ulonglong
|
||||||
var ret2 C.ulonglong
|
var ret2 C.ulonglong
|
||||||
next := C.ParseFixValue(C.int(fix.format), C.ulonglong(v),
|
next := C.ParseFixValue(C.int(fix.format), C.ulonglong(v),
|
||||||
&bind, &ret1, &ret2)
|
&bind, &ret1, &ret2)
|
||||||
|
|
||||||
if bind == 1 {
|
if bind == 1 {
|
||||||
s := C.GetImportsAt(&imports_table, C.int(ret1))
|
s := C.GetImportsAt(&imports_table, C.int(ret1))
|
||||||
name := C.GoString(s.name)
|
name := C.GoString(s.name)
|
||||||
dylib := string(mc.dylibs[int(s.lib_ordinal)-1].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.address = uint64(address)
|
||||||
sym.name = name
|
sym.name = name
|
||||||
sym.dylib = dylib
|
sym.dylib = dylib
|
||||||
sym.typ = "lazy"
|
sym.typ = "lazy"
|
||||||
|
|
||||||
sym.segment = uint32(mc.findSegmentIndexAt(uint64(address)))
|
sym.segment = uint32(mc.findSegmentIndexAt(uint64(address)))
|
||||||
sym.file_address = uint64(address)
|
sym.file_address = uint64(address)
|
||||||
sym.next = int(next)
|
sym.next = int(next)
|
||||||
new_sym := sym
|
new_sym := sym
|
||||||
syms = append(syms, &new_sym)
|
syms = append(syms, &new_sym)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("// 0x%x rebase=%d target=0x%x high8=0x%x\n", address, bind, ret1, ret2)
|
fmt.Printf("// 0x%x rebase=%d target=0x%x high8=0x%x\n", address, bind, ret1, ret2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if int(next) == 0 {
|
if int(next) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// because the pointer move up 8 bytes already so we minus 8
|
// because the pointer move up 8 bytes already so we minus 8
|
||||||
address += int64(next * 4)
|
address += int64(next * 4)
|
||||||
mc.file.Seek(int64(next * 4) - 8, io.SeekCurrent)
|
mc.file.Seek(int64(next*4)-8, io.SeekCurrent)
|
||||||
}
|
}
|
||||||
mc.file.Seek(0, io.SeekStart)
|
mc.file.Seek(0, io.SeekStart)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return syms
|
return syms
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old convention using LC_DYLD_INFO_ONLY section and bytecode runner
|
// Old convention using LC_DYLD_INFO_ONLY section and bytecode runner
|
||||||
func (mc *MachoContext) CollectBindSymbolsLegacy() []*ImportSymbol {
|
func (mc *MachoContext) CollectBindSymbolsLegacy() []*ImportSymbol {
|
||||||
noLazy := (func() []*ImportSymbol {
|
noLazy := (func() []*ImportSymbol {
|
||||||
start := mc.dyldinfo.bind_off
|
start := mc.dyldinfo.bind_off
|
||||||
size := mc.dyldinfo.bind_size
|
size := mc.dyldinfo.bind_size
|
||||||
end := start + size
|
end := start + size
|
||||||
buf := bytes.NewBuffer(mc.buf[start:end])
|
buf := bytes.NewBuffer(mc.buf[start:end])
|
||||||
return mc.readBindStream(buf, "no lazy")
|
return mc.readBindStream(buf, "no lazy")
|
||||||
})()
|
})()
|
||||||
|
|
||||||
lazy := (func() []*ImportSymbol {
|
lazy := (func() []*ImportSymbol {
|
||||||
start := mc.dyldinfo.lazy_bind_off
|
start := mc.dyldinfo.lazy_bind_off
|
||||||
size := mc.dyldinfo.lazy_bind_size
|
size := mc.dyldinfo.lazy_bind_size
|
||||||
end := start + size
|
end := start + size
|
||||||
buf := bytes.NewBuffer(mc.buf[start:end])
|
buf := bytes.NewBuffer(mc.buf[start:end])
|
||||||
return mc.readBindStream(buf, "lazy")
|
return mc.readBindStream(buf, "lazy")
|
||||||
})()
|
})()
|
||||||
|
|
||||||
weak := (func() []*ImportSymbol {
|
weak := (func() []*ImportSymbol {
|
||||||
start := mc.dyldinfo.weak_bind_off
|
start := mc.dyldinfo.weak_bind_off
|
||||||
size := mc.dyldinfo.weak_bind_size
|
size := mc.dyldinfo.weak_bind_size
|
||||||
end := start + size
|
end := start + size
|
||||||
buf := bytes.NewBuffer(mc.buf[start:end])
|
buf := bytes.NewBuffer(mc.buf[start:end])
|
||||||
return mc.readBindStream(buf, "weak")
|
return mc.readBindStream(buf, "weak")
|
||||||
})()
|
})()
|
||||||
|
|
||||||
var symbols []*ImportSymbol
|
var symbols []*ImportSymbol
|
||||||
symbols = append(symbols, noLazy...)
|
symbols = append(symbols, noLazy...)
|
||||||
symbols = append(symbols, lazy...)
|
symbols = append(symbols, lazy...)
|
||||||
symbols = append(symbols, weak...)
|
symbols = append(symbols, weak...)
|
||||||
|
|
||||||
return symbols
|
return symbols
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportSymbol {
|
func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportSymbol {
|
||||||
size := buf.Len()
|
size := buf.Len()
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return []*ImportSymbol{}
|
return []*ImportSymbol{}
|
||||||
}
|
}
|
||||||
@ -237,7 +237,7 @@ func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportS
|
|||||||
case BIND_OPCODE_DO_BIND:
|
case BIND_OPCODE_DO_BIND:
|
||||||
if sym.name != "" {
|
if sym.name != "" {
|
||||||
new_sym := sym
|
new_sym := sym
|
||||||
new_sym.typ = typ
|
new_sym.typ = typ
|
||||||
syms = append(syms, &new_sym)
|
syms = append(syms, &new_sym)
|
||||||
// fmt.Printf("Offset 0x%x: Symbol %+v\n", symoffset, 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,
|
"symbol": sym.name,
|
||||||
}).Trace("Bind")
|
}).Trace("Bind")
|
||||||
sym.name = ""
|
sym.name = ""
|
||||||
sym.address += 8
|
sym.address += 8
|
||||||
}
|
}
|
||||||
offset += 1
|
offset += 1
|
||||||
break
|
break
|
||||||
@ -275,9 +275,9 @@ func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportS
|
|||||||
|
|
||||||
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
||||||
sym.name, _ = buf.ReadString(0)
|
sym.name, _ = buf.ReadString(0)
|
||||||
// ReadString input the 0x00 byte to buffer
|
// ReadString input the 0x00 byte to buffer
|
||||||
// while we are string so we can remove that
|
// while we are string so we can remove that
|
||||||
sym.name = sym.name[:len(sym.name)-1]
|
sym.name = sym.name[:len(sym.name)-1]
|
||||||
offset += uint(len(sym.name))
|
offset += uint(len(sym.name))
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -301,12 +301,12 @@ func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportS
|
|||||||
offset += br
|
offset += br
|
||||||
break
|
break
|
||||||
|
|
||||||
case BIND_OPCODE_SET_TYPE_IMM:
|
case BIND_OPCODE_SET_TYPE_IMM:
|
||||||
fmt.Println("// symbol type", imm)
|
fmt.Println("// symbol type", imm)
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Println("BIND OPCODE NOT SUPPORTED", op, imm)
|
fmt.Println("BIND OPCODE NOT SUPPORTED", op, imm)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package macho
|
package macho
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
"bytes"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@ -272,93 +272,93 @@ func (mc *MachoContext) UpdateHeaderRemoveLcmd(size uint32) {
|
|||||||
|
|
||||||
func (mc *MachoContext) RemoveBindSymbols() {
|
func (mc *MachoContext) RemoveBindSymbols() {
|
||||||
if !mc.WriteEnabled() {
|
if !mc.WriteEnabled() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
if mc.dyldinfo == nil {
|
if mc.dyldinfo == nil {
|
||||||
mc.removeBindSymbolsModern()
|
mc.removeBindSymbolsModern()
|
||||||
} else {
|
} else {
|
||||||
mc.removeBindSymbolsLegacy()
|
mc.removeBindSymbolsLegacy()
|
||||||
}
|
}
|
||||||
mc.ReworkForObjc()
|
mc.ReworkForObjc()
|
||||||
|
|
||||||
// due to some limitations when design this tool
|
// due to some limitations when design this tool
|
||||||
// we write the c code to stdout lol
|
// we write the c code to stdout lol
|
||||||
for _, symbol := range mc.CollectBindSymbols() {
|
for _, symbol := range mc.CollectBindSymbols() {
|
||||||
if symbol.Type() != "lazy" {
|
if symbol.Type() != "lazy" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if mc.dyldinfo != nil {
|
if mc.dyldinfo != nil {
|
||||||
// for legacy resolve the opcodes can be rewritten as 0x00
|
// for legacy resolve the opcodes can be rewritten as 0x00
|
||||||
mc.file.WriteAt(make([]byte, 8), int64(symbol.file_address))
|
mc.file.WriteAt(make([]byte, 8), int64(symbol.file_address))
|
||||||
} else {
|
} else {
|
||||||
// for modern resolve the opcodes must not be rewritten as 0x00
|
// for modern resolve the opcodes must not be rewritten as 0x00
|
||||||
// because it contains 2 types of opcodes, BIND and REBASE
|
// because it contains 2 types of opcodes, BIND and REBASE
|
||||||
// we only fix BIND and leave REBASE intact
|
// we only fix BIND and leave REBASE intact
|
||||||
// However, each opcodes has a *next* field to the next opcode
|
// However, each opcodes has a *next* field to the next opcode
|
||||||
// So if we want to leave the header intact (contains pointers, size)
|
// So if we want to leave the header intact (contains pointers, size)
|
||||||
// We should rewrite this as REBASE opcode (so no symbol lookup happens)
|
// We should rewrite this as REBASE opcode (so no symbol lookup happens)
|
||||||
// and it can continue
|
// and it can continue
|
||||||
|
|
||||||
// we can write random values, because the loader just do
|
// we can write random values, because the loader just do
|
||||||
// (high8 << 56 | target) - mach_header
|
// (high8 << 56 | target) - mach_header
|
||||||
// or something, so no symbol lookup and no error at runtime
|
// or something, so no symbol lookup and no error at runtime
|
||||||
target := rand.Int()
|
target := rand.Int()
|
||||||
high8 := rand.Int()
|
high8 := rand.Int()
|
||||||
value := C.MakeRebaseFixupOpcode(C.int(symbol.next), C.ulonglong(target), C.ulonglong(high8))
|
value := C.MakeRebaseFixupOpcode(C.int(symbol.next), C.ulonglong(target), C.ulonglong(high8))
|
||||||
v := make([]byte, 8)
|
v := make([]byte, 8)
|
||||||
mc.byteorder.PutUint64(v, uint64(value))
|
mc.byteorder.PutUint64(v, uint64(value))
|
||||||
mc.file.WriteAt(v, int64(symbol.file_address))
|
mc.file.WriteAt(v, int64(symbol.file_address))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) removeBindSymbolsModern() {
|
func (mc *MachoContext) removeBindSymbolsModern() {
|
||||||
// we don't mess up the chain
|
// we don't mess up the chain
|
||||||
// we clear the imports table, and the raw opcodes
|
// we clear the imports table, and the raw opcodes
|
||||||
// clearing imports table disables static analysis
|
// clearing imports table disables static analysis
|
||||||
// clearing opcodes forces runtime manual mapping
|
// clearing opcodes forces runtime manual mapping
|
||||||
|
|
||||||
// imports item are defined by mc.fixups.imports_format
|
// imports item are defined by mc.fixups.imports_format
|
||||||
// basic case is dyld_chained_import, 4 bytes
|
// basic case is dyld_chained_import, 4 bytes
|
||||||
|
|
||||||
start := mc.fixups.dataoff
|
start := mc.fixups.dataoff
|
||||||
size := mc.fixups.datasize
|
size := mc.fixups.datasize
|
||||||
fixups := new(Fixups)
|
fixups := new(Fixups)
|
||||||
fixups.Deserialize(mc, mc.buf[start:start+size])
|
fixups.Deserialize(mc, mc.buf[start:start+size])
|
||||||
|
|
||||||
start = mc.fixups.dataoff + fixups.imports_offset
|
start = mc.fixups.dataoff + fixups.imports_offset
|
||||||
size = fixups.imports_count * 4
|
size = fixups.imports_count * 4
|
||||||
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
|
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
|
||||||
mc.file.WriteAt(make([]byte, size), int64(start))
|
mc.file.WriteAt(make([]byte, size), int64(start))
|
||||||
|
|
||||||
// string reference are at the end of this section
|
// string reference are at the end of this section
|
||||||
start = mc.fixups.dataoff + fixups.symbols_offset
|
start = mc.fixups.dataoff + fixups.symbols_offset
|
||||||
size = mc.fixups.Datasize() - fixups.symbols_offset
|
size = mc.fixups.Datasize() - fixups.symbols_offset
|
||||||
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
|
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
|
||||||
mc.file.WriteAt(make([]byte, size), int64(start))
|
mc.file.WriteAt(make([]byte, size), int64(start))
|
||||||
|
|
||||||
fixups.imports_count = 0
|
fixups.imports_count = 0
|
||||||
mc.file.WriteAt(fixups.Serialize(mc), int64(mc.fixups.dataoff))
|
mc.file.WriteAt(fixups.Serialize(mc), int64(mc.fixups.dataoff))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) removeBindSymbolsLegacy() {
|
func (mc *MachoContext) removeBindSymbolsLegacy() {
|
||||||
start := mc.dyldinfo.lazy_bind_off
|
start := mc.dyldinfo.lazy_bind_off
|
||||||
size := mc.dyldinfo.lazy_bind_size
|
size := mc.dyldinfo.lazy_bind_size
|
||||||
// set lazy opcodes to 0x00 == DO_BIND
|
// set lazy opcodes to 0x00 == DO_BIND
|
||||||
// but no symbol state to bind
|
// but no symbol state to bind
|
||||||
mc.file.WriteAt(make([]byte, size), int64(start))
|
mc.file.WriteAt(make([]byte, size), int64(start))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) ReworkForObjc() {
|
func (mc *MachoContext) ReworkForObjc() {
|
||||||
text_start := 0
|
text_start := 0
|
||||||
data_end := 0
|
data_end := 0
|
||||||
lc_main_offset := int64(0)
|
lc_main_offset := int64(0)
|
||||||
|
|
||||||
ptr := int64(0)
|
ptr := int64(0)
|
||||||
if mc.Is64bit() {
|
if mc.Is64bit() {
|
||||||
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
|
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
|
||||||
} else {
|
} else {
|
||||||
@ -366,218 +366,217 @@ func (mc *MachoContext) ReworkForObjc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, cmd := range mc.commands {
|
for _, cmd := range mc.commands {
|
||||||
if cmd.Cmd() == LC_MAIN {
|
if cmd.Cmd() == LC_MAIN {
|
||||||
lc_main_offset = ptr + 8
|
lc_main_offset = ptr + 8
|
||||||
ptr += int64(cmd.Cmdsize())
|
ptr += int64(cmd.Cmdsize())
|
||||||
continue
|
|
||||||
}
|
|
||||||
if cmd.Cmd() != LC_SEGMENT_64 {
|
|
||||||
ptr += int64(cmd.Cmdsize())
|
|
||||||
continue
|
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 {
|
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__TEXT")) == 0 {
|
||||||
section_ptr := ptr + 0x40 + 8
|
section_ptr := ptr + 0x40 + 8
|
||||||
for _, section := range segment.Sections() {
|
for _, section := range segment.Sections() {
|
||||||
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__text")) == 0 {
|
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__text")) == 0 {
|
||||||
text_start = int(section.Offset())
|
text_start = int(section.Offset())
|
||||||
}
|
}
|
||||||
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__init_offsets")) == 0 {
|
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__init_offsets")) == 0 {
|
||||||
// mc.file.WriteAt([]byte("__init_offsetx"), section_ptr)
|
// mc.file.WriteAt([]byte("__init_offsetx"), section_ptr)
|
||||||
// edit flags to not S_MOD_INIT_FUNC
|
// edit flags to not S_MOD_INIT_FUNC
|
||||||
mc.file.WriteAt([]byte{0, 0, 0, 0}, section_ptr + 0x40)
|
mc.file.WriteAt([]byte{0, 0, 0, 0}, section_ptr+0x40)
|
||||||
}
|
}
|
||||||
section_ptr += 16 * 2 + 8 * 2 + 4 * 8
|
section_ptr += 16*2 + 8*2 + 4*8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA_CONST")) == 0 {
|
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA_CONST")) == 0 {
|
||||||
section_ptr := ptr + 0x40 + 8
|
section_ptr := ptr + 0x40 + 8
|
||||||
for _, section := range segment.Sections() {
|
for _, section := range segment.Sections() {
|
||||||
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_classlist")) == 0 {
|
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_classlist")) == 0 {
|
||||||
mc.file.WriteAt([]byte("__objc_classbruh"), section_ptr)
|
mc.file.WriteAt([]byte("__objc_classbruh"), section_ptr)
|
||||||
}
|
}
|
||||||
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_nlclslist")) == 0 {
|
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_nlclslist")) == 0 {
|
||||||
mc.file.WriteAt([]byte("__objc_nlclsbruh"), section_ptr)
|
mc.file.WriteAt([]byte("__objc_nlclsbruh"), section_ptr)
|
||||||
}
|
}
|
||||||
section_ptr += 16 * 2 + 8 * 2 + 4 * 8
|
section_ptr += 16*2 + 8*2 + 4*8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 {
|
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 {
|
||||||
// end of __DATA segment, should have enough space for a pointer
|
// end of __DATA segment, should have enough space for a pointer
|
||||||
|
|
||||||
// __bss section is dynamically allocated at the end to or something, hmmge
|
// __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
|
// assume that it order correctly, which it should if compiled and not modified
|
||||||
sections := segment.Sections()
|
sections := segment.Sections()
|
||||||
last := sections[len(sections) - 1]
|
last := sections[len(sections)-1]
|
||||||
data_end = int(last.Offset()) + int(last.Size())
|
data_end = int(last.Offset()) + int(last.Size())
|
||||||
|
|
||||||
if (last.Offset() == 0) {
|
if last.Offset() == 0 {
|
||||||
before_last := sections[len(sections) - 2]
|
before_last := sections[len(sections)-2]
|
||||||
data_end += int(before_last.Offset()) + int(before_last.Size())
|
data_end += int(before_last.Offset()) + int(before_last.Size())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptr += int64(cmd.Cmdsize())
|
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),
|
// dummy value past the end of __DATA segment (logical size),
|
||||||
// its physical size is still a page
|
// its physical size is still a page
|
||||||
// mc.file.WriteAt([]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}, int64(0x81d8))
|
// mc.file.WriteAt([]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}, int64(0x81d8))
|
||||||
|
|
||||||
// we use 2 registers, x8 x9
|
// we use 2 registers, x8 x9
|
||||||
// stack values:
|
// stack values:
|
||||||
// [ return address, header, argc, argv, env, apple ]
|
// [ return address, header, argc, argv, env, apple ]
|
||||||
// we need to store the return address, and parameters passed to main
|
// we need to store the return address, and parameters passed to main
|
||||||
// we also store our header address to not calculate many times
|
// we also store our header address to not calculate many times
|
||||||
|
|
||||||
/*
|
/*
|
||||||
adr x8, 0
|
adr x8, 0
|
||||||
sub sp, sp, #0x30
|
sub sp, sp, #0x30
|
||||||
str x30, [sp]
|
str x30, [sp]
|
||||||
movz x9, #0x3d68 ; offset at this point
|
movz x9, #0x3d68 ; offset at this point
|
||||||
sub x8, x8, x9
|
sub x8, x8, x9
|
||||||
str x8, [sp, #0x8]
|
str x8, [sp, #0x8]
|
||||||
str x0, [sp, #0x10]
|
str x0, [sp, #0x10]
|
||||||
str x1, [sp, #0x18]
|
str x1, [sp, #0x18]
|
||||||
str x2, [sp, #0x20]
|
str x2, [sp, #0x20]
|
||||||
str x3, [sp, #0x28]
|
str x3, [sp, #0x28]
|
||||||
|
|
||||||
movz x9, #0x81d8 ; offset to end of __DATA
|
movz x9, #0x81d8 ; offset to end of __DATA
|
||||||
add x9, x8, x9
|
add x9, x8, x9
|
||||||
ldr x9, [x9]
|
ldr x9, [x9]
|
||||||
blr x9
|
blr x9
|
||||||
ldr x8, [sp, #0x8]
|
ldr x8, [sp, #0x8]
|
||||||
ldr x0, [sp, #0x10]
|
ldr x0, [sp, #0x10]
|
||||||
ldr x1, [sp, #0x18]
|
ldr x1, [sp, #0x18]
|
||||||
ldr x2, [sp, #0x20]
|
ldr x2, [sp, #0x20]
|
||||||
ldr x3, [sp, #0x28]
|
ldr x3, [sp, #0x28]
|
||||||
movz x9, #0x3e3c ; offset to original main
|
movz x9, #0x3e3c ; offset to original main
|
||||||
add x9, x8, x9
|
add x9, x8, x9
|
||||||
blr x9
|
blr x9
|
||||||
ldr x30, [sp]
|
ldr x30, [sp]
|
||||||
add sp, sp, #0x10
|
add sp, sp, #0x10
|
||||||
ret
|
ret
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: fix to work with offset larger than 0xffff
|
// TODO: fix to work with offset larger than 0xffff
|
||||||
shellcode := []uint32{
|
shellcode := []uint32{
|
||||||
0x10000008,
|
0x10000008,
|
||||||
0xD100C3FF,
|
0xD100C3FF,
|
||||||
0xF90003FE,
|
0xF90003FE,
|
||||||
0, // movz_shellcode_offset,
|
0, // movz_shellcode_offset,
|
||||||
0xCB090108,
|
0xCB090108,
|
||||||
0xF90007E8,
|
0xF90007E8,
|
||||||
0xF9000BE0,
|
0xF9000BE0,
|
||||||
0xF9000FE1,
|
0xF9000FE1,
|
||||||
0xF90013E2,
|
0xF90013E2,
|
||||||
0xF90017E3,
|
0xF90017E3,
|
||||||
0, // movz_data_end_offset,
|
0, // movz_data_end_offset,
|
||||||
0x8B090109,
|
0x8B090109,
|
||||||
0xF9400129,
|
0xF9400129,
|
||||||
0xD63F0120,
|
0xD63F0120,
|
||||||
0xF94007E8,
|
0xF94007E8,
|
||||||
0xF9400BE0,
|
0xF9400BE0,
|
||||||
0xF9400FE1,
|
0xF9400FE1,
|
||||||
0xF94013E2,
|
0xF94013E2,
|
||||||
0xF94017E3,
|
0xF94017E3,
|
||||||
0, // movz_main_offset,
|
0, // movz_main_offset,
|
||||||
0x8B090109,
|
0x8B090109,
|
||||||
0xD63F0120,
|
0xD63F0120,
|
||||||
0xF94003FE,
|
0xF94003FE,
|
||||||
0x910043FF,
|
0x910043FF,
|
||||||
0xD65F03C0,
|
0xD65F03C0,
|
||||||
}
|
}
|
||||||
|
|
||||||
ins_size_byte := 4
|
ins_size_byte := 4
|
||||||
shellcode_offset := text_start - (ins_size_byte * len(shellcode))
|
shellcode_offset := text_start - (ins_size_byte * len(shellcode))
|
||||||
main_offset := int(mc.entryoff)
|
main_offset := int(mc.entryoff)
|
||||||
|
|
||||||
encode_movz := func(v int) uint32 {
|
encode_movz := func(v int) uint32 {
|
||||||
return uint32(uint32(v)<<5 | uint32(0x694)<<21 | uint32(0x09))
|
return uint32(uint32(v)<<5 | uint32(0x694)<<21 | uint32(0x09))
|
||||||
}
|
}
|
||||||
|
|
||||||
movz_shellcode_offset := encode_movz(shellcode_offset)
|
movz_shellcode_offset := encode_movz(shellcode_offset)
|
||||||
movz_main_offset := encode_movz(main_offset)
|
movz_main_offset := encode_movz(main_offset)
|
||||||
movz_data_end_offset := encode_movz(data_end)
|
movz_data_end_offset := encode_movz(data_end)
|
||||||
|
|
||||||
shellcode[3] = movz_shellcode_offset
|
shellcode[3] = movz_shellcode_offset
|
||||||
shellcode[10] = movz_data_end_offset
|
shellcode[10] = movz_data_end_offset
|
||||||
shellcode[19] = movz_main_offset
|
shellcode[19] = movz_main_offset
|
||||||
|
|
||||||
fmt.Printf("// shellcode_offset=%x\n", shellcode_offset)
|
fmt.Printf("// shellcode_offset=%x\n", shellcode_offset)
|
||||||
fmt.Printf("// main_offset=%x\n", main_offset)
|
fmt.Printf("// main_offset=%x\n", main_offset)
|
||||||
fmt.Printf("// data_end=%x\n", data_end)
|
fmt.Printf("// data_end=%x\n", data_end)
|
||||||
fmt.Printf("// movz_shellcode_offset=%x\n", movz_shellcode_offset)
|
fmt.Printf("// movz_shellcode_offset=%x\n", movz_shellcode_offset)
|
||||||
fmt.Printf("// movz_main_offset=%x\n", movz_main_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("// movz_data_end_offset=%x\n", movz_data_end_offset)
|
||||||
fmt.Printf("// lc_main_offset=%x\n", lc_main_offset)
|
fmt.Printf("// lc_main_offset=%x\n", lc_main_offset)
|
||||||
|
|
||||||
offset := int64(shellcode_offset)
|
offset := int64(shellcode_offset)
|
||||||
{
|
{
|
||||||
// fix main to point to our newly created shellcode
|
// fix main to point to our newly created shellcode
|
||||||
bs := make([]byte, 8)
|
bs := make([]byte, 8)
|
||||||
mc.byteorder.PutUint64(bs, uint64(offset))
|
mc.byteorder.PutUint64(bs, uint64(offset))
|
||||||
mc.file.WriteAt(bs, int64(lc_main_offset))
|
mc.file.WriteAt(bs, int64(lc_main_offset))
|
||||||
}
|
}
|
||||||
|
|
||||||
bs := make([]byte, 4)
|
bs := make([]byte, 4)
|
||||||
for _, ins := range shellcode {
|
for _, ins := range shellcode {
|
||||||
mc.byteorder.PutUint32(bs, ins)
|
mc.byteorder.PutUint32(bs, ins)
|
||||||
mc.file.WriteAt(bs, offset)
|
mc.file.WriteAt(bs, offset)
|
||||||
offset += 4
|
offset += 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (mc *MachoContext) RemoveSymbolTable() {
|
func (mc *MachoContext) RemoveSymbolTable() {
|
||||||
// try to remove symtab and dysymtab
|
// try to remove symtab and dysymtab
|
||||||
mc.removeSymtabCommand()
|
mc.removeSymtabCommand()
|
||||||
mc.removeDySymtabCommand()
|
mc.removeDySymtabCommand()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) removeSymtabCommand() {
|
func (mc *MachoContext) removeSymtabCommand() {
|
||||||
ptr := int64(0)
|
ptr := int64(0)
|
||||||
if mc.Is64bit() {
|
if mc.Is64bit() {
|
||||||
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
|
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
|
||||||
} else {
|
} else {
|
||||||
ptr, _ = mc.file.Seek(int64(Header_size), io.SeekStart)
|
ptr, _ = mc.file.Seek(int64(Header_size), io.SeekStart)
|
||||||
}
|
}
|
||||||
|
|
||||||
var symtab_fix *Symtab
|
var symtab_fix *Symtab
|
||||||
for _, cmd := range mc.commands {
|
for _, cmd := range mc.commands {
|
||||||
if cmd.Cmd() != LC_SYMTAB {
|
if cmd.Cmd() != LC_SYMTAB {
|
||||||
ptr += int64(cmd.Cmdsize())
|
ptr += int64(cmd.Cmdsize())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var symtab = cmd.(*Symtab)
|
var symtab = cmd.(*Symtab)
|
||||||
symtab_fix = symtab
|
symtab_fix = symtab
|
||||||
|
|
||||||
// erase strings referenced
|
// erase strings referenced
|
||||||
start := int64(symtab_fix.stroff)
|
start := int64(symtab_fix.stroff)
|
||||||
size := symtab_fix.strsize
|
size := symtab_fix.strsize
|
||||||
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
|
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
|
||||||
mc.file.WriteAt(make([]byte, size), start)
|
mc.file.WriteAt(make([]byte, size), start)
|
||||||
|
|
||||||
// erase nlist64 symbol items
|
// erase nlist64 symbol items
|
||||||
start = int64(symtab_fix.symoff)
|
start = int64(symtab_fix.symoff)
|
||||||
size = symtab_fix.nsyms * 16
|
size = symtab_fix.nsyms * 16
|
||||||
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
|
fmt.Printf("// Erase at=0x%x size=0x%x\n", start, size)
|
||||||
mc.file.WriteAt(make([]byte, size), start)
|
mc.file.WriteAt(make([]byte, size), start)
|
||||||
|
|
||||||
symtab_fix.symoff = 0
|
symtab_fix.symoff = 0
|
||||||
symtab_fix.nsyms = 0
|
symtab_fix.nsyms = 0
|
||||||
symtab_fix.stroff = 0
|
symtab_fix.stroff = 0
|
||||||
symtab_fix.strsize = 0
|
symtab_fix.strsize = 0
|
||||||
mc.file.Seek(ptr, io.SeekStart)
|
mc.file.Seek(ptr, io.SeekStart)
|
||||||
mc.file.Write(symtab_fix.Serialize(mc))
|
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() {
|
func (mc *MachoContext) removeDySymtabCommand() {
|
||||||
ptr := int64(0)
|
ptr := int64(0)
|
||||||
if mc.Is64bit() {
|
if mc.Is64bit() {
|
||||||
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
|
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
|
||||||
} else {
|
} else {
|
||||||
@ -585,33 +584,33 @@ func (mc *MachoContext) removeDySymtabCommand() {
|
|||||||
}
|
}
|
||||||
for _, cmd := range mc.commands {
|
for _, cmd := range mc.commands {
|
||||||
if cmd.Cmd() != LC_DYSYMTAB {
|
if cmd.Cmd() != LC_DYSYMTAB {
|
||||||
ptr += int64(cmd.Cmdsize())
|
ptr += int64(cmd.Cmdsize())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var dysymtab = cmd.(*DySymtab)
|
var dysymtab = cmd.(*DySymtab)
|
||||||
dysymtab_fix := dysymtab
|
dysymtab_fix := dysymtab
|
||||||
dysymtab_fix.indirectsymoff = 0
|
dysymtab_fix.indirectsymoff = 0
|
||||||
dysymtab_fix.nindirectsyms = 0
|
dysymtab_fix.nindirectsyms = 0
|
||||||
mc.file.Seek(ptr, io.SeekStart)
|
mc.file.Seek(ptr, io.SeekStart)
|
||||||
mc.file.Write(dysymtab_fix.Serialize(mc))
|
mc.file.Write(dysymtab_fix.Serialize(mc))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) RemoveExportTrie() {
|
func (mc *MachoContext) RemoveExportTrie() {
|
||||||
var start int64
|
var start int64
|
||||||
var size int
|
var size int
|
||||||
if mc.dyldinfo != nil {
|
if mc.dyldinfo != nil {
|
||||||
// legacy export trie
|
// legacy export trie
|
||||||
start = int64(mc.dyldinfo.export_off)
|
start = int64(mc.dyldinfo.export_off)
|
||||||
size = int(mc.dyldinfo.export_size)
|
size = int(mc.dyldinfo.export_size)
|
||||||
mc.file.WriteAt(make([]byte, size), start)
|
mc.file.WriteAt(make([]byte, size), start)
|
||||||
} else if mc.exports != nil {
|
} else if mc.exports != nil {
|
||||||
// modern export trie
|
// modern export trie
|
||||||
start = int64(mc.exports.dataoff)
|
start = int64(mc.exports.dataoff)
|
||||||
size = int(mc.exports.datasize)
|
size = int(mc.exports.datasize)
|
||||||
mc.file.WriteAt(make([]byte, size), start)
|
mc.file.WriteAt(make([]byte, size), start)
|
||||||
} else {
|
} else {
|
||||||
// no export trie (??)
|
// no export trie (??)
|
||||||
// should never occur unless this binary is modified
|
// should never occur unless this binary is modified
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,13 +397,13 @@ func (lcmd *DyldInfo) Deserialize(mc *MachoContext, buf []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Fixups struct {
|
type Fixups struct {
|
||||||
fixups_version uint32
|
fixups_version uint32
|
||||||
starts_offset uint32
|
starts_offset uint32
|
||||||
imports_offset uint32
|
imports_offset uint32
|
||||||
symbols_offset uint32
|
symbols_offset uint32
|
||||||
imports_count uint32
|
imports_count uint32
|
||||||
imports_format uint32
|
imports_format uint32
|
||||||
symbols_format uint32
|
symbols_format uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lcmd *Fixups) Serialize(mc *MachoContext) []byte {
|
func (lcmd *Fixups) Serialize(mc *MachoContext) []byte {
|
||||||
@ -516,25 +516,25 @@ func (lcmd *Symtab) Deserialize(mc *MachoContext, buf []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DySymtab struct {
|
type DySymtab struct {
|
||||||
c LoadCmd
|
c LoadCmd
|
||||||
ilocalsym uint32
|
ilocalsym uint32
|
||||||
nlocalsym uint32
|
nlocalsym uint32
|
||||||
iextdefsym uint32
|
iextdefsym uint32
|
||||||
nextdefsym uint32
|
nextdefsym uint32
|
||||||
iundefsym uint32
|
iundefsym uint32
|
||||||
nundefsym uint32
|
nundefsym uint32
|
||||||
tocoff uint32
|
tocoff uint32
|
||||||
ntoc uint32
|
ntoc uint32
|
||||||
modtaboff uint32
|
modtaboff uint32
|
||||||
nmodtab uint32
|
nmodtab uint32
|
||||||
extrefsymoff uint32
|
extrefsymoff uint32
|
||||||
nextrefsyms uint32
|
nextrefsyms uint32
|
||||||
indirectsymoff uint32
|
indirectsymoff uint32
|
||||||
nindirectsyms uint32
|
nindirectsyms uint32
|
||||||
extreloff uint32
|
extreloff uint32
|
||||||
nextrel uint32
|
nextrel uint32
|
||||||
localrefoff uint32
|
localrefoff uint32
|
||||||
nlocref uint32
|
nlocref uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lcmd *DySymtab) Cmd() 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.nlocalsym)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.iextdefsym)
|
binary.Write(buf, mc.byteorder, lcmd.iextdefsym)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.nextdefsym)
|
binary.Write(buf, mc.byteorder, lcmd.nextdefsym)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.iundefsym)
|
binary.Write(buf, mc.byteorder, lcmd.iundefsym)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.nundefsym)
|
binary.Write(buf, mc.byteorder, lcmd.nundefsym)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.tocoff)
|
binary.Write(buf, mc.byteorder, lcmd.tocoff)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.ntoc)
|
binary.Write(buf, mc.byteorder, lcmd.ntoc)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.modtaboff)
|
binary.Write(buf, mc.byteorder, lcmd.modtaboff)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.nmodtab)
|
binary.Write(buf, mc.byteorder, lcmd.nmodtab)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.extrefsymoff)
|
binary.Write(buf, mc.byteorder, lcmd.extrefsymoff)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.nextrefsyms)
|
binary.Write(buf, mc.byteorder, lcmd.nextrefsyms)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.indirectsymoff)
|
binary.Write(buf, mc.byteorder, lcmd.indirectsymoff)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.nindirectsyms)
|
binary.Write(buf, mc.byteorder, lcmd.nindirectsyms)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.extreloff)
|
binary.Write(buf, mc.byteorder, lcmd.extreloff)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.nextrel)
|
binary.Write(buf, mc.byteorder, lcmd.nextrel)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.localrefoff)
|
binary.Write(buf, mc.byteorder, lcmd.localrefoff)
|
||||||
binary.Write(buf, mc.byteorder, lcmd.nlocref)
|
binary.Write(buf, mc.byteorder, lcmd.nlocref)
|
||||||
return buf.Bytes()
|
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.nlocalsym)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.iextdefsym)
|
binary.Read(r, mc.byteorder, &lcmd.iextdefsym)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.nextdefsym)
|
binary.Read(r, mc.byteorder, &lcmd.nextdefsym)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.iundefsym)
|
binary.Read(r, mc.byteorder, &lcmd.iundefsym)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.nundefsym)
|
binary.Read(r, mc.byteorder, &lcmd.nundefsym)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.tocoff)
|
binary.Read(r, mc.byteorder, &lcmd.tocoff)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.ntoc)
|
binary.Read(r, mc.byteorder, &lcmd.ntoc)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.modtaboff)
|
binary.Read(r, mc.byteorder, &lcmd.modtaboff)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.nmodtab)
|
binary.Read(r, mc.byteorder, &lcmd.nmodtab)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.extrefsymoff)
|
binary.Read(r, mc.byteorder, &lcmd.extrefsymoff)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.nextrefsyms)
|
binary.Read(r, mc.byteorder, &lcmd.nextrefsyms)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.indirectsymoff)
|
binary.Read(r, mc.byteorder, &lcmd.indirectsymoff)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.nindirectsyms)
|
binary.Read(r, mc.byteorder, &lcmd.nindirectsyms)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.extreloff)
|
binary.Read(r, mc.byteorder, &lcmd.extreloff)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.nextrel)
|
binary.Read(r, mc.byteorder, &lcmd.nextrel)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.localrefoff)
|
binary.Read(r, mc.byteorder, &lcmd.localrefoff)
|
||||||
binary.Read(r, mc.byteorder, &lcmd.nlocref)
|
binary.Read(r, mc.byteorder, &lcmd.nlocref)
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,11 @@ type MachoContext struct {
|
|||||||
linkedits []*LinkEdit
|
linkedits []*LinkEdit
|
||||||
segments []Segment
|
segments []Segment
|
||||||
symtab *Symtab
|
symtab *Symtab
|
||||||
dysymtab *DySymtab
|
dysymtab *DySymtab
|
||||||
|
|
||||||
dyldinfo *DyldInfo
|
dyldinfo *DyldInfo
|
||||||
fixups *LinkEdit
|
fixups *LinkEdit
|
||||||
exports *LinkEdit
|
exports *LinkEdit
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) FileSize() uint32 {
|
func (mc *MachoContext) FileSize() uint32 {
|
||||||
@ -235,12 +235,12 @@ func (mc *MachoContext) Parse(r *bufio.Reader) error {
|
|||||||
lcmd.Deserialize(mc, command_buf)
|
lcmd.Deserialize(mc, command_buf)
|
||||||
mc.commands = append(mc.commands, lcmd)
|
mc.commands = append(mc.commands, lcmd)
|
||||||
mc.linkedits = append(mc.linkedits, lcmd)
|
mc.linkedits = append(mc.linkedits, lcmd)
|
||||||
if lcmd.Cmd() == LC_DYLD_CHAINED_FIXUPS {
|
if lcmd.Cmd() == LC_DYLD_CHAINED_FIXUPS {
|
||||||
mc.fixups = lcmd
|
mc.fixups = lcmd
|
||||||
}
|
}
|
||||||
if lcmd.Cmd() == LC_DYLD_EXPORTS_TRIE {
|
if lcmd.Cmd() == LC_DYLD_EXPORTS_TRIE {
|
||||||
mc.exports = lcmd
|
mc.exports = lcmd
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
||||||
case LC_SYMTAB:
|
case LC_SYMTAB:
|
||||||
@ -248,12 +248,14 @@ func (mc *MachoContext) Parse(r *bufio.Reader) error {
|
|||||||
lcmd.Deserialize(mc, command_buf)
|
lcmd.Deserialize(mc, command_buf)
|
||||||
mc.commands = append(mc.commands, lcmd)
|
mc.commands = append(mc.commands, lcmd)
|
||||||
mc.symtab = lcmd
|
mc.symtab = lcmd
|
||||||
|
break
|
||||||
|
|
||||||
case LC_DYSYMTAB:
|
case LC_DYSYMTAB:
|
||||||
lcmd := new(DySymtab)
|
lcmd := new(DySymtab)
|
||||||
lcmd.Deserialize(mc, command_buf)
|
lcmd.Deserialize(mc, command_buf)
|
||||||
mc.commands = append(mc.commands, lcmd)
|
mc.commands = append(mc.commands, lcmd)
|
||||||
mc.dysymtab = lcmd
|
mc.dysymtab = lcmd
|
||||||
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
lcmd := new(LoadCmd)
|
lcmd := new(LoadCmd)
|
||||||
|
@ -82,7 +82,7 @@ func (mc *MachoContext) CollectSymbols() []*Symbol {
|
|||||||
binary.Read(symtab_buffer, mc.byteorder, &value64)
|
binary.Read(symtab_buffer, mc.byteorder, &value64)
|
||||||
} else {
|
} else {
|
||||||
// always use value64
|
// always use value64
|
||||||
var value32 uint32
|
var value32 uint32
|
||||||
binary.Read(symtab_buffer, mc.byteorder, &value32)
|
binary.Read(symtab_buffer, mc.byteorder, &value32)
|
||||||
value64 = uint64(value32)
|
value64 = uint64(value32)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user