working static strings migration
This commit is contained in:
parent
0640d38627
commit
c241e78cd8
@ -10,6 +10,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
. "ios-wrapper/pkg/ios"
|
. "ios-wrapper/pkg/ios"
|
||||||
@ -17,6 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// #include "fixups.h"
|
// #include "fixups.h"
|
||||||
|
// #include "arm.h"
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
func rewriteLoadcommandsWithoutCodesignature(mc *MachoContext) {
|
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))
|
value := C.MakeRebaseFixupOpcode(C.int(symbol.next), C.ulonglong(target), C.ulonglong(high8))
|
||||||
v := make([]byte, 8)
|
v := make([]byte, 8)
|
||||||
mc.byteorder.PutUint64(v, uint64(value))
|
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))
|
mc.file.WriteAt(v, int64(symbol.file_address))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -582,10 +586,6 @@ func (mc *MachoContext) RemoveStrings() {
|
|||||||
// their reference down too,
|
// their reference down too,
|
||||||
// symtab and dysymtab can be ignored, by removing them lmao
|
// symtab and dysymtab can be ignored, by removing them lmao
|
||||||
|
|
||||||
fmt.Println("TODO: Removing strings")
|
|
||||||
|
|
||||||
// identify the cstring region
|
|
||||||
|
|
||||||
var cstring *Section64;
|
var cstring *Section64;
|
||||||
for _, command := range mc.commands {
|
for _, command := range mc.commands {
|
||||||
switch command.(type) {
|
switch command.(type) {
|
||||||
@ -605,7 +605,6 @@ func (mc *MachoContext) RemoveStrings() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no section __cstring in __TEXT
|
|
||||||
if cstring == nil {
|
if cstring == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -661,7 +660,7 @@ func (mc *MachoContext) RemoveStrings() {
|
|||||||
// size of the section and segment is defined by the total
|
// size of the section and segment is defined by the total
|
||||||
// space for strings required
|
// space for strings required
|
||||||
|
|
||||||
section := Section64{
|
new_cstring_section := Section64{
|
||||||
sectname: secname,
|
sectname: secname,
|
||||||
segname: segname,
|
segname: segname,
|
||||||
addr: secstart,
|
addr: secstart,
|
||||||
@ -686,7 +685,7 @@ func (mc *MachoContext) RemoveStrings() {
|
|||||||
initprot: 3, // read/write
|
initprot: 3, // read/write
|
||||||
nsects: 1,
|
nsects: 1,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
sections: []*Section64{§ion},
|
sections: []*Section64{&new_cstring_section},
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewrite the header to be correct
|
// 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
|
// so we should be very free, because very few program goes this far
|
||||||
// but if this happens, god bless you
|
// 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?
|
// encoding ADRP is actually hard hmmge?
|
||||||
|
|
||||||
// revert to offset
|
// this part uses file offsets for calculations
|
||||||
mc.file.WriteAt([]byte{0x20, 0x00, 0x00, 0xb0}, int64(0x000003f70))
|
|
||||||
mc.file.WriteAt([]byte{0x00, 0x00, 0x00, 0x91}, int64(0x000003f74))
|
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)
|
// modify the rebase table (for both opcode and fixups chain versions)
|
||||||
// this is for pointer references
|
// 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 {
|
func (mc *MachoContext) AddSection(segname string, name string, size int) Section {
|
||||||
|
Loading…
Reference in New Issue
Block a user