add keep imports action
This commit is contained in:
parent
557eed0254
commit
6815ea6556
26
macho-go/internal/wrapper/action/rewrite_imports.go
Normal file
26
macho-go/internal/wrapper/action/rewrite_imports.go
Normal file
@ -0,0 +1,26 @@
|
||||
package action
|
||||
|
||||
import (
|
||||
. "ios-wrapper/internal/wrapper/ofile"
|
||||
)
|
||||
|
||||
type rewriteImports struct{
|
||||
symbols []string
|
||||
}
|
||||
|
||||
func (action *rewriteImports) withMacho(mf *MachoFile) error {
|
||||
mc := mf.Context()
|
||||
mc.RewriteImportsTable(action.symbols)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (action *rewriteImports) withFat(ff *FatFile) error {
|
||||
return defaultWithFat(action, ff)
|
||||
}
|
||||
|
||||
func NewRewriteImportsWithKeepSymbolsAction(symbols []string) *rewriteImports {
|
||||
return &rewriteImports{
|
||||
symbols,
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,16 @@ package action
|
||||
import (
|
||||
// "fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
// log "github.com/sirupsen/logrus"
|
||||
|
||||
. "ios-wrapper/internal/wrapper/ofile"
|
||||
"ios-wrapper/pkg/protomodel"
|
||||
)
|
||||
|
||||
type saveImports struct{}
|
||||
type saveImports struct{
|
||||
keepSymbols []string
|
||||
}
|
||||
|
||||
func (action *saveImports) withMacho(mf *MachoFile) error {
|
||||
// calculateHash := func(name string) uint32 {
|
||||
@ -51,6 +54,30 @@ func (action *saveImports) withMacho(mf *MachoFile) error {
|
||||
if symbol.Type() != "lazy" {
|
||||
continue
|
||||
}
|
||||
|
||||
skip := false
|
||||
for _, keep := range action.keepSymbols {
|
||||
name := keep
|
||||
lib := ""
|
||||
parts := strings.Split(keep, ",")
|
||||
if len(parts) == 2 {
|
||||
name = parts[0]
|
||||
lib = parts[1]
|
||||
}
|
||||
|
||||
if symbol.Name() != name {
|
||||
continue
|
||||
}
|
||||
if lib == "" || lib == symbol.Dylib() {
|
||||
skip = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
|
||||
// dylib_hash := calculateHash(symbol.Dylib())
|
||||
seg := mc.Segments()[symbol.Segment()]
|
||||
|
||||
@ -113,6 +140,8 @@ func (action *saveImports) withFat(ff *FatFile) error {
|
||||
return defaultWithFat(action, ff)
|
||||
}
|
||||
|
||||
func NewSaveImportsAction() *saveImports {
|
||||
return &saveImports{}
|
||||
func NewSaveImportsAction(keepSymbols []string) *saveImports {
|
||||
return &saveImports{
|
||||
keepSymbols,
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ func Cli() {
|
||||
pc.rpath_to_add = arg.Rpath
|
||||
pc.outfile = arg.Out
|
||||
pc.bcellfile = arg.Bcell
|
||||
pc.symbols_keep = arg.KeepImports
|
||||
|
||||
default:
|
||||
return
|
||||
|
@ -71,6 +71,8 @@ type PepeArgument struct {
|
||||
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"`
|
||||
|
||||
KeepImports []string `short:"keep" help:"Do not remove import symbols and allow dyld resolve. If symbols is found with more than 1 occurrances, specify the library with a comma or else all occurrances will be kept. e.g., _symbol,libLIB.dylib"`
|
||||
}
|
||||
|
||||
type BcellToHeaderArgument struct {
|
||||
|
@ -46,6 +46,7 @@ type ProgramContext struct {
|
||||
remove_symbol_table bool
|
||||
dylib_to_add []string
|
||||
rpath_to_add []string
|
||||
symbols_keep []string
|
||||
|
||||
outfile string
|
||||
|
||||
@ -95,8 +96,9 @@ func (pc *ProgramContext) Process(ofile OFile) {
|
||||
pc.AddAction(NewRemoveInitPointerAction())
|
||||
}
|
||||
if pc.remove_imports {
|
||||
pc.AddAction(NewSaveImportsAction())
|
||||
pc.AddAction(NewSaveImportsAction(pc.symbols_keep))
|
||||
pc.AddAction(NewRemoveImportsAction())
|
||||
pc.AddAction(NewRewriteImportsWithKeepSymbolsAction(pc.symbols_keep))
|
||||
}
|
||||
if pc.remove_symbol_table {
|
||||
pc.AddAction(NewRemoveClassicSymbolAction())
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"math/rand"
|
||||
"time"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
@ -524,6 +525,77 @@ func (mc *MachoContext) ReworkForObjc() {
|
||||
}
|
||||
}
|
||||
|
||||
func (mc *MachoContext) RewriteImportsTable(keepSymbols []string) {
|
||||
allSymbols := mc.CollectBindSymbols()
|
||||
fixups, fixupsOffset := mc.Fixups()
|
||||
|
||||
importTable := fixups.ImportsOffset(uint32(fixupsOffset))
|
||||
symbolTable := fixups.SymbolsOffset(uint32(fixupsOffset))
|
||||
symbolTablePtr := symbolTable
|
||||
|
||||
// in removeBindSymbolsModern, we erase these pointers in file
|
||||
// but because we keep a few symbols, we need to rewrite the pointers
|
||||
// as well as rebuild the import table and strings table, and bind values
|
||||
|
||||
keepCount := uint32(0)
|
||||
for _, symbol := range keepSymbols {
|
||||
name := symbol
|
||||
lib := ""
|
||||
parts := strings.Split(symbol, ",")
|
||||
if len(parts) == 2 {
|
||||
name = parts[0]
|
||||
lib = parts[1]
|
||||
}
|
||||
|
||||
symbolInfo := (*ImportSymbol)(nil)
|
||||
for _, s := range allSymbols {
|
||||
if s.Name() != name {
|
||||
continue
|
||||
}
|
||||
if lib == "" || lib == s.Dylib() {
|
||||
symbolInfo = s
|
||||
break
|
||||
}
|
||||
}
|
||||
if symbolInfo == nil {
|
||||
// symbol not found
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("keep symbol %s\n", name)
|
||||
fmt.Printf("importTable at 0x%x; stringTable at 0x%x\n", importTable, symbolTablePtr)
|
||||
fmt.Printf("bind value at 0x%x\n", symbolInfo.file_address)
|
||||
|
||||
// write string to string table
|
||||
mc.file.WriteAt([]byte(name), int64(symbolTablePtr))
|
||||
// fix bind value
|
||||
rebaseOpcodeBytes := make([]byte, 8)
|
||||
mc.file.ReadAt(rebaseOpcodeBytes, int64(symbolInfo.file_address))
|
||||
rebaseOpcode := mc.byteorder.Uint64(rebaseOpcodeBytes)
|
||||
bindOpcode := C.MakeBindFixupOpcodeFromRebase(C.uint64_t(rebaseOpcode), C.uint(keepCount))
|
||||
|
||||
{
|
||||
v := make([]byte, 8)
|
||||
mc.byteorder.PutUint64(v, uint64(bindOpcode))
|
||||
mc.file.WriteAt(v, int64(symbolInfo.file_address))
|
||||
}
|
||||
// write import data to import table
|
||||
entry := C.MakeImportTableEntry(C.uint(symbolInfo.LibOrdinal()), C.uint(symbolTablePtr - symbolTable))
|
||||
{
|
||||
v := make([]byte, 4)
|
||||
mc.byteorder.PutUint32(v, uint32(entry))
|
||||
mc.file.WriteAt(v, int64(importTable))
|
||||
}
|
||||
|
||||
keepCount += 1
|
||||
importTable += 4
|
||||
symbolTablePtr += uint32(len(name)) + 1
|
||||
}
|
||||
|
||||
fixups.imports_count = keepCount
|
||||
mc.file.WriteAt(fixups.Serialize(mc), int64(mc.fixups.dataoff))
|
||||
}
|
||||
|
||||
func (mc *MachoContext) RemoveSymbolTable() {
|
||||
// try to remove symtab and dysymtab
|
||||
mc.removeSymtabCommand()
|
||||
|
@ -104,6 +104,28 @@ uint64_t MakeRebaseFixupOpcode(int next, uint64_t target, uint64_t high8) {
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t MakeBindFixupOpcodeFromRebase(uint64_t rebaseOpcode, uint32_t ordinal) {
|
||||
printf("fix bind value\n");
|
||||
uint64_t ret;
|
||||
struct dyld_chained_ptr_64_bind* b = (struct dyld_chained_ptr_64_bind*)&ret;
|
||||
b->next = ((struct dyld_chained_ptr_64_rebase*)&rebaseOpcode)->next;
|
||||
b->bind = 1;
|
||||
b->ordinal = ordinal;
|
||||
b->addend = 0;
|
||||
b->reserved = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t MakeImportTableEntry(uint32_t lib_ordinal, uint32_t name_offset) {
|
||||
printf("append import table\n");
|
||||
uint32_t ret;
|
||||
struct dyld_chained_import* import = (struct dyld_chained_import*)&ret;
|
||||
import->lib_ordinal = lib_ordinal;
|
||||
import->name_offset = name_offset;
|
||||
import->weak_import = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ParseFixUps(uint8_t* buffer) {
|
||||
struct dyld_chained_fixups_header* header = (struct dyld_chained_fixups_header*)buffer;
|
||||
printf("starts=0x%x\n", header->starts_offset);
|
||||
|
@ -31,4 +31,7 @@ struct ImportSymbol GetImportsAt(struct ImportTable* table, int i);
|
||||
int GetSegmentFixAt(uint8_t* buffer, uint32_t i, struct SegmentFix* fix);
|
||||
int ParseFixValue(int format, uint64_t value, int* bind, uint64_t* ret1, uint64_t* ret2);
|
||||
uint64_t MakeRebaseFixupOpcode(int next, uint64_t target, uint64_t high8);
|
||||
|
||||
uint64_t MakeBindFixupOpcodeFromRebase(uint64_t rebaseOpcode, uint32_t ordinal);
|
||||
uint32_t MakeImportTableEntry(uint32_t lib_ordinal, uint32_t name_offset);
|
||||
#endif
|
||||
|
@ -37,6 +37,14 @@ func (h *Header) Cpusubtype() uint32 {
|
||||
return h.cpusubtype
|
||||
}
|
||||
|
||||
func (h *Header) IsExecutable() bool {
|
||||
return h.filetype == 0x2
|
||||
}
|
||||
|
||||
func (h *Header) IsDylib() bool {
|
||||
return h.filetype == 0x6
|
||||
}
|
||||
|
||||
func (h *Header) Serialize(mc *MachoContext) []byte {
|
||||
buf := new(bytes.Buffer)
|
||||
binary.Write(buf, mc.byteorder, h.magic)
|
||||
@ -406,6 +414,14 @@ type Fixups struct {
|
||||
symbols_format uint32
|
||||
}
|
||||
|
||||
func (lcmd *Fixups) ImportsOffset(fixups_offset uint32) uint32 {
|
||||
return lcmd.imports_offset + fixups_offset
|
||||
}
|
||||
|
||||
func (lcmd *Fixups) SymbolsOffset(fixups_offset uint32) uint32 {
|
||||
return lcmd.symbols_offset + fixups_offset
|
||||
}
|
||||
|
||||
func (lcmd *Fixups) Serialize(mc *MachoContext) []byte {
|
||||
buf := new(bytes.Buffer)
|
||||
binary.Write(buf, mc.byteorder, lcmd.fixups_version)
|
||||
|
@ -68,6 +68,14 @@ func (mc *MachoContext) Main() uint64 {
|
||||
return mc.entryoff
|
||||
}
|
||||
|
||||
func (mc *MachoContext) Fixups() (*Fixups, uint64) {
|
||||
start := mc.fixups.dataoff
|
||||
size := mc.fixups.datasize
|
||||
fixups := new(Fixups)
|
||||
fixups.Deserialize(mc, mc.buf[start:start+size])
|
||||
return fixups, uint64(mc.fixups.dataoff)
|
||||
}
|
||||
|
||||
func (mc *MachoContext) WriteEnabled() bool {
|
||||
return mc.file != nil
|
||||
}
|
||||
|
@ -63,7 +63,8 @@ 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
|
||||
|
||||
# extract symbols from a
|
||||
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --remove-symbol-table $OUT/a
|
||||
# ../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --remove-symbol-table --keep-imports _printf $OUT/a
|
||||
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --keep-imports _printf $OUT/a
|
||||
../../macho-go/bin/ios-wrapper bcell2header -b $OUT/b.bcell -o $OUT/b.h
|
||||
# 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
|
||||
|
Loading…
Reference in New Issue
Block a user