working static strings migration
This commit is contained in:
parent
0640d38627
commit
c241e78cd8
@ -10,6 +10,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"unsafe"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
. "ios-wrapper/pkg/ios"
|
||||
@ -17,6 +19,7 @@ import (
|
||||
)
|
||||
|
||||
// #include "fixups.h"
|
||||
// #include "arm.h"
|
||||
import "C"
|
||||
|
||||
func rewriteLoadcommandsWithoutCodesignature(mc *MachoContext) {
|
||||
@ -342,6 +345,7 @@ func (mc *MachoContext) RemoveBindSymbols() {
|
||||
value := C.MakeRebaseFixupOpcode(C.int(symbol.next), C.ulonglong(target), C.ulonglong(high8))
|
||||
v := make([]byte, 8)
|
||||
mc.byteorder.PutUint64(v, uint64(value))
|
||||
fmt.Printf("change to rebase at %x\n", symbol.file_address)
|
||||
mc.file.WriteAt(v, int64(symbol.file_address))
|
||||
}
|
||||
}
|
||||
@ -582,10 +586,6 @@ func (mc *MachoContext) RemoveStrings() {
|
||||
// their reference down too,
|
||||
// symtab and dysymtab can be ignored, by removing them lmao
|
||||
|
||||
fmt.Println("TODO: Removing strings")
|
||||
|
||||
// identify the cstring region
|
||||
|
||||
var cstring *Section64;
|
||||
for _, command := range mc.commands {
|
||||
switch command.(type) {
|
||||
@ -605,7 +605,6 @@ func (mc *MachoContext) RemoveStrings() {
|
||||
}
|
||||
}
|
||||
|
||||
// no section __cstring in __TEXT
|
||||
if cstring == nil {
|
||||
return
|
||||
}
|
||||
@ -661,7 +660,7 @@ func (mc *MachoContext) RemoveStrings() {
|
||||
// size of the section and segment is defined by the total
|
||||
// space for strings required
|
||||
|
||||
section := Section64{
|
||||
new_cstring_section := Section64{
|
||||
sectname: secname,
|
||||
segname: segname,
|
||||
addr: secstart,
|
||||
@ -686,7 +685,7 @@ func (mc *MachoContext) RemoveStrings() {
|
||||
initprot: 3, // read/write
|
||||
nsects: 1,
|
||||
flags: 0,
|
||||
sections: []*Section64{§ion},
|
||||
sections: []*Section64{&new_cstring_section},
|
||||
}
|
||||
|
||||
// rewrite the header to be correct
|
||||
@ -793,19 +792,88 @@ func (mc *MachoContext) RemoveStrings() {
|
||||
// so we should be very free, because very few program goes this far
|
||||
// but if this happens, god bless you
|
||||
|
||||
// for the demo, we can try to hard code, (addresses are virtual)
|
||||
// text should be in 0x100003f70
|
||||
// string to reference is 0x100008000
|
||||
|
||||
// encoding ADRP is actually hard hmmge?
|
||||
|
||||
// revert to offset
|
||||
mc.file.WriteAt([]byte{0x20, 0x00, 0x00, 0xb0}, int64(0x000003f70))
|
||||
mc.file.WriteAt([]byte{0x00, 0x00, 0x00, 0x91}, int64(0x000003f74))
|
||||
// this part uses file offsets for calculations
|
||||
|
||||
in_cstring := func (offset uint64) bool {
|
||||
cstring_start := uint64(cstring.Offset())
|
||||
cstring_end := cstring_start + cstring.Size()
|
||||
return (offset >= cstring_start) && (offset < cstring_end)
|
||||
}
|
||||
|
||||
text := mc.segments[1]
|
||||
text_start := text.Fileoff()
|
||||
text_end := text_start + text.Filesize()
|
||||
|
||||
inst := make([]byte, 4)
|
||||
for addr := text_start; addr < text_end; addr = addr + 4 {
|
||||
mc.file.ReadAt(inst, int64(addr))
|
||||
inst_adrp := binary.LittleEndian.Uint32(inst)
|
||||
mc.file.ReadAt(inst, int64(addr + 4))
|
||||
inst_add := binary.LittleEndian.Uint32(inst)
|
||||
|
||||
if !(C.is_adrp(C.uint(inst_adrp)) != 0 && C.is_add(C.uint(inst_add)) != 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
base := (addr >> 12) << 12
|
||||
|
||||
// calculate the old string reference
|
||||
ref_base := C.adrp_imm_get(C.uint(inst_adrp))
|
||||
ref_offset := C.add_imm_get(C.uint(inst_add))
|
||||
ref := base + uint64(ref_base + ref_offset)
|
||||
|
||||
if (!in_cstring(ref)) {
|
||||
continue
|
||||
}
|
||||
|
||||
oldstr := uint64(ref)
|
||||
oldstr_relative := oldstr - uint64(cstring.Offset())
|
||||
|
||||
// find the new string address
|
||||
// using oldstr relative address to cstring section
|
||||
newstr := uint64(new_cstring_section.Offset()) + oldstr_relative
|
||||
newstr_base := (newstr >> 12) << 12 // to calculate new offset in adrp
|
||||
newstr_offset := newstr - newstr_base // to calculate new offset in add
|
||||
|
||||
C.adrp_imm_set((*C.uint32_t)(unsafe.Pointer(&inst_adrp)), C.uint(newstr_base - base))
|
||||
C.add_imm_set((*C.uint32_t)(unsafe.Pointer(&inst_add)), C.uint(newstr_offset))
|
||||
|
||||
binary.LittleEndian.PutUint32(inst, inst_adrp)
|
||||
mc.file.WriteAt(inst, int64(addr))
|
||||
binary.LittleEndian.PutUint32(inst, inst_add)
|
||||
mc.file.WriteAt(inst, int64(addr + 4))
|
||||
}
|
||||
|
||||
// modify the rebase table (for both opcode and fixups chain versions)
|
||||
// this is for pointer references
|
||||
|
||||
isModernSymbol := mc.dyldinfo == nil
|
||||
isLegacySymbol := !isModernSymbol
|
||||
for _, symbol := range mc.CollectBindSymbols() {
|
||||
if isLegacySymbol {
|
||||
} else {
|
||||
// (high8 << 56 | target) - mach_header
|
||||
|
||||
ref := uint64(symbol.high8 << 56 | symbol.target)
|
||||
if (!in_cstring(ref)) {
|
||||
continue
|
||||
}
|
||||
|
||||
oldstr := ref
|
||||
oldstr_relative := oldstr - uint64(cstring.Offset())
|
||||
newstr := uint64(new_cstring_section.Offset()) + oldstr_relative
|
||||
|
||||
target := newstr & 0x00FFFFFFFFFFFFFF
|
||||
high8 := newstr >> 56
|
||||
value := C.MakeRebaseFixupOpcode(C.int(symbol.next), C.ulonglong(target), C.ulonglong(high8))
|
||||
v := make([]byte, 8)
|
||||
mc.byteorder.PutUint64(v, uint64(value))
|
||||
fmt.Printf("change to rebase at %x\n", symbol.file_address)
|
||||
mc.file.WriteAt(v, int64(symbol.file_address))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (mc *MachoContext) AddSection(segname string, name string, size int) Section {
|
||||
|
Loading…
Reference in New Issue
Block a user