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.remove_codesign = true
|
||||||
pc.outfile = arg.Out
|
pc.outfile = arg.Out
|
||||||
|
|
||||||
|
case "remove-imports":
|
||||||
|
arg := cli.RemoveImports
|
||||||
|
ofile = NewOFile(arg.OFile)
|
||||||
|
pc.remove_imports = true
|
||||||
|
pc.outfile = arg.Out
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,11 @@ type RemoveCodesignArgument struct {
|
|||||||
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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
type SignedBcellArgument struct {
|
||||||
Out string `short:"o" required name:"outfile" help:"bcell.dat.signed output file" type:"existingfile"`
|
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"`
|
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"`
|
Wrap WrapArgument `cmd help:"Modifies Mach-O/Fat binary"`
|
||||||
Vltk VltkArgument `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"`
|
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"`
|
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>"`
|
SignedBcell SignedBcellArgument `cmd name:"signed-bcell" help:"Change Protobuf<BcellFile> into Protobuf<SignedData>"`
|
||||||
DisplayBcell DisplayBcellArgument `cmd name:"display-bcell" help:"Display Protobuf<BcellFile> content"`
|
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)
|
fmt.Printf("Init functions at offset %s\n", &fun)
|
||||||
}
|
}
|
||||||
|
|
||||||
symbols := mc.CollectLazyBindSymbols()
|
symbols := mc.CollectBindSymbols()
|
||||||
if len(symbols) > 0 {
|
for _, sym := range symbols {
|
||||||
fmt.Println("Lazy Symbols")
|
fmt.Printf(
|
||||||
for _, sym := range symbols {
|
"%s (%s)\n\tStub=0x%x Address=0x%x\n\tDylib=%s\n",
|
||||||
fmt.Printf(
|
sym.Name(),
|
||||||
"%s\n\tStub=0x%x Address=0x%x\n\tDylib=%s\n",
|
sym.Type(),
|
||||||
sym.Name(),
|
sym.Stub(),
|
||||||
sym.Stub(),
|
sym.Address(),
|
||||||
sym.Address(),
|
sym.Dylib(),
|
||||||
sym.Dylib(),
|
)
|
||||||
)
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println("No lazy symbols")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("======")
|
fmt.Println("======")
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ func (uc *UserConfig) Protomodel() *protomodel.Config {
|
|||||||
type ProgramContext struct {
|
type ProgramContext struct {
|
||||||
strip_init_pointers bool
|
strip_init_pointers bool
|
||||||
remove_codesign bool
|
remove_codesign bool
|
||||||
|
remove_imports bool
|
||||||
dylib_to_add []string
|
dylib_to_add []string
|
||||||
rpath_to_add []string
|
rpath_to_add []string
|
||||||
|
|
||||||
@ -83,6 +84,12 @@ 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())
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
type ImportSymbol struct {
|
type ImportSymbol struct {
|
||||||
name string
|
name string
|
||||||
|
typ string
|
||||||
dylib string
|
dylib string
|
||||||
segment uint32
|
segment uint32
|
||||||
segment_offset uint32
|
segment_offset uint32
|
||||||
@ -29,6 +30,10 @@ func (sym *ImportSymbol) Name() string {
|
|||||||
return sym.name
|
return sym.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sym *ImportSymbol) Type() string {
|
||||||
|
return sym.typ
|
||||||
|
}
|
||||||
|
|
||||||
func (sym *ImportSymbol) Dylib() string {
|
func (sym *ImportSymbol) Dylib() string {
|
||||||
return sym.dylib
|
return sym.dylib
|
||||||
}
|
}
|
||||||
@ -45,28 +50,22 @@ func (sym *ImportSymbol) Stub() uint64 {
|
|||||||
return sym.stub
|
return sym.stub
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) CollectLazyBindSymbols() []*ImportSymbol {
|
func (mc *MachoContext) CollectBindSymbols() []*ImportSymbol {
|
||||||
if mc.dyldinfo == nil {
|
if mc.dyldinfo == nil {
|
||||||
return mc.CollectLazyBindSymbolsModern()
|
return mc.CollectBindSymbolsModern()
|
||||||
} else {
|
} else {
|
||||||
return mc.CollectLazyBindSymbolsLegacy()
|
return mc.CollectBindSymbolsLegacy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New convention using LC_DYLD_CHAINED_FIXUPS
|
// New convention using LC_DYLD_CHAINED_FIXUPS
|
||||||
func (mc *MachoContext) CollectLazyBindSymbolsModern() []*ImportSymbol {
|
func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
||||||
var buf []byte
|
var buf []byte
|
||||||
for _, cmd := range mc.Linkedits() {
|
for _, cmd := range mc.Linkedits() {
|
||||||
if cmd.Cmd() != LC_DYLD_CHAINED_FIXUPS {
|
if cmd.Cmd() != LC_DYLD_CHAINED_FIXUPS {
|
||||||
continue
|
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()]
|
buf = mc.buf[cmd.Dataoff() : cmd.Dataoff()+cmd.Datasize()]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -98,34 +97,62 @@ func (mc *MachoContext) CollectLazyBindSymbolsModern() []*ImportSymbol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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) CollectLazyBindSymbolsLegacy() []*ImportSymbol {
|
func (mc *MachoContext) CollectBindSymbolsLegacy() []*ImportSymbol {
|
||||||
start := mc.dyldinfo.lazy_bind_off
|
// // clear this whole section to 0x00 BIND_OPCODE_DONE
|
||||||
size := mc.dyldinfo.lazy_bind_size
|
// dummy := []byte{
|
||||||
end := start + size
|
// 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 {
|
if size == 0 {
|
||||||
return []*ImportSymbol{}
|
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 syms []*ImportSymbol
|
||||||
var sym ImportSymbol
|
var sym ImportSymbol
|
||||||
// symoffset := offset
|
|
||||||
|
offset := uint(0)
|
||||||
lastop_done := false
|
lastop_done := false
|
||||||
for offset < uint(size) {
|
for offset < uint(size) {
|
||||||
d, _ := buf.ReadByte()
|
d, _ := buf.ReadByte()
|
||||||
@ -151,6 +178,7 @@ func (mc *MachoContext) CollectLazyBindSymbolsLegacy() []*ImportSymbol {
|
|||||||
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
|
||||||
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)
|
||||||
|
|
||||||
@ -187,6 +215,9 @@ func (mc *MachoContext) CollectLazyBindSymbolsLegacy() []*ImportSymbol {
|
|||||||
|
|
||||||
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
|
||||||
|
// while we are string so we can remove that
|
||||||
|
sym.name = sym.name[:len(sym.name)-1]
|
||||||
offset += uint(len(sym.name))
|
offset += uint(len(sym.name))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -267,3 +267,51 @@ func (mc *MachoContext) UpdateHeaderRemoveLcmd(size uint32) {
|
|||||||
mc.file.WriteAt(mc.header.Serialize(mc), 0)
|
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