add selfbind functionality

This commit is contained in:
2023-07-12 13:34:02 +07:00
parent 6815ea6556
commit 4ee62a2d93
4 changed files with 305 additions and 88 deletions

View File

@ -7,9 +7,11 @@ import (
"math/rand"
"time"
"strings"
"encoding/binary"
log "github.com/sirupsen/logrus"
"ios-wrapper/pkg/protomodel"
. "ios-wrapper/pkg/ios"
)
@ -681,3 +683,130 @@ func (mc *MachoContext) RemoveExportTrie() {
// should never occur unless this binary is modified
}
}
func (mc *MachoContext) AddSection(segname string, name string, size int) Section {
// mc.file.WriteAt(mc.header.Serialize(mc), 0)
var ret Section
var buffer bytes.Buffer
for _, command := range mc.commands {
switch command.(type) {
case *Segment64:
var virtualAddr uint64
var fileOffset uint64
var segment = command.(*Segment64)
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte(segname)) != 0 {
buffer.Write(segment.Serialize(mc))
continue
} else {
virtualAddr = segment.Vmaddr()
fileOffset = segment.Fileoff()
for _, section := range segment.Sections() {
virtualAddr += section.Size()
// if section.Offset() != 0 {
fileOffset += section.Size()
// }
}
align := uint64(4)
alignment := align - (fileOffset % align)
fileOffset += alignment
virtualAddr += alignment
enoughSpace := segment.Fileoff() + segment.Filesize() >= fileOffset + uint64(size)
if !enoughSpace {
fmt.Println("Not enough space to store saved info in __DATA segment, need resize (not supported now)")
panic("Not enough space to store saved info in __DATA segment, need resize (not supported now)")
}
}
var section Section64
section.sectname = make([]byte, 16)
copy(section.sectname, name)
section.segname = make([]byte, 16)
copy(section.segname, segname)
section.size = uint64(size)
section.reloff = 0
section.nreloc = 0
section.flags = 0
section.align = 3
section.reserved1 = 0
section.reserved2 = 0
section.reserved3 = 0
// addr will increment from the last section
// offset will increment from the last section + size
// be careful of Virtual section (bss)
section.addr = virtualAddr
section.offset = uint32(fileOffset)
segment.nsects += 1
buffer.Write(segment.Serialize(mc))
buffer.Write(section.Serialize(mc))
fmt.Printf("Add a new section with addr=0x%x, fileoffset=0x%x\n", section.addr, section.offset)
ret = &section
continue
default:
buffer.Write(command.Serialize(mc))
continue
}
}
mc.header.sizeofcmds = uint32(buffer.Len())
header := mc.header.Serialize(mc)
mc.file.WriteAt(header, 0)
mc.file.WriteAt(buffer.Bytes(), int64(len(header)))
return ret
}
func (mc *MachoContext) WriteInfoToData(info *protomodel.MachoInfo) {
encode := func () []byte {
buffer := new(bytes.Buffer)
for _, table := range info.Symbols.Tables {
binary.Write(buffer, mc.byteorder, table.LibIndex)
binary.Write(buffer, mc.byteorder, table.Nsymbols)
for _, symbol := range table.Symbols {
binary.Write(buffer, mc.byteorder, (symbol.SymbolIndex<<8)|symbol.SegmentIndex)
binary.Write(buffer, mc.byteorder, symbol.Offset)
}
}
instructions := buffer.Bytes()
buffer = new(bytes.Buffer)
for _, lib := range info.Symbols.Libs {
buffer.WriteString(lib)
buffer.WriteByte(0)
}
liblist := buffer.Bytes()
buffer = new(bytes.Buffer)
for _, symbol := range info.Symbols.Symbols {
buffer.WriteString(symbol)
buffer.WriteByte(0)
}
symbollist := buffer.Bytes()
buffer = new(bytes.Buffer)
// offset to liblist
binary.Write(buffer, mc.byteorder, uint32(len(instructions)))
// offset to symbollist
binary.Write(buffer, mc.byteorder, uint32(len(instructions) + len(liblist)))
buffer.Write(instructions)
buffer.Write(liblist)
buffer.Write(symbollist)
return buffer.Bytes()
}
encoded := encode()
// encoded := []byte{0x11,0x22,0x33, 0x44}
section := mc.AddSection("__DATA", "selfbind", len(encoded))
if mc.Is64bit() {
var s *Section64 = section.(*Section64)
mc.file.WriteAt(encoded, int64(s.Offset()))
} else {
var s *Section32 = section.(*Section32)
mc.file.WriteAt(encoded, int64(s.Offset()))
}
}