mirror of
https://github.com/lukaszraczylo/go-obfuscation.git
synced 2026-10-16 06:07:50 +00:00
.
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
//go:build darwin
|
||||
|
||||
package pclntab
|
||||
|
||||
import (
|
||||
"debug/macho"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func runtimeCorrupt(binaryPath string, key byte) error {
|
||||
self, err := os.ReadFile(binaryPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pclntab: cannot read binary: %w", err)
|
||||
}
|
||||
|
||||
f, err := macho.NewFile(bytesReader(self))
|
||||
if err != nil {
|
||||
return fmt.Errorf("pclntab: cannot parse Mach-O from memory: %w", err)
|
||||
}
|
||||
|
||||
sectionData, sectionAddr, sectionSize, err := findPclntabMacho(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nameStart, nameEnd := findMemoryNameRegion(sectionData)
|
||||
if nameStart == 0 || nameEnd <= nameStart {
|
||||
return fmt.Errorf("pclntab: could not locate name region")
|
||||
}
|
||||
|
||||
pageSize := syscall.Getpagesize()
|
||||
baseAddr := sectionAddr &^ uintptr(pageSize-1)
|
||||
protSize := sectionSize + (sectionAddr - baseAddr)
|
||||
|
||||
if err := mprotectRW(baseAddr, protSize); err != nil {
|
||||
return fmt.Errorf("pclntab: mprotect failed: %w", err)
|
||||
}
|
||||
|
||||
nameSlice := ptrToSlice(sectionAddr+uintptr(nameStart), uintptr(nameEnd-nameStart))
|
||||
for i := range nameSlice {
|
||||
if nameSlice[i] != 0 {
|
||||
nameSlice[i] ^= key
|
||||
}
|
||||
}
|
||||
|
||||
mprotectRO(baseAddr, protSize)
|
||||
return nil
|
||||
}
|
||||
|
||||
func findPclntabMacho(f *macho.File) ([]byte, uintptr, uintptr, error) {
|
||||
sectionNames := []string{
|
||||
"__gopclntab",
|
||||
"__pclntab",
|
||||
}
|
||||
|
||||
for _, sec := range f.Sections {
|
||||
for _, name := range sectionNames {
|
||||
if sec.Name == name {
|
||||
data, err := sec.Data()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
buf := make([]byte, len(data))
|
||||
copy(buf, data)
|
||||
return buf, uintptr(sec.Addr), uintptr(sec.Size), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, sec := range f.Sections {
|
||||
data, err := sec.Data()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if len(data) >= 8 {
|
||||
for _, magic := range pclntabMagics {
|
||||
if len(data) >= len(magic) && bytesEqual(data[:len(magic)], magic) {
|
||||
buf := make([]byte, len(data))
|
||||
copy(buf, data)
|
||||
return buf, uintptr(sec.Addr), uintptr(sec.Size), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, 0, 0, fmt.Errorf("pclntab: __gopclntab section not found in memory")
|
||||
}
|
||||
|
||||
func findMemoryNameRegion(data []byte) (uint32, uint32) {
|
||||
tab := &pclntabParser{data: data}
|
||||
if err := tab.parse(); err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
return findNameRegion(tab)
|
||||
}
|
||||
|
||||
type bytesReaderWrapper struct {
|
||||
data []byte
|
||||
}
|
||||
|
||||
func bytesReader(data []byte) *bytesReaderWrapper {
|
||||
return &bytesReaderWrapper{data: data}
|
||||
}
|
||||
|
||||
func (r *bytesReaderWrapper) ReadAt(p []byte, off int64) (int, error) {
|
||||
if off < 0 || int(off) >= len(r.data) {
|
||||
return 0, fmt.Errorf("invalid offset")
|
||||
}
|
||||
n := copy(p, r.data[int(off):])
|
||||
if n < len(p) {
|
||||
return n, fmt.Errorf("EOF")
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
Reference in New Issue
Block a user