Skip to content

Instantly share code, notes, and snippets.

@chanwit
Created October 6, 2013 14:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chanwit/6854529 to your computer and use it in GitHub Desktop.
Save chanwit/6854529 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"log"
"syscall"
"unsafe"
)
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40
)
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")
)
func SysAlloc(n uintptr) (uintptr, error) {
addr, _, err := VirtualAlloc.Call(0, n, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE)
if addr == 0 {
return 0, err
}
return addr, nil
}
const SIZE = 64 * 1024
type FunctionBuilder struct {
size uint32
pc int
buf unsafe.Pointer
}
func (fb *FunctionBuilder) Nop() {
b := (*[SIZE]byte)(fb.buf)
b[fb.pc] = 0x90;
fb.pc++;
}
func (fb *FunctionBuilder) Push_EBP() {
b := (*[SIZE]byte)(fb.buf)
b[fb.pc] = 0x55;
fb.pc++;
}
func (fb *FunctionBuilder) Pop_EBP() {
b := (*[SIZE]byte)(fb.buf)
b[fb.pc] = 0x5d;
fb.pc++;
}
func (fb *FunctionBuilder) Mov_ESP_EBP() {
b := (*[SIZE]byte)(fb.buf)
b[fb.pc] = 0x8b;
fb.pc++;
b[fb.pc] = 0xec;
fb.pc++;
}
func (fb *FunctionBuilder) Mov_EBP_Param_EAX(i int) {
b := (*[SIZE]byte)(fb.buf)
b[fb.pc] = 0x8b; fb.pc++;
b[fb.pc] = 0x45; fb.pc++;
b[fb.pc] = byte((i+2)*4); fb.pc++;
}
func (fb *FunctionBuilder) IMul_EBP_Param_EAX(i int) {
b := (*[SIZE]byte)(fb.buf)
b[fb.pc] = 0x0f; fb.pc++;
b[fb.pc] = 0xaf; fb.pc++;
b[fb.pc] = 0x45; fb.pc++;
b[fb.pc] = byte((i+2)*4); fb.pc++;
}
func (fb *FunctionBuilder) Add_EBP_Param_EAX(i int) {
b := (*[SIZE]byte)(fb.buf)
b[fb.pc] = 0x03; fb.pc++;
b[fb.pc] = 0x45; fb.pc++;
b[fb.pc] = byte((i+2)*4); fb.pc++;
}
func (fb *FunctionBuilder) Ret() {
b := (*[SIZE]byte)(fb.buf)
b[fb.pc] = 0xc3;
fb.pc++;
}
/*
func Mul(x, y) {
}
func Add(x, y) {
}
func Ret(x) {
}
*/
func mkprog() error {
const size = SIZE
addr, err := SysAlloc(size)
if err != nil {
return err
}
fb := &FunctionBuilder{SIZE, 0, unsafe.Pointer(addr)}
fb.Push_EBP()
fb.Mov_ESP_EBP()
fb.Mov_EBP_Param_EAX(0)
fb.IMul_EBP_Param_EAX(1)
fb.Add_EBP_Param_EAX(2)
fb.Pop_EBP()
fb.Ret()
fb.Nop()
r1, r2, e := syscall.Syscall(addr, 3, 3, 5, 2)
fmt.Printf("%d\n", r1)
fmt.Printf("%d\n", r2)
fmt.Printf("%s\n", e)
return nil
}
func main() {
err := mkprog()
if err != nil {
log.Fatal(err)
}
fmt.Printf("HELLO\n")
}
@ZenLiuCN
Copy link

wrap into Unsafe.Pointer

package main

import (
	"syscall"
	"unsafe"
)
const (
	MemCommit  = 0x1000
	MemReserve = 0x2000
	PageExecuteReadwrite = 0x40
)
var (
	kernel32     = syscall.MustLoadDLL("kernel32.dll")
	virtualAlloc = kernel32.MustFindProc("VirtualAlloc")
)
func sysAlloc(n uintptr) (uintptr, error) {
	addr, _, err := virtualAlloc.Call(0, n, MemReserve|MemCommit, PageExecuteReadwrite)
	if addr == 0 {
		return 0, err
	}
	return addr, nil
}
const SIZE = 64 * 1024
func Execute(data []byte,invoker func(unsafe.Pointer) error) (er error) {
	size := len(data)
	addr, err := sysAlloc(uintptr(size))
	if err != nil {
		return err
	}
	buf := (*[SIZE]byte)(unsafe.Pointer(addr))
	for i := range data {
		buf[i] = data[i]
	}
	unsafeFunc := (uintptr)(unsafe.Pointer(&buf))
	return invoker(unsafe.Pointer(&unsafeFunc))
}

func main() {
	ret:=0
	//binary dump of an compiled object
	/**
		package inc
		func inc(v int) int{
			return v+1
	    }
	 */
	err:=Execute([]byte{
		0x48,0x83,0xec,0x10,
		0x48,0x89,0x6c,0x24,0x08,
		0x48,0x8d,0x6c,0x24,0x08,
		0x48,0x89,0x44,0x24,0x18,
		0x48,0xc7,0x04,0x24,0x00,0x00,0x00,0x00,

		0x48,0x8b,0x4c,0x24,0x18,
		0x48,0x8d,0x41,0x01,
		0x48,0x89,0x04,0x24,
		0x48,0x8b,0x6c,0x24,0x08,
		0x48,0x83,0xc4,0x10,
		0xc3,
	},func(pointer unsafe.Pointer) error {
		fn:=*(*func(int)int)(pointer)
		ret=fn(10)
		return nil
	})
	if err!=nil{
		panic(err)
	}
	println("invoked :",ret)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment