哇,这比我想象的要痛苦得多 . 100%的痛苦是linux保护程序不被覆盖和/或执行数据 .
两个解决方案如下所示并且涉及了很多谷歌搜索,所以有点简单地把一些指令字节和执行它们是我的,在页面大小上的mprotect和对齐是从谷歌搜索中剔除的,我必须为这个例子学习的东西 .
自修改代码是直截了当的,如果您接受程序或至少只是两个简单的函数,编译然后反汇编,您将获得这些指令的操作码 . 或者使用nasm来编译汇编程序块等 . 从此确定操作码将立即加载到eax然后返回 .
理想情况下,您只需将这些字节放在某个ram中并执行该ram . 要让linux执行此操作,您必须更改保护,这意味着您必须向它发送一个在mmap页面上对齐的指针 . 因此,分配超出您需要的内容,找到页面边界上的分配中的对齐地址,并从该地址进行保护,并使用该内存放置您的操作码然后执行 .
第二个例子将现有的函数编译到程序中,再次因为保护机制你不能简单地指向它并改变字节,你必须从写入中取消保护它 . 所以你必须备份到前一页边界调用mprotect与该地址和足够的字节来覆盖要修改的代码 . 然后,您可以以任何您想要的方式更改该函数的字节/操作码(只要您不会溢出到您想要继续使用的任何函数中)并执行它 . 在这种情况下,您可以看到 fun() 工作,然后我将其更改为只返回一个值,再次调用它,现在它已被修改 .
#include
#include
#include
#include
unsigned char *testfun;
unsigned int fun ( unsigned int a )
{
return(a+13);
}
unsigned int fun2 ( void )
{
return(13);
}
int main ( void )
{
unsigned int ra;
unsigned int pagesize;
unsigned char *ptr;
unsigned int offset;
pagesize=getpagesize();
testfun=malloc(1023+pagesize+1);
if(testfun==NULL) return(1);
//need to align the address on a page boundary
printf("%p\n",testfun);
testfun = (unsigned char *)(((long)testfun + pagesize-1) & ~(pagesize-1));
printf("%p\n",testfun);
if(mprotect(testfun, 1024, PROT_READ|PROT_EXEC|PROT_WRITE))
{
printf("mprotect failed\n");
return(1);
}
//400687: b8 0d 00 00 00 mov $0xd,%eax
//40068d: c3 retq
testfun[ 0]=0xb8;
testfun[ 1]=0x0d;
testfun[ 2]=0x00;
testfun[ 3]=0x00;
testfun[ 4]=0x00;
testfun[ 5]=0xc3;
ra=((unsigned int (*)())testfun)();
printf("0x%02X\n",ra);
testfun[ 0]=0xb8;
testfun[ 1]=0x20;
testfun[ 2]=0x00;
testfun[ 3]=0x00;
testfun[ 4]=0x00;
testfun[ 5]=0xc3;
ra=((unsigned int (*)())testfun)();
printf("0x%02X\n",ra);
printf("%p\n",fun);
offset=(unsigned int)(((long)fun)&(pagesize-1));
ptr=(unsigned char *)((long)fun&(~(pagesize-1)));
printf("%p 0x%X\n",ptr,offset);
if(mprotect(ptr, pagesize, PROT_READ|PROT_EXEC|PROT_WRITE))
{
printf("mprotect failed\n");
return(1);
}
//for(ra=0;ra<20;ra++) printf("0x%02X,",ptr[offset+ra]); printf("\n");
ra=4;
ra=fun(ra);
printf("0x%02X\n",ra);
ptr[offset+0]=0xb8;
ptr[offset+1]=0x22;
ptr[offset+2]=0x00;
ptr[offset+3]=0x00;
ptr[offset+4]=0x00;
ptr[offset+5]=0xc3;
ra=4;
ra=fun(ra);
printf("0x%02X\n",ra);
return(0);
}