用户态进程在堆栈执行代码时,因为内核在加载该进程的时候,取消了在堆栈上执行代码的权限,因此如果在其上执行代码的话,进程会直接死掉。
接下来是在堆栈执行代码的测试例子,主要思路是给物理内存加上可执行代码的权限。代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/mman.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
typedef int (*func)(unsigned int);
int hello(unsigned int start)
{
return 0x61;
}
int main(void)
{
unsigned int len = 0;
unsigned char *q = NULL;
unsigned char *p = NULL;
int i = 0;
func qq = NULL;
FILE *f;
int n, fd;
fd = open("/dev/mem", O_RDWR|O_EXCL|O_SYNC);
if(fd == -1){
printf("open /dev/mem failed!\n");
return -1;
}
/*通过mmap设置其用可执行权限(PROT_EXEC)*/
q = mmap(NULL, 0xff, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, fd, 0x20000);
if(q == 0){
printf("mmap failed!\n");
}
p = (unsigned char *)hello;
/*拷贝代码*/
for(i = 0;p[i]!=0xc3;i++){
q[i] = p[i];
printf( "hello:%p:\t%02x\t\n",p+i,p[i]);
printf( "q :%p:\t%02x\t\n",q+i,q[i]);
}
q[i] = p[i];
printf( "hello:%p:\t%02x\t\n",p+i,p[i]);
printf( "q :%p:\t%02x\t\n",q+i,q[i]);
printf( "len = 0x%x before hack\n",len);
qq = (func)q;
/*执行*/
len = qq(0);
printf( "len = 0x%x after hack\n",len);
close(fd);
munmap(q, 0xff);
return 0;
}
结果如下:
可见,成功执行了该代码。