YY指针堆栈,测试你的基础知识。(csdn)

#include <stdlib.h>

int funa(void)
{
   printf("AAAAA");
   exit(3);
   return 0;
}

int funb(int (*p)(void))
{
   char *h;
   h = (char*)&h;
   /* point to the first variable */

   h += sizeof(char *);
   /* point to the old ebp */

   h += sizeof(char *);
   /* point to the return address */

   (*(int (**)(void))(h)) = p;
   return 0;
}

int main()
{
   funb(funa);
   return 0;
}
-----------------------------------------------------------------------------------------------------------

if ( !setjmp(thr_table[cur_thr->id]->jb) )///strange code here//
        /*maybe setjmp(cur_thr->jb) could gain better performance*/
        {
                stack_base = thr_table[i]->stack_base = MALLOC(thr_table[i]->sta
ck_sz);
                cur_thr = thr_table[i];
                asm("movl 12(%ebp), %eax");
                asm("movl 8(%ebp), %ecx");
                asm("movl stack_base.1, %esp");
                asm("pushl %eax");
                asm("pushl %ecx");
                asm("call thr_creat_wrapper");
        }
        else
        {
                cur_thr = cur_thr->prev_thr;
        }

随便邪恶一把……
-----------------------------------------------------------------------------------------------------------

说实话,这个东西也就一般性质的邪恶,和vfork比起来差的远了

int main(void){ vfork();}
就这么个东西就可以core dump了……

-----------------------------------------------------------------------------------------------------------

三井的代码要是不自个儿调用一下exit的话,也会和vfork获得一样的效果就是core dump……

另外,一般这样的东西我会这么写

void foo(void* another_func)
{
  void* ia[1];
  ia[2] = another_func;
}
三井的代码里面太明目张胆了……

还有,我怀疑这样的代码最多也就在IA32(了不得再加上个AMD64)上面能用,又不是所有的体系上stack都这样布局……

-----------------------------------------------------------------------------------------------------------

这个代码实际上已经和汇编没有什么区别了。
而汇编本身就是依赖硬件环境的。所以能在奔腾上运行就不错了。呵呵。

-----------------------------------------------------------------------------------------------------------

楼主的代码都有解释了,所以比较容易看出来.
关键是获得函数返回值地址并且修改了它.

-----------------------------------------------------------------------------------------------------------

楼上不懂的只要弄明白以下两点就知道了:
1.x86的stack是从高地址到低地址增长的.
2.ebp和esp之间的关系及这样一个事实 : 调用一个函数或中断要用堆栈来保护现场. 
这份代码其实就是玩了一个破坏堆栈的把戏而已.

 h += sizeof(char *);
   /* point to the old ebp */

   h += sizeof(char *);
   /* point to the return address */

   (*(int (**)(void))(h)) = p;
破坏了堆栈,而使funb返回后不往下执行而是跳到funa中去了.
其实楼主代码中的注释写得很清楚了.呵呵.
正因如此,所以funa中要写个exit,不然会引发异常.

-----------------------------------------------------------------------------------------------------------

也贴一个玩弄堆栈的小程序:

#include <stdio.h>
#include <stdlib.h>

int funa(void)
{
   int a = 2;
   int *b = &a;
   *(b+2) += 9;
   return 0;
}


int main()
{
 int a = 1;
   funa();
   a += 2;
   printf("a = %d/n",a);
   return 0;
}
这个程序是VC的,如果是GCC的话,*(b+2) += 9;写成*(b+2) += 4;

-----------------------------------------------------------------------------------------------------------

别人玩省下的!


char main = '/xc3';

char main[] = "/xFE/xEB/xc3";

-----------------------------------------------------------------------------------------------------------

h =(char*) &h;将h的地址赋值给指针h本身

   h += sizeof(char *);
   /* point to the old ebp */

   h += sizeof(char *);
   /* point to the return address */
得到堆栈中系统寄存器的地址

(*(int (**)(void))(h)) = p;
改变EIP的值,从main函数中跳去执行funa函数,由于不能回到main中执行return 0语句,所以要在funa中加上exit(3)

*(b+2) += 9;因为在vc6中a+=2语句需要9条机器指令,这个在汇编中可以很方便的看出来。所以在函数funa返回到main函数中时,eip的值加上9,就刚好跳过了a+=2这一句。如果是*(b+2) += 26;则还可以跳过printf那一句。

-----------------------------------------------------------------------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值