您的位置:首页 > 其它

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

2005-12-06 19:01 621 查看
#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那一句。

-----------------------------------------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: