working static strings migration

This commit is contained in:
nganhkhoa 2024-08-26 16:00:54 +07:00
parent 0640d38627
commit c241e78cd8

View File

@ -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{&section},
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 {