mirror of
https://github.com/lukaszraczylo/go-obfuscation.git
synced 2026-10-12 05:32:33 +00:00
196 lines
4.7 KiB
Go
196 lines
4.7 KiB
Go
//go:build windows
|
|
|
|
package syscallobf
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"sync"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
var (
|
|
modntdll = syscall.NewLazyDLL("ntdll.dll")
|
|
|
|
procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess")
|
|
procNtSetInformationThread = modntdll.NewProc("NtSetInformationThread")
|
|
procNtClose = modntdll.NewProc("NtClose")
|
|
procNtProtectVirtualMemory = modntdll.NewProc("NtProtectVirtualMemory")
|
|
procNtReadVirtualMemory = modntdll.NewProc("NtReadVirtualMemory")
|
|
procNtOpenProcess = modntdll.NewProc("NtOpenProcess")
|
|
|
|
obfPtraceTrap ObfuscatedCall
|
|
obfGetpidTrap ObfuscatedCall
|
|
obfKillTrap ObfuscatedCall
|
|
obfOpenTrap ObfuscatedCall
|
|
obfCloseTrap ObfuscatedCall
|
|
obfReadTrap ObfuscatedCall
|
|
obfLseekTrap ObfuscatedCall
|
|
obfMmapTrap ObfuscatedCall
|
|
obfMprotectTrap ObfuscatedCall
|
|
)
|
|
|
|
func init() {
|
|
var key [4]byte
|
|
if _, err := rand.Read(key[:]); err != nil {
|
|
panic("syscallobf: failed to generate random key: " + err.Error())
|
|
}
|
|
|
|
obfCloseTrap = encode(0, key)
|
|
obfReadTrap = encode(0, key)
|
|
obfOpenTrap = encode(0, key)
|
|
obfLseekTrap = encode(0, key)
|
|
obfMmapTrap = encode(0, key)
|
|
obfMprotectTrap = encode(0, key)
|
|
obfPtraceTrap = encode(0, key)
|
|
obfGetpidTrap = encode(0, key)
|
|
obfKillTrap = encode(0, key)
|
|
}
|
|
|
|
var (
|
|
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
procGetCurrentPID = kernel32.NewProc("GetCurrentProcessId")
|
|
procOpenProcess = kernel32.NewProc("OpenProcess")
|
|
procCloseHandle = kernel32.NewProc("CloseHandle")
|
|
procReadProcessMem = kernel32.NewProc("ReadProcessMemory")
|
|
)
|
|
|
|
func ObfGetpid() int {
|
|
r1, _, _ := procGetCurrentPID.Call()
|
|
return int(r1)
|
|
}
|
|
|
|
func ObfOpen(path string, flags int, mode int) (int, error) {
|
|
p, err := syscall.UTF16PtrFromString(path)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
access := uint32(syscall.GENERIC_READ)
|
|
if flags&syscall.O_WRONLY != 0 {
|
|
access = syscall.GENERIC_WRITE
|
|
}
|
|
if flags&syscall.O_RDWR != 0 {
|
|
access = syscall.GENERIC_READ | syscall.GENERIC_WRITE
|
|
}
|
|
creation := uint32(syscall.OPEN_EXISTING)
|
|
if flags&syscall.O_CREAT != 0 {
|
|
creation = syscall.CREATE_ALWAYS
|
|
}
|
|
h, _, err := syscall.CreateFile(p, access, syscall.FILE_SHARE_READ, nil, creation, syscall.FILE_ATTRIBUTE_NORMAL, 0)
|
|
if err != nil && err.(syscall.Errno) != 0 {
|
|
return -1, err
|
|
}
|
|
return int(h), nil
|
|
}
|
|
|
|
func ObfClose(fd int) error {
|
|
r1, _, err := procCloseHandle.Call(uintptr(fd))
|
|
if r1 == 0 {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ObfRead(fd int, buf []byte) (int, error) {
|
|
var bytesRead uint32
|
|
var p *byte
|
|
if len(buf) > 0 {
|
|
p = &buf[0]
|
|
}
|
|
r1, _, err := syscall.ReadFile(
|
|
syscall.Handle(fd),
|
|
buf,
|
|
&bytesRead,
|
|
nil,
|
|
)
|
|
if r1 == 0 {
|
|
return int(bytesRead), err
|
|
}
|
|
return int(bytesRead), nil
|
|
}
|
|
|
|
func ObfLseek(fd int, offset int64, whence int) (int64, error) {
|
|
var newOff int64
|
|
high := int32(offset >> 32)
|
|
r1, _, err := syscall.Seek(syscall.Handle(fd), int32(offset), high)
|
|
if r1 == 0xffffffff && err != nil {
|
|
return 0, err
|
|
}
|
|
_ = newOff
|
|
return int64(r1), nil
|
|
}
|
|
|
|
func ObfMmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset uintptr) (uintptr, error) {
|
|
flProtect := uint32(syscall.PAGE_READWRITE)
|
|
if prot&syscall.PROT_EXEC != 0 {
|
|
flProtect = syscall.PAGE_EXECUTE_READWRITE
|
|
}
|
|
h, _, err := syscall.CreateFileMapping(
|
|
syscall.Handle(fd),
|
|
nil,
|
|
flProtect,
|
|
uint32(length>>32),
|
|
uint32(length),
|
|
nil,
|
|
)
|
|
if h == 0 {
|
|
return 0, err
|
|
}
|
|
return uintptr(h), nil
|
|
}
|
|
|
|
func ObfMprotect(addr uintptr, length uintptr, prot int) error {
|
|
var oldProtect uint32
|
|
flProtect := uint32(syscall.PAGE_READWRITE)
|
|
if prot&syscall.PROT_EXEC != 0 {
|
|
flProtect = syscall.PAGE_EXECUTE_READWRITE
|
|
}
|
|
r1, _, err := procNtProtectVirtualMemory.Call(
|
|
uintptr(0xffffffffffffffff),
|
|
uintptr(unsafe.Pointer(&addr)),
|
|
uintptr(unsafe.Pointer(&length)),
|
|
uintptr(flProtect),
|
|
uintptr(unsafe.Pointer(&oldProtect)),
|
|
)
|
|
if r1 != 0 {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type windowsObfCall struct {
|
|
once sync.Once
|
|
procAddr uintptr
|
|
proc *syscall.LazyProc
|
|
}
|
|
|
|
func (w *windowsObfCall) Call(args ...uintptr) (uintptr, uintptr, error) {
|
|
w.once.Do(func() {
|
|
if w.proc != nil {
|
|
w.procAddr = w.proc.Addr()
|
|
}
|
|
})
|
|
return syscall.Syscall(w.procAddr, uintptr(len(args)), args[0], args[1], args[2])
|
|
}
|
|
|
|
func NtQueryInformationProcess(handle uintptr, infoclass uint32, info uintptr, infolen uint32, retlen *uint32) uintptr {
|
|
r1, _, _ := procNtQueryInformationProcess.Call(
|
|
handle,
|
|
uintptr(infoclass),
|
|
info,
|
|
uintptr(infolen),
|
|
uintptr(unsafe.Pointer(retlen)),
|
|
)
|
|
return r1
|
|
}
|
|
|
|
func NtSetInformationThread(handle uintptr, infoclass uint32, info uintptr, infolen uint32) uintptr {
|
|
r1, _, _ := procNtSetInformationThread.Call(
|
|
handle,
|
|
uintptr(infoclass),
|
|
info,
|
|
uintptr(infolen),
|
|
)
|
|
return r1
|
|
}
|