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那一句。
-----------------------------------------------------------------------------------------------------------
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那一句。
-----------------------------------------------------------------------------------------------------------
相关文章推荐
- 接口测试基础知识详解
- jQuery小测试系列之jQuery基础知识
- 软件测试基础知识
- CSS3基础知识小测验上线,大家有兴趣可以测试一下!
- 关于channel和chaincode的基础知识+基本测试
- 软件测试基础理论知识
- jQuery小测试系列之jQuery基础知识
- 软件测试的基础知识概要介绍
- Unity3D基础知识(一) MonoBehaviour脚本内置函数执行顺序测试
- 【转载】测试基础培训-测试理论知识
- 软件测试不得不说的基础知识
- 测试工程师基础知识
- Java核心技术卷I:基础知识(原书第8版):5.2.2 相等测试与继承
- java基础知识测试
- MySQL基础知识测试
- 新手软件测试基础知识学习必知
- 《软件测试管理》第14章 软件测试常见问题——(一)基础知识部分
- [Android测试] AS+Appium+Java+Win自动化测试之三: 基础知识和Appium界面
- LoadRunner性能测试基础知识问答
- 测试SQL基础知识