3 回答
TA贡献1860条经验 获得超8个赞
首先,您根本不需要(当前)使用mmap,因为 go memory 是可执行的。如果确实需要mmap,可以使用匿名内存并放弃临时文件:
b, e := syscall.Mmap(0, 0, len(shellcode), syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC, syscall.MAP_ANON)
copy(b, shellcode)
否则,您可以尝试shellcode直接使用,因为它已经由连续数组支持。
至于将字节转换shellcode为函数,C 中的模拟将如下所示:
f := *(*func() int)(unsafe.Pointer(&d[0]))
它创建了一个名为的函数值f,然后可以像普通函数一样调用它。
如果 shellcode 不是专门为 Go 编写的,并且您需要从 C 堆栈中调用它,那么使用 cgo 直接在 C 中执行它会更容易。
/*
call(char *code) {
int (*ret)() = (int(*)())code;
ret();
}
*/
import "C"
func main() {
...
// at your call site, you can send the shellcode directly to the C
// function by converting it to a pointer of the correct type.
C.call((*C.char)(unsafe.Pointer(&shellcode[0])))
TA贡献1911条经验 获得超7个赞
我试图了解如何mmap PROT_EXEC在 中工作Go,并提出了同样的问题。
我很难[]byte将 正确转换为函数。它并不像这里的一些答案所说的那么明显。
我想出了一个工作示例,说明如何使用mmap名为mmap-go的更高级别的库来执行此操作。在这个例子中,我们有一个函数的可执行代码,它为传递的参数增加 1。
code := []byte{
0x48, 0xc7, 0x44, 0x24, 0x10, 0x00, 0x00, 0x00, 0x00,
0x48, 0x8b, 0x44, 0x24, 0x08,
0x48, 0xff, 0xc0,
0x48, 0x89, 0x44, 0x24, 0x10,
0xc3,
}
memory, err := mmap.MapRegion(nil, len(code), mmap.EXEC|mmap.RDWR, mmap.ANON, 0)
if err != nil {
panic(err)
}
copy(memory, code)
memory_ptr := &memory
ptr := unsafe.Pointer(&memory_ptr)
f := *(*func(int) int)(ptr)
fmt.Println(f(10)) // Prints 11
我认为unsafe.Pointer(&memory[0])会像答案之一所暗示的那样解决我的问题。但是通过这样做,您无法将地址转换为正确地址中的可调用函数。诀窍是更进一步,做到这一点
memory_ptr := &memory
ptr := unsafe.Pointer(&memory_ptr)
代替
f := *(*func(int) int)(&memory[0])
- 3 回答
- 0 关注
- 294 浏览
添加回答
举报