我在x86_64上写了一个示例代码,尝试动态执行malloc代码。有一个
程序接收到信号SIGSEGV,分段故障。0x0000000000601010英寸??()
0x0000000000601010是bin的位置,有人能说出为什么?谢谢
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <sys/mman.h>
volatile int sum(int a,int b)
{
return a+b;
}
int main(int argc, char **argv)
{
char* bin = NULL;
unsigned int len = 0;
int ret = 0;
/*code_str is the compiled code for function sum.*/
char code_str[] ={0x55,0x48,0x89,0xe5,0x89,0x7d,0xfc,0x89,
0x75,0xf8,0x8b,0x45,0xf8,0x03,0x45,0xfc,0xc9,0xc3};
len = sizeof(code_str)/sizeof(char);
bin = (char*)malloc(len);
memcpy(bin,code_str,len);
mprotect(bin,len , PROT_EXEC | PROT_READ | PROT_WRITE);
asm volatile ("mov $0x2,%%esi nt"
"mov $0x8,%%edi nt"
"mov %1,%%rbx nt"
"call *%%rbx "
:"=a"(ret)
:"g"(bin)
:"%rbx","%esi","%edi");
printf("sum:%dn",ret);
return 0;
}
不要在不检查系统函数返回的情况下使用这些技巧。我的mprotect
手册页特别提到:
POSIX says that the behavior of mprotect() is unspecified if it is applied to a region of memory that was not obtained via mmap(2).
所以不要使用CCD_ 2 ed缓冲区。
还有:
- 缓冲区大小只是
sizeof(code_str)
,没有理由除以sizeof(char)
(保证为1,但这并不正确) - 不需要强制转换
malloc
的返回(如果您将其更改为mmap
,也不需要强制它) code_str
的正确类型是unsigned char
,而不是char
问题是bin地址应该与多个PAGESIZE对齐,否则mprotect将返回-1,参数无效。
bin = (char *)(((int) bin + PAGESIZE-1) & ~(PAGESIZE-1));//added....
memcpy(bin,code_str,len);
if(mprotect(bin, len , PROT_EXEC |PROT_READ | PROT_WRITE) == -1)
{
printf("mprotect error:%dn",errno);
return 0;
}