linux 自修改代码 smc,如何在x86汇编中编写自修改代码

哇,这比我预想的要痛苦得多。 100%的痛苦是linux保护程序不被覆盖和/或执行数据。

如下所示的两种解决方案。 涉及到很多谷歌搜索,因此稍微简单一些就放一些指令字节并执行它们是我的,mprotect和页面大小对齐是从谷歌搜索中剔除的,这是我在本例中必须学习的内容。

自修改代码很简单,如果您使用程序或至少仅使用两个简单函数,则进行编译然后反汇编,您将获得这些指令的操作码。 或使用nasm编译汇编程序块等。由此,我确定了将立即数加载到eax中然后返回的操作码。

理想情况下,您只需将这些字节放入某个ram中并执行该ram。 为了使Linux能够做到这一点,您必须更改保护,这意味着您必须向其发送一个在mmap页面上对齐的指针。 因此,分配比您需要更多的资源,在该分配中找到位于页面边界上的对齐地址,并从该地址进行mprotect并使用该内存放入您的操作码,然后执行。

第二个示例采用了已编译到程序中的现有函数,同样由于保护机制的原因,您不能简单地指向它并更改字节,因此必须取消对它的写保护。 因此,您必须使用该地址和足够的字节备份到先前的页面边界调用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);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值