add remove imports command
This commit is contained in:
parent
9d94dd5494
commit
b5ee7124ab
21
macho-go/internal/wrapper/action/remove_imports.go
Normal file
21
macho-go/internal/wrapper/action/remove_imports.go
Normal file
@ -0,0 +1,21 @@
|
||||
package action
|
||||
|
||||
import (
|
||||
. "ios-wrapper/internal/wrapper/ofile"
|
||||
)
|
||||
|
||||
type removeImports struct{}
|
||||
|
||||
func (action *removeImports) withMacho(mf *MachoFile) error {
|
||||
mf.Context().RemoveBindSymbols()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (action *removeImports) withFat(ff *FatFile) error {
|
||||
return defaultWithFat(action, ff)
|
||||
}
|
||||
|
||||
func NewRemoveImportsAction() *removeImports {
|
||||
return &removeImports{}
|
||||
}
|
||||
|
@ -94,6 +94,12 @@ func Cli() {
|
||||
pc.remove_codesign = true
|
||||
pc.outfile = arg.Out
|
||||
|
||||
case "remove-imports":
|
||||
arg := cli.RemoveImports
|
||||
ofile = NewOFile(arg.OFile)
|
||||
pc.remove_imports = true
|
||||
pc.outfile = arg.Out
|
||||
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
@ -24,6 +24,11 @@ type RemoveCodesignArgument struct {
|
||||
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
|
||||
}
|
||||
|
||||
type RemoveImportsArgument struct {
|
||||
Out string `short:"o" required name:"outfile" help:"Modified Mach-O/Fat binary output file" type:"path"`
|
||||
OFile string `arg help:"Path to Mach-O/Fat binary file" type:"existingfile"`
|
||||
}
|
||||
|
||||
type SignedBcellArgument struct {
|
||||
Out string `short:"o" required name:"outfile" help:"bcell.dat.signed output file" type:"existingfile"`
|
||||
Bcell string `arg short:"b" required help:"bcell.dat input file" type:"existingfile"`
|
||||
@ -57,6 +62,7 @@ type Argument struct {
|
||||
Wrap WrapArgument `cmd help:"Modifies Mach-O/Fat binary"`
|
||||
Vltk VltkArgument `cmd help:"Modifies Mach-O/Fat binary"`
|
||||
Info InfoArgument `cmd help:"Show Mach-O/Fat binary information"`
|
||||
RemoveImports RemoveImportsArgument `cmd aliases:"remove-imports" name:"remove-imports" help:"Remove imports"`
|
||||
RemoveCodesign RemoveCodesignArgument `cmd aliases:"remove-signature" name:"remove-codesign" help:"Remove LC_CODE_SIGNATURE from Mach-O/Fat binary"`
|
||||
SignedBcell SignedBcellArgument `cmd name:"signed-bcell" help:"Change Protobuf<BcellFile> into Protobuf<SignedData>"`
|
||||
DisplayBcell DisplayBcellArgument `cmd name:"display-bcell" help:"Display Protobuf<BcellFile> content"`
|
||||
|
@ -34,21 +34,17 @@ func (printer *InfoPrinter) Print() {
|
||||
fmt.Printf("Init functions at offset %s\n", &fun)
|
||||
}
|
||||
|
||||
symbols := mc.CollectLazyBindSymbols()
|
||||
if len(symbols) > 0 {
|
||||
fmt.Println("Lazy Symbols")
|
||||
for _, sym := range symbols {
|
||||
fmt.Printf(
|
||||
"%s\n\tStub=0x%x Address=0x%x\n\tDylib=%s\n",
|
||||
sym.Name(),
|
||||
sym.Stub(),
|
||||
sym.Address(),
|
||||
sym.Dylib(),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("No lazy symbols")
|
||||
}
|
||||
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(),
|
||||
)
|
||||
}
|
||||
|
||||
fmt.Println("======")
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ func (uc *UserConfig) Protomodel() *protomodel.Config {
|
||||
type ProgramContext struct {
|
||||
strip_init_pointers bool
|
||||
remove_codesign bool
|
||||
remove_imports bool
|
||||
dylib_to_add []string
|
||||
rpath_to_add []string
|
||||
|
||||
@ -83,6 +84,12 @@ func (pc *ProgramContext) dispatchActions(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 {
|
||||
pc.AddAction(NewRemoveCodeSignatureAction())
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
|
||||
type ImportSymbol struct {
|
||||
name string
|
||||
typ string
|
||||
dylib string
|
||||
segment uint32
|
||||
segment_offset uint32
|
||||
@ -29,6 +30,10 @@ func (sym *ImportSymbol) Name() string {
|
||||
return sym.name
|
||||
}
|
||||
|
||||
func (sym *ImportSymbol) Type() string {
|
||||
return sym.typ
|
||||
}
|
||||
|
||||
func (sym *ImportSymbol) Dylib() string {
|
||||
return sym.dylib
|
||||
}
|
||||
@ -45,28 +50,22 @@ func (sym *ImportSymbol) Stub() uint64 {
|
||||
return sym.stub
|
||||
}
|
||||
|
||||
func (mc *MachoContext) CollectLazyBindSymbols() []*ImportSymbol {
|
||||
func (mc *MachoContext) CollectBindSymbols() []*ImportSymbol {
|
||||
if mc.dyldinfo == nil {
|
||||
return mc.CollectLazyBindSymbolsModern()
|
||||
return mc.CollectBindSymbolsModern()
|
||||
} else {
|
||||
return mc.CollectLazyBindSymbolsLegacy()
|
||||
return mc.CollectBindSymbolsLegacy()
|
||||
}
|
||||
}
|
||||
|
||||
// New convention using LC_DYLD_CHAINED_FIXUPS
|
||||
func (mc *MachoContext) CollectLazyBindSymbolsModern() []*ImportSymbol {
|
||||
func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
||||
var buf []byte
|
||||
for _, cmd := range mc.Linkedits() {
|
||||
if cmd.Cmd() != LC_DYLD_CHAINED_FIXUPS {
|
||||
continue
|
||||
}
|
||||
|
||||
count_offset := int64(cmd.Dataoff()) + 16
|
||||
mc.file.WriteAt([]byte{0, 0, 0, 0}, count_offset)
|
||||
|
||||
symbol_offset := int64(0x4000)
|
||||
mc.file.WriteAt([]byte{0, 0, 0, 0, 0, 0, 0, 0}, symbol_offset)
|
||||
|
||||
buf = mc.buf[cmd.Dataoff() : cmd.Dataoff()+cmd.Datasize()]
|
||||
break
|
||||
}
|
||||
@ -98,34 +97,62 @@ func (mc *MachoContext) CollectLazyBindSymbolsModern() []*ImportSymbol {
|
||||
}
|
||||
|
||||
// Old convention using LC_DYLD_INFO_ONLY section and bytecode runner
|
||||
func (mc *MachoContext) CollectLazyBindSymbolsLegacy() []*ImportSymbol {
|
||||
start := mc.dyldinfo.lazy_bind_off
|
||||
size := mc.dyldinfo.lazy_bind_size
|
||||
end := start + size
|
||||
func (mc *MachoContext) CollectBindSymbolsLegacy() []*ImportSymbol {
|
||||
// // clear this whole section to 0x00 BIND_OPCODE_DONE
|
||||
// dummy := []byte{
|
||||
// 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
// 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
// }
|
||||
// // make LINK EDIT section writable
|
||||
// // mc.file.WriteAt([]byte{0x03}, int64(0x3f8))
|
||||
// // set number of symbols to 0
|
||||
// mc.file.WriteAt([]byte{0, 0, 0, 0}, int64(0x444))
|
||||
// mc.file.WriteAt([]byte{0, 0, 0, 0}, int64(0x44c))
|
||||
// mc.file.WriteAt([]byte{0, 0, 0, 0}, int64(0x48c))
|
||||
// mc.file.WriteAt(dummy, int64(start))
|
||||
|
||||
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")
|
||||
})()
|
||||
|
||||
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...)
|
||||
|
||||
return symbols
|
||||
}
|
||||
|
||||
func (mc *MachoContext) readBindStream(buf *bytes.Buffer, typ string) []*ImportSymbol {
|
||||
size := buf.Len()
|
||||
if size == 0 {
|
||||
return []*ImportSymbol{}
|
||||
}
|
||||
|
||||
// clear this whole section to 0x00 BIND_OPCODE_DONE
|
||||
dummy := []byte{
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
}
|
||||
// make LINK EDIT section writable
|
||||
// mc.file.WriteAt([]byte{0x03}, int64(0x3f8))
|
||||
// set number of symbols to 0
|
||||
mc.file.WriteAt([]byte{0, 0, 0, 0}, int64(0x444))
|
||||
mc.file.WriteAt([]byte{0, 0, 0, 0}, int64(0x44c))
|
||||
mc.file.WriteAt([]byte{0, 0, 0, 0}, int64(0x48c))
|
||||
mc.file.WriteAt(dummy, int64(start))
|
||||
|
||||
buf := bytes.NewBuffer(mc.buf[start:end])
|
||||
offset := uint(0)
|
||||
|
||||
var syms []*ImportSymbol
|
||||
var sym ImportSymbol
|
||||
// symoffset := offset
|
||||
|
||||
offset := uint(0)
|
||||
lastop_done := false
|
||||
for offset < uint(size) {
|
||||
d, _ := buf.ReadByte()
|
||||
@ -151,6 +178,7 @@ func (mc *MachoContext) CollectLazyBindSymbolsLegacy() []*ImportSymbol {
|
||||
case BIND_OPCODE_DO_BIND:
|
||||
if sym.name != "" {
|
||||
new_sym := sym
|
||||
new_sym.typ = typ
|
||||
syms = append(syms, &new_sym)
|
||||
// fmt.Printf("Offset 0x%x: Symbol %+v\n", symoffset, sym)
|
||||
|
||||
@ -187,6 +215,9 @@ func (mc *MachoContext) CollectLazyBindSymbolsLegacy() []*ImportSymbol {
|
||||
|
||||
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]
|
||||
offset += uint(len(sym.name))
|
||||
break
|
||||
|
||||
|
@ -267,3 +267,51 @@ func (mc *MachoContext) UpdateHeaderRemoveLcmd(size uint32) {
|
||||
mc.file.WriteAt(mc.header.Serialize(mc), 0)
|
||||
}
|
||||
}
|
||||
|
||||
func (mc *MachoContext) RemoveBindSymbols() {
|
||||
if !mc.WriteEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
if mc.dyldinfo == nil {
|
||||
mc.removeBindSymbolsModern()
|
||||
} else {
|
||||
mc.removeBindSymbolsLegacy()
|
||||
}
|
||||
}
|
||||
|
||||
func (mc *MachoContext) removeBindSymbolsModern() {}
|
||||
|
||||
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))
|
||||
|
||||
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
|
||||
// we write the c code to stdout lol
|
||||
fmt.Println("struct imported_symbol {const char* name; const char* lib; uint32_t hash; uint64_t address;};")
|
||||
fmt.Println("struct imported_symbol imported_table[] = {")
|
||||
count := 0
|
||||
for _, symbol := range mc.CollectBindSymbols() {
|
||||
if symbol.Type() != "lazy" {
|
||||
continue
|
||||
}
|
||||
count += 1
|
||||
dylib_hash := calculateHash(symbol.Dylib())
|
||||
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x},\n",
|
||||
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.Address());
|
||||
}
|
||||
fmt.Println("};")
|
||||
fmt.Printf("uint32_t nimports = %d;\n", count);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user