diff --git a/macho-go/pkg/ios/macho/edit.go b/macho-go/pkg/ios/macho/edit.go index 7e84b6c..a6f810f 100644 --- a/macho-go/pkg/ios/macho/edit.go +++ b/macho-go/pkg/ios/macho/edit.go @@ -282,7 +282,7 @@ func (mc *MachoContext) RemoveBindSymbols() { } else { mc.removeBindSymbolsLegacy() } - mc.RenameObjcClasslist() + mc.ReworkForObjc() // due to some limitations when design this tool // we write the c code to stdout lol @@ -353,7 +353,9 @@ func (mc *MachoContext) removeBindSymbolsLegacy() { mc.file.WriteAt(make([]byte, size), int64(start)) } -func (mc *MachoContext) RenameObjcClasslist() { +func (mc *MachoContext) ReworkForObjc() { + text_start := 0 + ptr := int64(0) if mc.Is64bit() { ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart) @@ -368,6 +370,14 @@ func (mc *MachoContext) RenameObjcClasslist() { } var segment = cmd.(*Segment64) + if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__TEXT")) == 0 { + for _, section := range segment.Sections() { + if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__text")) == 0 { + text_start = int(section.Offset()) + break + } + } + } if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA_CONST")) == 0 { section_ptr := ptr + 0x40 + 8 for _, section := range segment.Sections() { @@ -380,15 +390,86 @@ func (mc *MachoContext) RenameObjcClasslist() { section_ptr += 16 * 2 + 8 * 2 + 4 * 8 } } - // if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 { - // section_ptr := ptr + 0x40 + 8 - // for _, section := range segment.Sections() { - // section_ptr += 16 * 2 + 8 * 2 + 4 * 8 - // } - // } + if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 { + // section_ptr := ptr + 0x40 + 8 + // for _, section := range segment.Sections() { + // section_ptr += 16 * 2 + 8 * 2 + 4 * 8 + // } + // end of __DATA segment, should have enough space for a pointer + } ptr += int64(cmd.Cmdsize()) } mc.file.Seek(0, io.SeekStart) + + // dummy value past the end of __DATA segment (logical size), + // its physical size is still a page + // mc.file.WriteAt([]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}, int64(0x81d8)) + + ins_size_byte := 4 + x8_value_offset := text_start - (ins_size_byte * 17) + (ins_size_byte * 2) + main_offset := mc.entryoff + + movz_x8_value_offset := uint32(uint32(x8_value_offset)<<5 | uint32(0x694)<<21 | uint32(0x09)) + movz_main_offset := uint32(uint32(main_offset)<<5 | uint32(0x694)<<21 | uint32(0x09)) + + fmt.Printf("// x8_value_offset=%x\n", x8_value_offset) + fmt.Printf("// main_offset=%x\n", main_offset) + fmt.Printf("// x8_value_offset=%x\n", movz_x8_value_offset) + fmt.Printf("// main_offset=%x\n", movz_main_offset) + + // sub sp, sp, #0x10 + // str x30, [sp] + // adr x8, 0 + // movz x9, #0x3d68 ; offset at this point + // sub x8, x8, x9 + // str x8, [sp, #8] + // movz x9, #0x81d8 + // add x9, x8, x9 + // ldr x9, [x9] + // blr x9 + // ldr x8, [sp, #8] + // movz x9, #0x3e3c ; offset to original main + // add x9, x8, x9 + // blr x9 + // ldr x30, [sp] + // add sp, sp, #0x10 + // ret + + // TODO: fix to work with offset larger than 0xffff + shellcode := []uint32{ + 0xD10043FF, + 0xF90003FE, + 0x10000008, + movz_x8_value_offset, + 0xCB090108, + 0xF90007E8, + 0xD2903B09, + 0x8B090109, + 0xF9400129, + 0xD63F0120, + 0xF94007E8, + movz_main_offset, + 0x8B090109, + 0xD63F0120, + 0xF94003FE, + 0x910043FF, + 0xD65F03C0, + } + + offset := int64(0x3da4 - len(shellcode) * 4) + { + // fix main to point to our newly created shellcode + bs := make([]byte, 8) + mc.byteorder.PutUint64(bs, uint64(offset)) + mc.file.WriteAt(bs, int64(0x870)) + } + + bs := make([]byte, 4) + for _, ins := range shellcode { + mc.byteorder.PutUint32(bs, ins) + mc.file.WriteAt(bs, offset) + offset += 4 + } }