免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 23022 | 回复: 64
打印 上一主题 下一主题

把函数复制到堆上并运行的方法 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-08-07 23:51 |只看该作者 |倒序浏览
有需求见此贴,所谓的动态执行 http://bbs.chinaunix.net/thread-1235365-1-1.html

实现如下:

void add(int a, int b)
{
        printf("a+b=%d\n", a+b);
}

char *get_call_addr(char *p, int len)
{
       while(len-- && (*p != (char)0xe8 ))
               p++;

       if (len)
               return p;
       else
               return 0;
}

void set_call(int call_addr, int fun_addr)
{
        int ip = call_addr + 5;
        int set_call_addr = call_addr + 1;
       (*(int *)set_call_addr) = fun_addr - ip;
}


int main()
{
         char *p = (char *)malloc(100);
         
         memcpy(p, add, 100);

         void (*pf)(int, int) = (void(*)(int, int))p;

          char *call_addr = get_call_addr(p, 100);
          if (call_addr) {
                  set_call((int)call_addr, (int)printf);
                  pf(10, 20);
          }

         return 0;
}


上面的代码能实现,将函数复制到 malloc 出来的内存里正确执行,原理就是修改里面的 call 指令偏移值。
这里能正确运行,但这种方法并不保险。
实际情况可能是:1、编译器产生的代码是多变的。2、刚刚好其它指令里没有 0xe8 这个机器码,要经过很多重判断(否则是话就大错特错了, )


二、还有就是用直接调用的方法,或类似方法

void foo()
{
          printf("I'm foo()...\n";
}

int main()
{
          char *p = (char *)malloc(20);
          int pf = (int)foo;

          p[0] = 0xff;
          p[1] = 0x15;
          *((int *)&p[2]) = (int)&pf;
          p[6] = 0xc3;

          (void (*)())p();

          return 0;
}


虽然,正确调用得到了保证,但要传递参数的话,要多动点脑子

评分

参与人数 1可用积分 +5 收起 理由
prolj + 5 层次更深一点

查看全部评分

论坛徽章:
0
2 [报告]
发表于 2008-08-07 23:55 |只看该作者
那段地址有运行的权限吗

论坛徽章:
0
3 [报告]
发表于 2008-08-07 23:57 |只看该作者

回复 #2 agaric 的帖子

可以执行

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
4 [报告]
发表于 2008-08-07 23:59 |只看该作者
原帖由 agaric 于 2008-8-7 23:55 发表
那段地址有运行的权限吗

这个......应该是OS相关,有些OS确实可能无法执行(一般此类则较为安全)

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
5 [报告]
发表于 2008-08-08 00:04 |只看该作者
mik兄,这段时间忙啥呢?呵呵

论坛徽章:
0
6 [报告]
发表于 2008-08-08 00:12 |只看该作者

回复 #5 cjaizss 的帖子

没啥忙的,人懒惰了啥都不想干,啥都不想忙。

论坛徽章:
0
7 [报告]
发表于 2008-08-08 00:20 |只看该作者
很好的贴。

请问以下问号处怎么理解?
void set_call(int call_addr, int fun_addr)
{
        int ip = call_addr + 5;   //?
        int set_call_addr = call_addr + 1;
       (*(int *)set_call_addr) = fun_addr - ip;  //?
}

论坛徽章:
0
8 [报告]
发表于 2008-08-08 00:29 |只看该作者

回复 #7 eagle518 的帖子

你 objdump 一下 add() 来看看会明白很多

论坛徽章:
0
9 [报告]
发表于 2008-08-08 00:34 |只看该作者
这样做又什么好处吗?还是特殊要求?

论坛徽章:
0
10 [报告]
发表于 2008-08-08 00:35 |只看该作者
原帖由 mik 于 2008-8-8 00:29 发表
你 objdump 一下 add() 来看看会明白很多


ok.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP