go fmt
This commit is contained in:
parent
9a8ab15d88
commit
41144ff0dc
@ -139,14 +139,14 @@ func (action *saveImports) saveToInfo(mf *MachoFile) error {
|
|||||||
|
|
||||||
mf.Info().Main = mc.Main()
|
mf.Info().Main = mc.Main()
|
||||||
|
|
||||||
selectors_list := []*protomodel.MachoInfo_Selector{}
|
selectors_list := []*protomodel.MachoInfo_Selector{}
|
||||||
for _, sel := range mc.CollectSpecialSelectors() {
|
for _, sel := range mc.CollectSpecialSelectors() {
|
||||||
selectors_list = append(selectors_list, &protomodel.MachoInfo_Selector{
|
selectors_list = append(selectors_list, &protomodel.MachoInfo_Selector{
|
||||||
Idx: uint32(sel.Idx()),
|
Idx: uint32(sel.Idx()),
|
||||||
Name: sel.Name(),
|
Name: sel.Name(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
mf.Info().SpecialSelectors = selectors_list
|
mf.Info().SpecialSelectors = selectors_list
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -302,16 +302,16 @@ func bcell2header(bfile string, header string) {
|
|||||||
|
|
||||||
fmt.Fprintf(w, "__attribute__((section(\"__DATA,bshield\")))\n")
|
fmt.Fprintf(w, "__attribute__((section(\"__DATA,bshield\")))\n")
|
||||||
fmt.Fprintf(w, "uint32_t special_selectors_idx[] = {\n")
|
fmt.Fprintf(w, "uint32_t special_selectors_idx[] = {\n")
|
||||||
for _, selector := range info.GetSpecialSelectors() {
|
for _, selector := range info.GetSpecialSelectors() {
|
||||||
fmt.Fprintf(w, "%x,\n", selector.Idx)
|
fmt.Fprintf(w, "%x,\n", selector.Idx)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "};\n")
|
fmt.Fprintf(w, "};\n")
|
||||||
|
|
||||||
fmt.Fprintf(w, "__attribute__((section(\"__DATA,bshield\")))\n")
|
fmt.Fprintf(w, "__attribute__((section(\"__DATA,bshield\")))\n")
|
||||||
fmt.Fprintf(w, "const char* special_selectors_name[] = {\n")
|
fmt.Fprintf(w, "const char* special_selectors_name[] = {\n")
|
||||||
for _, selector := range info.GetSpecialSelectors() {
|
for _, selector := range info.GetSpecialSelectors() {
|
||||||
fmt.Fprintf(w, "\"%s\",\n", selector.Name)
|
fmt.Fprintf(w, "\"%s\",\n", selector.Name)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "};\n")
|
fmt.Fprintf(w, "};\n")
|
||||||
fmt.Fprintf(w, "uint32_t n_selectors = %d;\n", len(info.GetSpecialSelectors()))
|
fmt.Fprintf(w, "uint32_t n_selectors = %d;\n", len(info.GetSpecialSelectors()))
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func (sym *ImportSymbol) Type() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sym *ImportSymbol) SafeForRemoval() bool {
|
func (sym *ImportSymbol) SafeForRemoval() bool {
|
||||||
return sym.typ == "lazy" || sym.typ == "fixups"
|
return sym.typ == "lazy" || sym.typ == "fixups"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sym *ImportSymbol) Dylib() string {
|
func (sym *ImportSymbol) Dylib() string {
|
||||||
|
@ -280,8 +280,8 @@ func (mc *MachoContext) RemoveBindSymbols() {
|
|||||||
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
isModernSymbol := mc.dyldinfo == nil
|
isModernSymbol := mc.dyldinfo == nil
|
||||||
isLegacySymbol := !isModernSymbol
|
isLegacySymbol := !isModernSymbol
|
||||||
|
|
||||||
if isModernSymbol {
|
if isModernSymbol {
|
||||||
mc.removeBindSymbolsModern()
|
mc.removeBindSymbolsModern()
|
||||||
|
@ -1,27 +1,26 @@
|
|||||||
package macho
|
package macho
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"bytes"
|
||||||
"bytes"
|
"encoding/binary"
|
||||||
"encoding/binary"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
. "ios-wrapper/pkg/ios"
|
. "ios-wrapper/pkg/ios"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type SpecialSelector struct {
|
type SpecialSelector struct {
|
||||||
idx uint
|
idx uint
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sel *SpecialSelector) Idx() uint {
|
func (sel *SpecialSelector) Idx() uint {
|
||||||
return sel.idx
|
return sel.idx
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sel *SpecialSelector) Name() string {
|
func (sel *SpecialSelector) Name() string {
|
||||||
return sel.name
|
return sel.name
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect the index and the name in selector list of special method names
|
// collect the index and the name in selector list of special method names
|
||||||
@ -33,9 +32,9 @@ func (sel *SpecialSelector) Name() string {
|
|||||||
// - retain
|
// - retain
|
||||||
func (mc *MachoContext) CollectSpecialSelectors() []*SpecialSelector {
|
func (mc *MachoContext) CollectSpecialSelectors() []*SpecialSelector {
|
||||||
|
|
||||||
var special_selectors []*SpecialSelector
|
var special_selectors []*SpecialSelector
|
||||||
var methods []byte
|
var methods []byte
|
||||||
var methname_offset uint32
|
var methname_offset uint32
|
||||||
|
|
||||||
for _, cmd := range mc.commands {
|
for _, cmd := range mc.commands {
|
||||||
if cmd.Cmd() == LC_MAIN {
|
if cmd.Cmd() == LC_MAIN {
|
||||||
@ -49,50 +48,50 @@ func (mc *MachoContext) CollectSpecialSelectors() []*SpecialSelector {
|
|||||||
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__TEXT")) == 0 {
|
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__TEXT")) == 0 {
|
||||||
for _, section := range segment.Sections() {
|
for _, section := range segment.Sections() {
|
||||||
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_methname")) == 0 {
|
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_methname")) == 0 {
|
||||||
methname_offset = section.Offset()
|
methname_offset = section.Offset()
|
||||||
methods = make([]byte, section.Size())
|
methods = make([]byte, section.Size())
|
||||||
mc.file.ReadAt(methods, int64(section.Offset()))
|
mc.file.ReadAt(methods, int64(section.Offset()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 {
|
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 {
|
||||||
for _, section := range segment.Sections() {
|
for _, section := range segment.Sections() {
|
||||||
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_selrefs")) == 0 {
|
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_selrefs")) == 0 {
|
||||||
selectors_buffer := make([]byte, section.Size())
|
selectors_buffer := make([]byte, section.Size())
|
||||||
mc.file.ReadAt(selectors_buffer, int64(section.Offset()))
|
mc.file.ReadAt(selectors_buffer, int64(section.Offset()))
|
||||||
|
|
||||||
buffer := bytes.NewReader(selectors_buffer)
|
buffer := bytes.NewReader(selectors_buffer)
|
||||||
|
|
||||||
for i := uint(0); i < uint(section.Size()) / 8; i++ {
|
for i := uint(0); i < uint(section.Size())/8; i++ {
|
||||||
// this field is actually a Rebase
|
// this field is actually a Rebase
|
||||||
// we assume that no rebase is needed
|
// we assume that no rebase is needed
|
||||||
// so everything sticks to its file offset
|
// so everything sticks to its file offset
|
||||||
var offset uint32
|
var offset uint32
|
||||||
binary.Read(buffer, mc.byteorder, &offset) // first 4 bytes is offset
|
binary.Read(buffer, mc.byteorder, &offset) // first 4 bytes is offset
|
||||||
|
|
||||||
var name_builder strings.Builder
|
var name_builder strings.Builder
|
||||||
for j := uint32(0); ; j++ {
|
for j := uint32(0); ; j++ {
|
||||||
c := methods[offset - methname_offset + j]
|
c := methods[offset-methname_offset+j]
|
||||||
if c == 0 {
|
if c == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
name_builder.WriteByte(c)
|
name_builder.WriteByte(c)
|
||||||
}
|
}
|
||||||
name := name_builder.String()
|
name := name_builder.String()
|
||||||
if name == "load" {
|
if name == "load" {
|
||||||
special_selectors = append(special_selectors, &SpecialSelector{
|
special_selectors = append(special_selectors, &SpecialSelector{
|
||||||
idx: i,
|
idx: i,
|
||||||
name: name,
|
name: name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
binary.Read(buffer, mc.byteorder, &offset) // ignore rebase arguments
|
binary.Read(buffer, mc.byteorder, &offset) // ignore rebase arguments
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return special_selectors
|
return special_selectors
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MachoContext) ReworkForObjc() {
|
func (mc *MachoContext) ReworkForObjc() {
|
||||||
@ -131,14 +130,14 @@ func (mc *MachoContext) ReworkForObjc() {
|
|||||||
mc.file.WriteAt([]byte{0, 0, 0, 0}, section_ptr+0x40)
|
mc.file.WriteAt([]byte{0, 0, 0, 0}, section_ptr+0x40)
|
||||||
}
|
}
|
||||||
|
|
||||||
// erases all objc method names
|
// erases all objc method names
|
||||||
// this should still works because the cache inserts the pointer value not string
|
// this should still works because the cache inserts the pointer value not string
|
||||||
// but some symbols relies on pre-defined implementations, such as **load** method
|
// but some symbols relies on pre-defined implementations, such as **load** method
|
||||||
// load method is the same across all classes and so objc define an implementation
|
// load method is the same across all classes and so objc define an implementation
|
||||||
// selector should points to this load selector to make objc thinks that it's "load"
|
// selector should points to this load selector to make objc thinks that it's "load"
|
||||||
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_methname")) == 0 {
|
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_methname")) == 0 {
|
||||||
// mc.file.WriteAt([]byte("__objc_methbruh"), section_ptr)
|
// mc.file.WriteAt([]byte("__objc_methbruh"), section_ptr)
|
||||||
mc.file.WriteAt(make([]byte, section.Size()), int64(section.Offset()))
|
mc.file.WriteAt(make([]byte, section.Size()), int64(section.Offset()))
|
||||||
}
|
}
|
||||||
section_ptr += 16*2 + 8*2 + 4*8
|
section_ptr += 16*2 + 8*2 + 4*8
|
||||||
}
|
}
|
||||||
@ -167,7 +166,7 @@ func (mc *MachoContext) ReworkForObjc() {
|
|||||||
last := sections[len(sections)-1]
|
last := sections[len(sections)-1]
|
||||||
data_end = int(last.Addr() - segment.Vmaddr() + segment.Fileoff() + last.Size())
|
data_end = int(last.Addr() - segment.Vmaddr() + segment.Fileoff() + last.Size())
|
||||||
|
|
||||||
// do not register selector and see what happens
|
// do not register selector and see what happens
|
||||||
section_ptr := ptr + 0x40 + 8
|
section_ptr := ptr + 0x40 + 8
|
||||||
for _, section := range segment.Sections() {
|
for _, section := range segment.Sections() {
|
||||||
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_selrefs")) == 0 {
|
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_selrefs")) == 0 {
|
||||||
@ -196,24 +195,24 @@ func (mc *MachoContext) ReworkForObjc() {
|
|||||||
// must recover stack to same value before calling main
|
// must recover stack to same value before calling main
|
||||||
// must recover link register before calling main
|
// must recover link register before calling main
|
||||||
|
|
||||||
// ┌─────────────────┐
|
// ┌─────────────────┐
|
||||||
// │ │
|
// │ │
|
||||||
// shellcode starts ────┼─────────────────┼───── │ │instruction
|
// shellcode starts ────┼─────────────────┼───── │ │instruction
|
||||||
// │ │ │ │fetch RIP size
|
// │ │ │ │fetch RIP size
|
||||||
// RIP returns ────┼─────────────────┼───── ▲ │ │
|
// RIP returns ────┼─────────────────┼───── ▲ │ │
|
||||||
// │ │ │ │
|
// │ │ │ │
|
||||||
// │ │ │ │ shellcode length
|
// │ │ │ │ shellcode length
|
||||||
// shellcode ends │ │ │ offset │
|
// shellcode ends │ │ │ offset │
|
||||||
// __text ────┼─────────────────┼───── │ range │
|
// __text ────┼─────────────────┼───── │ range │
|
||||||
// │ │ │ │ __DATA ends - __text
|
// │ │ │ │ __DATA ends - __text
|
||||||
// │ │ │ │
|
// │ │ │ │
|
||||||
// __DATA ends ────┼─────────────────┼───── ▼ │
|
// __DATA ends ────┼─────────────────┼───── ▼ │
|
||||||
// │ │
|
// │ │
|
||||||
// │ │
|
// │ │
|
||||||
// │ │
|
// │ │
|
||||||
// │ │
|
// │ │
|
||||||
// │ │
|
// │ │
|
||||||
// └─────────────────┘
|
// └─────────────────┘
|
||||||
|
|
||||||
shellcode := []uint32{}
|
shellcode := []uint32{}
|
||||||
ins_size_byte := 4
|
ins_size_byte := 4
|
||||||
@ -223,32 +222,32 @@ func (mc *MachoContext) ReworkForObjc() {
|
|||||||
isArm := (mc.header.cputype & 0xff) == 12
|
isArm := (mc.header.cputype & 0xff) == 12
|
||||||
if isArm {
|
if isArm {
|
||||||
|
|
||||||
// we use shorthand store/load multiple
|
// we use shorthand store/load multiple
|
||||||
// arm also has different indexing instruction, so be careful
|
// arm also has different indexing instruction, so be careful
|
||||||
// https://developer.arm.com/documentation/102374/0101/Loads-and-stores---addressing
|
// https://developer.arm.com/documentation/102374/0101/Loads-and-stores---addressing
|
||||||
/*
|
/*
|
||||||
adr x8, 0
|
adr x8, 0
|
||||||
# x9 = (offset end of __DATA) - (offset shellcode)
|
# x9 = (offset end of __DATA) - (offset shellcode)
|
||||||
movz x9, #0x9999
|
movz x9, #0x9999
|
||||||
add x8, x8, x9
|
add x8, x8, x9
|
||||||
|
|
||||||
stp x30, x8, [sp], #-0x10
|
stp x30, x8, [sp], #-0x10
|
||||||
stp x3, x2, [sp], #-0x10
|
stp x3, x2, [sp], #-0x10
|
||||||
stp x1, x0, [sp], #-0x10
|
stp x1, x0, [sp], #-0x10
|
||||||
|
|
||||||
# custom intializer
|
# custom intializer
|
||||||
ldr x9, [x8]
|
ldr x9, [x8]
|
||||||
blr x9
|
blr x9
|
||||||
|
|
||||||
ldp x1, x0, [sp, #0x10]!
|
ldp x1, x0, [sp, #0x10]!
|
||||||
ldp x3, x2, [sp, #0x10]!
|
ldp x3, x2, [sp, #0x10]!
|
||||||
ldp x30, x8, [sp, #0x10]!
|
ldp x30, x8, [sp, #0x10]!
|
||||||
|
|
||||||
# original main
|
# original main
|
||||||
# link register is set so jump only
|
# link register is set so jump only
|
||||||
ldr x9, [x8, #8]
|
ldr x9, [x8, #8]
|
||||||
br x9
|
br x9
|
||||||
*/
|
*/
|
||||||
shellcode = []uint32{
|
shellcode = []uint32{
|
||||||
0x10000008,
|
0x10000008,
|
||||||
0, // x9 = (offset end of __DATA) - (offset shellcode)
|
0, // x9 = (offset end of __DATA) - (offset shellcode)
|
||||||
@ -362,4 +361,3 @@ func (mc *MachoContext) ReworkForObjc() {
|
|||||||
offset += 4
|
offset += 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user