rework ios-wrapper cli parsing
This commit is contained in:
parent
a257286d2e
commit
e2c75bf718
@ -7,7 +7,7 @@ import (
|
|||||||
type removeClassicSymbol struct{}
|
type removeClassicSymbol struct{}
|
||||||
|
|
||||||
func (action *removeClassicSymbol) withMacho(mf *MachoFile) error {
|
func (action *removeClassicSymbol) withMacho(mf *MachoFile) error {
|
||||||
mf.Context().RemoveClassicSymbol()
|
mf.Context().RemoveSymbolTable()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
macho-go/internal/wrapper/action/remove_exports.go
Normal file
21
macho-go/internal/wrapper/action/remove_exports.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package action
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "ios-wrapper/internal/wrapper/ofile"
|
||||||
|
)
|
||||||
|
|
||||||
|
type removeExports struct{}
|
||||||
|
|
||||||
|
func (action *removeExports) withMacho(mf *MachoFile) error {
|
||||||
|
mf.Context().RemoveExportTrie()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (action *removeExports) withFat(ff *FatFile) error {
|
||||||
|
return defaultWithFat(action, ff)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRemoveExportsAction() *removeExports {
|
||||||
|
return &removeExports{}
|
||||||
|
}
|
||||||
|
|
71
macho-go/internal/wrapper/action/save_imports.go
Normal file
71
macho-go/internal/wrapper/action/save_imports.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package action
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
// log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
. "ios-wrapper/internal/wrapper/ofile"
|
||||||
|
"ios-wrapper/pkg/protomodel"
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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()]
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
fmt.Println("};")
|
||||||
|
fmt.Printf("uint32_t nimports = %d;\n", len(symbols));
|
||||||
|
mf.Info().Symbols = symbols
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (action *saveImports) withFat(ff *FatFile) error {
|
||||||
|
return defaultWithFat(action, ff)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSaveImportsAction() *saveImports {
|
||||||
|
return &saveImports{}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
"github.com/alecthomas/kong"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -63,7 +64,11 @@ func Cli() {
|
|||||||
arg := cli.Lipo.Join
|
arg := cli.Lipo.Join
|
||||||
fat.FatJoin(arg.Macho, arg.Out)
|
fat.FatJoin(arg.Macho, arg.Out)
|
||||||
return
|
return
|
||||||
}
|
} else if command == "bcell2header" {
|
||||||
|
arg := cli.BcellToHeader
|
||||||
|
bcell2header(arg.Bcell, arg.Out)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var pc ProgramContext
|
var pc ProgramContext
|
||||||
var ofile OFile = nil
|
var ofile OFile = nil
|
||||||
@ -73,7 +78,7 @@ func Cli() {
|
|||||||
arg := cli.Wrap
|
arg := cli.Wrap
|
||||||
ofile = NewOFile(arg.OFile)
|
ofile = NewOFile(arg.OFile)
|
||||||
pc.remove_codesign = true
|
pc.remove_codesign = true
|
||||||
pc.strip_init_pointers = true
|
pc.remove_inits = true
|
||||||
pc.dylib_to_add = []string{"@rpath/bcell.framework/bcell"}
|
pc.dylib_to_add = []string{"@rpath/bcell.framework/bcell"}
|
||||||
pc.rpath_to_add = []string{"@executable_path/Frameworks"}
|
pc.rpath_to_add = []string{"@executable_path/Frameworks"}
|
||||||
pc.outfile = arg.Out
|
pc.outfile = arg.Out
|
||||||
@ -99,6 +104,29 @@ func Cli() {
|
|||||||
ofile = NewOFile(arg.OFile)
|
ofile = NewOFile(arg.OFile)
|
||||||
pc.remove_imports = true
|
pc.remove_imports = true
|
||||||
pc.outfile = arg.Out
|
pc.outfile = arg.Out
|
||||||
|
pc.bcellfile = arg.Bcell
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
pc.remove_imports = arg.RemoveBindSymbols
|
||||||
|
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.dylib_to_add = arg.Dylibs
|
||||||
|
pc.rpath_to_add = arg.Rpath
|
||||||
|
pc.outfile = arg.Out
|
||||||
|
pc.bcellfile = arg.Bcell
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
@ -165,6 +193,12 @@ func displayBcell(bfile string) {
|
|||||||
init_ptr.Value,
|
init_ptr.Value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
fmt.Printf(" | Bind Symbols:\n")
|
||||||
|
for _, symbol := range info.Symbols {
|
||||||
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,3 +228,36 @@ func resolveAddresses(dwarf string, load string, addresses []string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func bcell2header(bfile string, header string) {
|
||||||
|
raw_data, err := ioutil.ReadFile(bfile)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic("Invalid Protobuf<BcellFile> bcell.dat (1)")
|
||||||
|
}
|
||||||
|
data := &protomodel.BcellFile{}
|
||||||
|
err = proto.Unmarshal(raw_data, data)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic("Invalid Protobuf<BcellFile> bcell.dat (2)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("[+] User Config: %+v\n", data.BcellConfig)
|
||||||
|
for arch, info := range data.MachoInfos {
|
||||||
|
fmt.Printf("[+] Arch %s:\n", arch)
|
||||||
|
fmt.Printf(" | PointerSize : %+v\n", info.PointerSize)
|
||||||
|
fmt.Printf(" | Image Base : 0x%x\n", info.ImageBase)
|
||||||
|
fmt.Printf(" | Init Pointers:\n")
|
||||||
|
for _, init_ptr := range info.InitPointers {
|
||||||
|
fmt.Printf(
|
||||||
|
" | offset 0x%x => addr 0x%x\n",
|
||||||
|
init_ptr.Offset,
|
||||||
|
init_ptr.Value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fmt.Printf(" | Bind Symbols:\n")
|
||||||
|
for _, symbol := range info.Symbols {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -26,6 +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"`
|
||||||
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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +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"`
|
||||||
|
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"`
|
||||||
|
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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Argument struct {
|
type Argument struct {
|
||||||
@ -68,5 +88,14 @@ type Argument struct {
|
|||||||
DisplayBcell DisplayBcellArgument `cmd name:"display-bcell" help:"Display Protobuf<BcellFile> content"`
|
DisplayBcell DisplayBcellArgument `cmd name:"display-bcell" help:"Display Protobuf<BcellFile> content"`
|
||||||
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:"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"`
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,12 @@ func (uc *UserConfig) Protomodel() *protomodel.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProgramContext struct {
|
type ProgramContext struct {
|
||||||
strip_init_pointers bool
|
remove_inits bool
|
||||||
remove_codesign bool
|
remove_codesign bool
|
||||||
remove_imports bool
|
remove_imports bool
|
||||||
|
remove_others bool
|
||||||
|
remove_exports bool
|
||||||
|
remove_symbol_table bool
|
||||||
dylib_to_add []string
|
dylib_to_add []string
|
||||||
rpath_to_add []string
|
rpath_to_add []string
|
||||||
|
|
||||||
@ -84,24 +87,27 @@ func (pc *ProgramContext) dispatchActions(ofile OFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pc *ProgramContext) Process(ofile OFile) {
|
func (pc *ProgramContext) Process(ofile OFile) {
|
||||||
if pc.remove_imports {
|
|
||||||
pc.AddAction(NewRemoveImportsAction())
|
|
||||||
pc.AddAction(NewWriteFileAction(pc.outfile))
|
|
||||||
pc.dispatchActions(ofile)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if pc.remove_codesign {
|
if pc.remove_codesign {
|
||||||
pc.AddAction(NewRemoveCodeSignatureAction())
|
pc.AddAction(NewRemoveCodeSignatureAction())
|
||||||
}
|
}
|
||||||
if pc.strip_init_pointers {
|
if pc.remove_inits {
|
||||||
pc.AddAction(NewSaveInitPointerAction())
|
pc.AddAction(NewSaveInitPointerAction())
|
||||||
pc.AddAction(NewRemoveInitPointerAction())
|
pc.AddAction(NewRemoveInitPointerAction())
|
||||||
}
|
}
|
||||||
ExperimentalFeature("Remove Unnecessary Info", func() {
|
if pc.remove_imports {
|
||||||
pc.AddAction(NewRemoveUnnecessaryInfoAction())
|
pc.AddAction(NewSaveImportsAction())
|
||||||
})
|
pc.AddAction(NewRemoveImportsAction())
|
||||||
ExperimentalFeature("Remove Classic Symbol", func() {
|
}
|
||||||
|
if pc.remove_symbol_table {
|
||||||
pc.AddAction(NewRemoveClassicSymbolAction())
|
pc.AddAction(NewRemoveClassicSymbolAction())
|
||||||
|
}
|
||||||
|
if pc.remove_exports {
|
||||||
|
pc.AddAction(NewRemoveExportsAction())
|
||||||
|
}
|
||||||
|
ExperimentalFeature("Remove Unnecessary Info", func() {
|
||||||
|
if pc.remove_others {
|
||||||
|
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))
|
||||||
|
@ -57,6 +57,10 @@ func (sym *ImportSymbol) Stub() uint64 {
|
|||||||
return sym.stub
|
return sym.stub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sym *ImportSymbol) Segment() uint32 {
|
||||||
|
return sym.segment
|
||||||
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) CollectBindSymbols() []*ImportSymbol {
|
func (mc *MachoContext) CollectBindSymbols() []*ImportSymbol {
|
||||||
if mc.dyldinfo == nil {
|
if mc.dyldinfo == nil {
|
||||||
return mc.CollectBindSymbolsModern()
|
return mc.CollectBindSymbolsModern()
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
"bytes"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@ -190,10 +191,6 @@ func (mc *MachoContext) RemoveUnnecessaryInfo() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) RemoveClassicSymbol() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mc *MachoContext) AddLoadCmd(lcmd LoadCommand) {
|
func (mc *MachoContext) AddLoadCmd(lcmd LoadCommand) {
|
||||||
var offset uint64
|
var offset uint64
|
||||||
payload := lcmd.Serialize(mc)
|
payload := lcmd.Serialize(mc)
|
||||||
@ -285,42 +282,15 @@ func (mc *MachoContext) RemoveBindSymbols() {
|
|||||||
} else {
|
} else {
|
||||||
mc.removeBindSymbolsLegacy()
|
mc.removeBindSymbolsLegacy()
|
||||||
}
|
}
|
||||||
|
mc.RenameObjcClasslist()
|
||||||
calculateHash := func(name string) uint32 {
|
|
||||||
var h uint32 = 0x811c9dc5
|
|
||||||
for _, s := range name {
|
|
||||||
h ^= uint32(s)
|
|
||||||
h *= 0x01000193
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
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[] = {")
|
|
||||||
count := 0
|
|
||||||
for _, symbol := range mc.CollectBindSymbols() {
|
for _, symbol := range mc.CollectBindSymbols() {
|
||||||
if symbol.Type() != "lazy" {
|
if symbol.Type() != "lazy" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
count += 1
|
|
||||||
dylib_hash := calculateHash(symbol.Dylib())
|
|
||||||
seg := mc.segments[symbol.segment]
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
|
|
||||||
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.segment, offset);
|
|
||||||
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))
|
||||||
@ -344,8 +314,6 @@ func (mc *MachoContext) RemoveBindSymbols() {
|
|||||||
mc.file.WriteAt(v, int64(symbol.file_address))
|
mc.file.WriteAt(v, int64(symbol.file_address))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("};")
|
|
||||||
fmt.Printf("uint32_t nimports = %d;\n", count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) removeBindSymbolsModern() {
|
func (mc *MachoContext) removeBindSymbolsModern() {
|
||||||
@ -385,6 +353,45 @@ func (mc *MachoContext) removeBindSymbolsLegacy() {
|
|||||||
mc.file.WriteAt(make([]byte, size), int64(start))
|
mc.file.WriteAt(make([]byte, size), int64(start))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mc *MachoContext) RenameObjcClasslist() {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cmd := range mc.commands {
|
||||||
|
if cmd.Cmd() != LC_SEGMENT_64 {
|
||||||
|
ptr += int64(cmd.Cmdsize())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var segment = cmd.(*Segment64)
|
||||||
|
|
||||||
|
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 {
|
||||||
|
// section_ptr := ptr + 0x40 + 8
|
||||||
|
// for _, section := range segment.Sections() {
|
||||||
|
// section_ptr += 16 * 2 + 8 * 2 + 4 * 8
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
ptr += int64(cmd.Cmdsize())
|
||||||
|
}
|
||||||
|
mc.file.Seek(0, io.SeekStart)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (mc *MachoContext) RemoveSymbolTable() {
|
func (mc *MachoContext) RemoveSymbolTable() {
|
||||||
// try to remove symtab and dysymtab
|
// try to remove symtab and dysymtab
|
||||||
mc.removeSymtabCommand()
|
mc.removeSymtabCommand()
|
||||||
|
@ -97,6 +97,7 @@ int ParseFixValue(int format, uint64_t value, int* bind, uint64_t* ret1, uint64_
|
|||||||
uint64_t MakeRebaseFixupOpcode(int next, uint64_t target, uint64_t high8) {
|
uint64_t MakeRebaseFixupOpcode(int next, uint64_t target, uint64_t high8) {
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
struct dyld_chained_ptr_64_rebase* b = (struct dyld_chained_ptr_64_rebase*)&value;
|
struct dyld_chained_ptr_64_rebase* b = (struct dyld_chained_ptr_64_rebase*)&value;
|
||||||
|
b->bind = 0;
|
||||||
b->next = next;
|
b->next = next;
|
||||||
b->target = target;
|
b->target = target;
|
||||||
b->high8 = high8;
|
b->high8 = high8;
|
||||||
|
@ -72,7 +72,6 @@ func (mc *MachoContext) CollectSymbols() []*Symbol {
|
|||||||
var flags uint8
|
var flags uint8
|
||||||
var sect uint8
|
var sect uint8
|
||||||
var desc uint16
|
var desc uint16
|
||||||
var value32 uint32
|
|
||||||
var value64 uint64
|
var value64 uint64
|
||||||
|
|
||||||
binary.Read(symtab_buffer, mc.byteorder, &strx)
|
binary.Read(symtab_buffer, mc.byteorder, &strx)
|
||||||
@ -83,6 +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
|
||||||
binary.Read(symtab_buffer, mc.byteorder, &value32)
|
binary.Read(symtab_buffer, mc.byteorder, &value32)
|
||||||
value64 = uint64(value32)
|
value64 = uint64(value32)
|
||||||
}
|
}
|
||||||
|
@ -17,18 +17,18 @@ message MachoInfo {
|
|||||||
uint64 value = 2; // address of the init function
|
uint64 value = 2; // address of the init function
|
||||||
}
|
}
|
||||||
|
|
||||||
// iOS library rewrite these as opcodes and dyld processes
|
// right now we waste memory to store name/hash for all symbols
|
||||||
// message LazySymbol {
|
// should consider compress them, dyld stores the index in list of LC_DYLIB
|
||||||
// string name = 1;
|
message BindSymbol {
|
||||||
// int32 dylib_ordinal = 2; // could be -1 -2
|
string name = 1;
|
||||||
// uint32 segment = 3;
|
string libname = 2;
|
||||||
// uint32 segment_offset = 4;
|
uint32 libhash = 3;
|
||||||
// }
|
uint32 segment = 4; // segment index
|
||||||
|
uint64 offset = 5; // offset in segment
|
||||||
|
}
|
||||||
|
|
||||||
PointerSize pointer_size = 1;
|
PointerSize pointer_size = 1;
|
||||||
uint64 image_base = 2;
|
uint64 image_base = 2;
|
||||||
repeated InitPointer init_pointers = 3;
|
repeated InitPointer init_pointers = 3;
|
||||||
// saved or read from header -> dyld_info -> lazyoff
|
repeated BindSymbol symbols = 4;
|
||||||
// uint64 lazy_symbol_address = 4;
|
|
||||||
// repeated LazySymbol lazy_symbols = 5;
|
|
||||||
}
|
}
|
||||||
|
@ -61,11 +61,11 @@ clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_l
|
|||||||
clang -fobjc-arc -ObjC -mmacosx-version-min=$VERSION -o $OUT/a -L"./out" -lb a.mm
|
clang -fobjc-arc -ObjC -mmacosx-version-min=$VERSION -o $OUT/a -L"./out" -lb a.mm
|
||||||
|
|
||||||
# extract symbols from a
|
# extract symbols from a
|
||||||
../../macho-go/bin/ios-wrapper remove-imports $OUT/a -o $OUT/a > $OUT/b.h
|
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --remove-symbol-table $OUT/a > $OUT/b.h
|
||||||
# build libb with symbols extracted from a
|
# build libb with symbols extracted from a
|
||||||
clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_library out/libc.dylib b.cc
|
clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_library out/libc.dylib b.cc
|
||||||
|
|
||||||
out/a
|
out/a-fixed
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user