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
|
// push number
|
||||||
pnum uint32
|
pnum uint32
|
||||||
stub uint64
|
stub uint64
|
||||||
|
|
||||||
|
next int // only for LC_DYLD_CHAINED_FIXUPS
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sym *ImportSymbol) Name() string {
|
func (sym *ImportSymbol) Name() string {
|
||||||
@ -120,7 +122,7 @@ func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
mc.file.Read(code)
|
mc.file.Read(code)
|
||||||
v := binary.LittleEndian.Uint64(code)
|
v := mc.byteorder.Uint64(code)
|
||||||
|
|
||||||
var bind C.int
|
var bind C.int
|
||||||
var ret1 C.ulonglong
|
var ret1 C.ulonglong
|
||||||
@ -133,7 +135,7 @@ func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
|||||||
name := C.GoString(s.name)
|
name := C.GoString(s.name)
|
||||||
dylib := string(mc.dylibs[int(s.lib_ordinal)-1].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.address = uint64(address)
|
||||||
sym.name = name
|
sym.name = name
|
||||||
@ -142,14 +144,19 @@ func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
|||||||
|
|
||||||
sym.segment = uint32(mc.findSegmentIndexAt(uint64(address)))
|
sym.segment = uint32(mc.findSegmentIndexAt(uint64(address)))
|
||||||
sym.file_address = uint64(address)
|
sym.file_address = uint64(address)
|
||||||
|
sym.next = int(next)
|
||||||
new_sym := sym
|
new_sym := sym
|
||||||
syms = append(syms, &new_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
|
address += 8
|
||||||
if int(next) == 0 {
|
if int(next) == 0 {
|
||||||
break
|
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)
|
mc.file.Seek(0, io.SeekStart)
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,17 @@ package macho
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
. "ios-wrapper/pkg/ios"
|
. "ios-wrapper/pkg/ios"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// #include "fixups.h"
|
||||||
|
import "C"
|
||||||
|
|
||||||
func rewriteLoadcommandsWithoutCodesignature(mc *MachoContext) {
|
func rewriteLoadcommandsWithoutCodesignature(mc *MachoContext) {
|
||||||
if mc.Is64bit() {
|
if mc.Is64bit() {
|
||||||
mc.file.Seek(int64(Header_size_64), io.SeekStart)
|
mc.file.Seek(int64(Header_size_64), io.SeekStart)
|
||||||
@ -273,6 +278,8 @@ func (mc *MachoContext) RemoveBindSymbols() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
if mc.dyldinfo == nil {
|
if mc.dyldinfo == nil {
|
||||||
mc.removeBindSymbolsModern()
|
mc.removeBindSymbolsModern()
|
||||||
} else {
|
} else {
|
||||||
@ -291,6 +298,7 @@ func (mc *MachoContext) RemoveBindSymbols() {
|
|||||||
// 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("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[] = {")
|
fmt.Println("struct imported_symbol imported_table[] = {")
|
||||||
count := 0
|
count := 0
|
||||||
for _, symbol := range mc.CollectBindSymbols() {
|
for _, symbol := range mc.CollectBindSymbols() {
|
||||||
@ -313,7 +321,28 @@ func (mc *MachoContext) RemoveBindSymbols() {
|
|||||||
|
|
||||||
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
|
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
|
||||||
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.segment, offset);
|
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.segment, offset);
|
||||||
mc.file.WriteAt(make([]byte, 8), int64(symbol.file_address))
|
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.Println("};")
|
||||||
fmt.Printf("uint32_t nimports = %d;\n", count);
|
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) {
|
void ParseFixUps(uint8_t* buffer) {
|
||||||
struct dyld_chained_fixups_header* header = (struct dyld_chained_fixups_header*)buffer;
|
struct dyld_chained_fixups_header* header = (struct dyld_chained_fixups_header*)buffer;
|
||||||
printf("starts=0x%x\n", header->starts_offset);
|
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);
|
struct ImportSymbol GetImportsAt(struct ImportTable* table, int i);
|
||||||
int GetSegmentFixAt(uint8_t* buffer, uint32_t i, struct SegmentFix* fix);
|
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);
|
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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user