首页
社区
课程
招聘
[求助]不用异常处理,如何判断是否可以在栈上面执行代码?
发表于: 2009-2-13 09:10 5533

[求助]不用异常处理,如何判断是否可以在栈上面执行代码?

2009-2-13 09:10
5533
如下,是在栈上面执行一条ret执行,其实就是什么都不做。
	DWORD code = 0xC3;
	((FARPROC)&code)();


这样的语句在EXE文件里面一点问题都没有,而在DLL中也不一定会出问题,但如果这个DLL是rundll32加载的就一定出错,原因是页面没有可执行属性,用VirtualProtect加上可执行属性后,就可以正常执行。

现在问题来了,我试过用VirtualQuery查询&code也就是栈所在的section的属性,结果发现不管是哪一种情况,都只是PAGE_READWRITE,没有可执行属性,那么为什么Exe可以在没有权限的情况下在栈上面执行代码?或者说,我们还可以根据什么来判断是否可以在栈上面执行代码呢?

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (14)
雪    币: 2056
活跃值: (13)
能力值: ( LV13,RANK:250 )
在线值:
发帖
回帖
粉丝
2
看下是否为“基本Windows服务及程序”启用了DEP。
2009-2-13 09:47
0
雪    币: 359
活跃值: (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
目前的设置是“仅为基本的 Windows 程序和服务启用 DEP”,原来是这个原因啊。
多谢LS。
2009-2-13 10:56
0
雪    币: 359
活跃值: (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
我刚才试了一下,发现即便选成“为所有程序和服务启用DEP”,然后再重启,在EXE里面,在栈上面执行也不会出错。
似乎不是2L说的原因啊!?到底怎么回事?
2009-2-13 17:16
0
雪    币: 70
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
还需要CPU的支持
2009-2-13 18:45
0
雪    币: 359
活跃值: (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
顶楼我就已经说过了,如果在Rundll32加载的DLL里面执行那段代码,出异常,你说我这块CPU支持么?
2009-2-13 20:39
0
雪    币: 44
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
该函数执行时EIP应该是在代码段吧
2009-2-14 13:21
0
雪    币: 359
活跃值: (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
可以明确的告诉你,确实是在栈上面, 在code的内存空间,只不过call进去以后,第一条指令ret,又返回了出来。
如果不是在栈上面执行的,甚至不能解释为什么rundll32加载会出错。
2009-2-14 14:16
0
雪    币: 44
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
Exe里执行到自己写的Ret时确实是在栈的地址空间,此时的执行页面没有被标记为可执行的,但是EIP已经指向了它,可以说是一个必须被执行的页面即使它是一个数据页面。如果启用了DEP是我这是会掷出异常STATUS_ACCESS_VIOLATION(0xc0000005)的。DEP还需CPU支持。
2009-2-14 20:43
0
雪    币: 44
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
rundll32加载时,dll中的函数使用的是__stdcall方式,你直接Ret时,栈帧出错了。
2009-2-14 22:19
0
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
栈不可执行吗?
我还以为windows是栈可执行的操作系统
2009-2-15 10:00
0
雪    币: 359
活跃值: (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
这个ret对应的是((FARPROC)&code)()的call,只是返回到这句的下一句而已,又不是返回到外面了,堆栈怎么可能会不平衡呢?而且对于没有参数的函数而言,_cdcel和_stdcall也没啥区别。

不过你说你启用DEP后,普通Exe也一样抛STATUS_ACCESS_VIOLATION(0xc0000005),那可能就是DEP的原因了。不过不知道为什么我这台机,即使是启用了DEP,也只有rundll32会抛这个异常,其他的则是正常执行。我的CPU是T7300。
2009-2-15 12:44
0
雪    币: 44
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
((FARPROC)&code)()的call XXXX(0x7ff14), XXXX(0x7ff14)也就是你的ret的位置,
调用前
0:000> kn
# ChildEBP RetAddr  
00 0007ff18 01001abb ret!test+0x24 [E:\code\Ret\Ret.c @ 17]
01 0007ff60 01001bcf rundll32!WinMainT+0x104
02 0007ffc0 7c816fd7 rundll32!_ModuleEntry+0x84
03 0007fff0 00000000 kernel32!BaseProcessStart+0x23
调用后:
0:000> kn
# ChildEBP RetAddr  
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 0007fec0 00a31096 0x7ff14
01 0007ff18 01001abb ret!test+0x26 [E:\code\Ret\Ret.c @ 17]
02 0007ff60 01001bcf rundll32!WinMainT+0x104
03 0007ffc0 7c816fd7 rundll32!_ModuleEntry+0x84
04 0007fff0 00000000 kernel32!BaseProcessStart+0x23
2009-2-15 15:21
0
雪    币: 359
活跃值: (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
这个跟ebp有关系么?用ebp来保存当时的esp,只不过是为了访问调用参数更方便一点,好像GCC还有一个编译参数可以禁用ebp保存esp的编译行为,使得ebp成为一个普通的寄存器。
另外,call没有修改除esp以外的任何一个寄存器,esp也只是减小4,ret的时候esp就变回来了,堆栈上有问题么?
不过我用的VS2003在RELEASE下编译这两条语句,会把code=0xC3优化没掉,所以要用_asm mov dword ptr[code],  0xC3来确保赋值语句正常。
可能这个问题是DEP引起的吧?LS的是不是开启DEP以后,EXE执行这两条语句也出抛异常?
2009-2-15 21:07
0
雪    币: 44
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
将rundll32设置为DEP例外,再调用时没出错了,应该是DEP的问题
2009-2-16 15:32
0
游客
登录 | 注册 方可回帖
返回
//