fix fixups chain rewrite stops at first entry
This commit is contained in:
parent
1b7da037bb
commit
88bb0aa09d
@ -29,6 +29,8 @@ type ImportSymbol struct {
|
||||
// push number
|
||||
pnum uint32
|
||||
stub uint64
|
||||
|
||||
next int // only for LC_DYLD_CHAINED_FIXUPS
|
||||
}
|
||||
|
||||
func (sym *ImportSymbol) Name() string {
|
||||
@ -120,7 +122,7 @@ func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
||||
|
||||
for {
|
||||
mc.file.Read(code)
|
||||
v := binary.LittleEndian.Uint64(code)
|
||||
v := mc.byteorder.Uint64(code)
|
||||
|
||||
var bind C.int
|
||||
var ret1 C.ulonglong
|
||||
@ -133,7 +135,7 @@ func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
||||
name := C.GoString(s.name)
|
||||
dylib := string(mc.dylibs[int(s.lib_ordinal)-1].name[:])
|
||||
|
||||
// fmt.Printf("%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.name = name
|
||||
@ -142,14 +144,19 @@ func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
||||
|
||||
sym.segment = uint32(mc.findSegmentIndexAt(uint64(address)))
|
||||
sym.file_address = uint64(address)
|
||||
sym.next = int(next)
|
||||
new_sym := sym
|
||||
syms = append(syms, &new_sym)
|
||||
} else {
|
||||
fmt.Printf("// 0x%x rebase=%d target=0x%x high8=0x%x\n", address, bind, ret1, ret2)
|
||||
}
|
||||
|
||||
address += 8
|
||||
if int(next) == 0 {
|
||||
break
|
||||
}
|
||||
// because the pointer move up 8 bytes already so we minus 8
|
||||
mc.file.Seek(int64(next * 4) - 8, io.SeekCurrent)
|
||||
}
|
||||
mc.file.Seek(0, io.SeekStart)
|
||||
}
|
||||
|
@ -3,12 +3,17 @@ package macho
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
. "ios-wrapper/pkg/ios"
|
||||
)
|
||||
|
||||
// #include "fixups.h"
|
||||
import "C"
|
||||
|
||||
func rewriteLoadcommandsWithoutCodesignature(mc *MachoContext) {
|
||||
if mc.Is64bit() {
|
||||
mc.file.Seek(int64(Header_size_64), io.SeekStart)
|
||||
@ -273,6 +278,8 @@ func (mc *MachoContext) RemoveBindSymbols() {
|
||||
return
|
||||
}
|
||||
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
if mc.dyldinfo == nil {
|
||||
mc.removeBindSymbolsModern()
|
||||
} else {
|
||||
@ -291,6 +298,7 @@ func (mc *MachoContext) RemoveBindSymbols() {
|
||||
// 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; 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() {
|
||||
@ -313,7 +321,28 @@ func (mc *MachoContext) RemoveBindSymbols() {
|
||||
|
||||
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
|
||||
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.segment, offset);
|
||||
if mc.dyldinfo != nil {
|
||||
// for legacy resolve the opcodes can be rewritten as 0x00
|
||||
mc.file.WriteAt(make([]byte, 8), int64(symbol.file_address))
|
||||
} else {
|
||||
// for modern resolve the opcodes must not be rewritten as 0x00
|
||||
// because it contains 2 types of opcodes, BIND and REBASE
|
||||
// we only fix BIND and leave REBASE intact
|
||||
// However, each opcodes has a *next* field to the next opcode
|
||||
// So if we want to leave the header intact (contains pointers, size)
|
||||
// We should rewrite this as REBASE opcode (so no symbol lookup happens)
|
||||
// and it can continue
|
||||
|
||||
// we can write random values, because the loader just do
|
||||
// (high8 << 56 | target) - mach_header
|
||||
// or something, so no symbol lookup and no error at runtime
|
||||
target := rand.Int()
|
||||
high8 := rand.Int()
|
||||
value := C.MakeRebaseFixupOpcode(C.int(symbol.next), C.ulonglong(target), C.ulonglong(high8))
|
||||
v := make([]byte, 8)
|
||||
mc.byteorder.PutUint64(v, uint64(value))
|
||||
mc.file.WriteAt(v, int64(symbol.file_address))
|
||||
}
|
||||
}
|
||||
fmt.Println("};")
|
||||
fmt.Printf("uint32_t nimports = %d;\n", count);
|
||||
|
@ -94,6 +94,15 @@ 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 value;
|
||||
struct dyld_chained_ptr_64_rebase* b = (struct dyld_chained_ptr_64_rebase*)&value;
|
||||
b->next = next;
|
||||
b->target = target;
|
||||
b->high8 = high8;
|
||||
return value;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -30,4 +30,5 @@ struct ImportTable GetImportsTable(uint8_t* header_ptr);
|
||||
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);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user