免费注册 查看新帖 |

Chinaunix

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

通过切换STACK实现远跳longjmp的最简单的演示 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-02-26 13:19 |只看该作者 |倒序浏览
前几天有人问longjmp代码的问题。这里实验了一个演示。

仅仅为了说明通过切换STACK实现远跳的初步演示。是一个没有任何实际用处的程序。




  1. /* setjmp & longjmp simple demo
  2. */

  3. char jbuf[128];

  4. char *setjmp()
  5. {
  6. int i;

  7.    printf("setjmp...\n");
  8.    memcpy(jbuf, &i, 32);
  9.    return jbuf;
  10. }


  11. int longjmp(char *p)
  12. {
  13. int i;
  14.     memcpy(&i, jbuf, 32);
  15.     printf("doing longjmp...\n");
  16.     return 0;
  17. }

  18. func()
  19. {
  20.     printf("in function...\n");
  21.     longjmp(jbuf);
  22.     printf("useless code---\n");
  23. }

  24. main()
  25. {
  26. char *jp;
  27. int k = 4;

  28.     printf("normal path...\n");
  29.     jp = setjmp();
  30.     if(jp) {
  31.        printf("normal path 0--------- k %d jp %p\n", k, jp);
  32.        printf("normal path 1---------\n");
  33.        //longjmp(jp);
  34.        printf("normal path 1---------\n");
  35.        func();
  36.        printf("never reach here...\n");
  37.     } else {
  38.        printf("longjmp path 3 --------- k %d jp %p\n", k, jp);
  39.     }
  40. }


复制代码

论坛徽章:
0
2 [报告]
发表于 2007-02-26 13:39 |只看该作者
有点意思,要是加上一些解释就好了,也可以做为理解缓冲区溢出,函数栈原理的材料哦~~

论坛徽章:
0
3 [报告]
发表于 2007-02-26 13:45 |只看该作者

  1. /* setjmp & longjmp simple demo
  2. */

  3. char jbuf[128];

  4. char *setjmp()
  5. {
  6. int i;

  7.    printf("setjmp...\n");
  8.    memcpy(jbuf, &i, 32);   //保存setjmp时刻的STACK到buffer中。这里可以分配内存保存,而不用全局量jbuf. 如果这样可以有多个longjmp点。
  9.    return jbuf;
  10. }


  11. int longjmp(char *p)
  12. {
  13. int i;
  14.     memcpy(&i, jbuf, 32);  //恢复此点的STACK。STACK内容在p中
  15.     printf("doing longjmp...\n");
  16.     return 0;  //必须返回0,与setjmp原始返回区分路径。
  17. }

  18. func()
  19. {
  20.     printf("in function...\n");
  21.     longjmp(jbuf);  //远跳
  22.     printf("useless code---\n");
  23. }

  24. main()
  25. {
  26. char *jp;
  27. int k = 4;

  28.     //其它没有什么了。基本意思可以看setjmp longjmp函数
  29.     printf("normal path...\n");
  30.     jp = setjmp();
  31.     if(jp) {
  32.        printf("normal path 0--------- k %d jp %p\n", k, jp);
  33.        printf("normal path 1---------\n");
  34.        //longjmp(jp);
  35.        printf("normal path 1---------\n");
  36.        func();
  37.        printf("never reach here...\n");
  38.     } else {
  39.        printf("longjmp path 3 --------- k %d jp %p\n", k, jp);
  40.     }
  41. }
复制代码

评分

参与人数 1可用积分 +5 收起 理由
converse + 5 我很赞同

查看全部评分

论坛徽章:
0
4 [报告]
发表于 2007-02-26 14:52 |只看该作者
好久没看这些东西了,栈桢的结构都忘了。


  1. memcpy(jbuf, &i, 32);   
复制代码

拷贝的是eip,ebp,edi,esi的地址把,现在还没弄懂edi,esi存什么,怎么用

试了一下,只是保存和恢复eip程序也能工作

  1. memcpy(jbuf, &i+3, 4);   
  2. ...
  3. memcpy(&i+3, jbuf, 4);  
复制代码

论坛徽章:
0
5 [报告]
发表于 2007-03-04 19:02 |只看该作者
这个只是x86上的longjmp。stack longjmp与计算机体系有关

论坛徽章:
0
6 [报告]
发表于 2007-03-04 21:04 |只看该作者
LZ 的 setjump() 有个很大的缺陷:

memcpy(jbuf, &i, 32);   // 32 怎么得来?
通过变量 i 偏移来获得返回地址,在没有特别选项进行编译时,大多数编译器会浪费掉一些空间用来对齐。
所以变量 i 的上一个地址不是返回址,所以不可能是根据局部变量来得出返回地址。


获得返回地址方法有很多:
1、利用参数,参数是固定的
char * setjump(int i)
{
      memcpy(buf,&i-1, 4);
      ......   
}



2、 取 eip 值

#define __EIP__                                 \
        {      int i;                                      \
       __asm__ __volatile__("call f\n"     \
               "f: pop %0\n"                         \
                :"=r"(i)                                  \
       );                                                   \
      memcpy(buf, &i, 4);                        \
      }

论坛徽章:
0
7 [报告]
发表于 2007-03-04 21:40 |只看该作者
我那程序仅仅是一个最简单的原理演示. 目的就是使程序简单容易看懂. 不是有用的实用程序.

大家可以发贴子改进.

论坛徽章:
0
8 [报告]
发表于 2008-07-11 13:49 |只看该作者
我对程序做了几次修改,产生的结果让我不明白,第一次修改:
把memcpy(jbuf, &i, 32); 改成 memcpy(jbuf, &i+2,4);把 memcpy(&i, jbuf, 32);改成memcpy(&i+2, jbuf, 4);
输出结果是:
normal path...
setjmp...
normal path 0--------- k 4 jp 0x80497e0
normal path 1---------
normal path 1---------
in function...
doing longjmp...
longjmp path 3 --------- k 134514259 jp (nil)
never reach here...
为什么会多出 never reach here 呢?
按我的理解:我修改longjump的返回地址,把0 赋给jp了, 应该执行到longjmp path 3 --------- k 134514259 jp (nil)就结束了啊.
而没改之前是没有这句打印的
第2次改动是把memcpy(jbuf, &i, 32);和memcpy(&i, jbuf, 32); 改成
memcpy(jbuf, &+1, 4);memcpy( &+1,jbuf 4);
或则
memcpy(jbuf, &+3, 4);memcpy( &+3,jbuf 4);
..............................
memcpy(jbuf, &+25, 4);memcpy( &+25,jbuf 4);
.............................
程序的结果是不挺的循环,又是为什么啊,程序的输出结果:
..............................
normal path...
setjmp...
normal path 0--------- k 4 jp 0x80497e0
normal path 1---------
normal path 1---------
in function...
doing longjmp...
normal path...
setjmp...
normal path 0--------- k 4 jp 0x80497e0
normal path 1---------
normal path 1---------
in function...
doing longjmp...
normal path...
setjmp...
normal path 0--------- k 4 jp 0x80497e0
normal path 1---------
normal path 1---------
in function...
doing longjmp...
normal path...
setjmp...
normal path 0--------- k 4 jp 0x80497e0
normal path 1---------
normal path 1---------
in function...
doing longjmp...
normal path...
setjmp...
normal path 0--------- k 4 jp 0x80497e0
normal path 1---------
normal path 1---------
in function...
doing longjmp...
.........................................
后面的改动并没有修改函数的返回地址,怎么会造成死循环的呢?

论坛徽章:
0
9 [报告]
发表于 2008-07-11 14:03 |只看该作者
lz这个是通过保存当前的stack的状态,在需要的时候覆盖回去,来达到longjmp的功能吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP