能力值:
( LV12,RANK:210 )
|
-
-
2 楼
试验过,确实如此
理论上栈指针上方的空间是自由空间, 它的内容是不确定的, 尽管之前已经对它进行了修改, 它的值还是会不断变化
猜想原因可能是:
1.栈指针上方的空间被映射到内存中的另一个页面上了(可能性不大)
2.系统API也会使用堆栈, 可能它们占用了栈指针上方的空间(用于局部变量保存等),导致栈内容发生改变
楼主碰到的情况应该是第2种, 就是调用系统API改变了堆栈自由空间的内容
|
能力值:
( LV12,RANK:210 )
|
-
-
3 楼
写了一个小程序测试了一下, MASM编写
其中$CTA0是定义字符串的一个宏, 这里不列出了
;Compile:ml /c /coff /Cp Test.asm
;Link:link /subsystem:windows Test.obj
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib
.code
Start:
push ebp
mov ebp, esp
sub esp, 1000h ;保留1K字节的空间
mov ebx, esp
mov eax, 0CCCCCCCCh ;全填入0CCh
mov ecx, 1000h / 4h
mov edi, ebx
cld
rep stosd
add esp, 1000h ;还原保留的1K字节空间
call GetCommandLine ;这里随便调用一个函数
mov eax, 0CCCCCCCCh
mov edi, ebx
mov ecx, 1000h / 4h
repz scasd ;检查堆栈数据是否发生变化
jz Exit
;结果这句执行了, 证明堆栈数据发生了变化
invoke MessageBox, NULL, $CTA0("Data on stack has changed."), $CTA0("Test"), MB_OK
Exit:
leave
ret
END Start
|
能力值:
( LV4,RANK:50 )
|
-
-
4 楼
VC的优化也不错:
00401000 />push ebp
00401001 |>mov ebp,esp
00401003 |>sub esp,400
00401009 |>push 400 ; /BufSize = 400 (1024.)
0040100E |>lea eax,[ebp-400] ; |
00401014 |>push eax ; |Buffer
00401015 |>push 0040301C ; |VarName = "ComSpec"
0040101A |>call [<&KERNEL32.GetEnvironmentVariableA>] ; \GetEnvironmentVariableA
00401020 |>push 200 ; /BufSize = 200 (512.)
00401025 |>push 00403010 ; |/StringToAdd = " /c del \""
0040102A |>lea eax,[ebp-400] ; ||
00401030 |>push eax ; ||ConcatString
00401031 |>call [<&KERNEL32.lstrcatA>] ; |\lstrcatA
00401037 |>push eax ; |/String
00401038 |>call [<&KERNEL32.lstrlenA>] ; |\lstrlenA
0040103E |>lea eax,[ebp+eax-400] ; |
00401045 |>push eax ; |PathBuffer
00401046 |>push 0 ; |/pModule = NULL
00401048 |>call [<&KERNEL32.GetModuleHandleA>] ; |\GetModuleHandleA
0040104E |>push eax ; |hModule
0040104F |>call [<&KERNEL32.GetModuleFileNameA>] ; \GetModuleFileNameA
00401055 |>push 0 ; /ShowState = SW_HIDE
00401057 |>lea eax,[ebp-400] ; |
0040105D |>push eax ; |CmdLine
0040105E |>call [<&KERNEL32.WinExec>] ; \WinExec
00401064 |>xor eax,eax
00401066 |>leave
00401067 \>retn
再手工优化一下:
sub esp,400
push 400
push esp
push 0040301C ;"ComSpec"
call GetEnvironmentVariableA
push 200
push 00403010 ;" /c del \""
push esp
call lstrcatA
push eax
call lstrlenA
add eax,esp
push eax
push 0
call GetModuleHandleA
push eax
call GetModuleFileNameA
push 0
push esp
call WinExec
add esp,400
retn
|
能力值:
( LV8,RANK:130 )
|
-
-
5 楼
自由空间当然是会改变的...举个简单的例子来说。
系统要用到很多的SEH...这样就需要使用堆栈...我们一般能确定的可能只能是在api返回以后,esp指向原来的值(经管现在对于类似strcpy之类的函数也不能确定它一定能返回-_-b),所以对于系统来说低esp的地址空间里面就是他想怎么着就怎么着的地方咯..
|
能力值:
( LV13,RANK:810 )
|
-
-
6 楼
To thebutterfly :Thank~~Boy
To Dwing:我是准备在已经获取长度的后面直接再次连接..字符串..
原来ASM不可以这么直接操作堆践..
最近VC坏了~~被"某人"删除了.不让阿拉写代码了..
只能用ASm直接写..原来不能这么直接操作堆践..
To Lenus:谢谢~~为什么再次sub esp,150就不会被覆盖??
这个如何解释?究竟有多少自由空间??~
谢谢楼上三位GG的~指教
|
能力值:
( LV8,RANK:130 )
|
-
-
7 楼
因为esp永远指向当前堆栈地址,你要用一段堆栈的空间,就应该将esp往前划一些,比如子程序中的局域变量区间。sub esp,150后这150个字节的空间都让你程序占了,其中的内容自然不会再被API改变
|
|
|