首页
社区
课程
招聘
[求助]堆践使用的问题.移动堆践指针为什么一些堆践中数据会变动?
2006-4-17 17:13 5738

[求助]堆践使用的问题.移动堆践指针为什么一些堆践中数据会变动?

2006-4-17 17:13
5738
看到Dwing~GG写的那个自删除代码后
决定从新写一下.
但是发现一点点问题..堆践数据会变动??
Google搜了一下可是没有找到任何资料..不得已来这里问一下

;tasm32.exe /mx /m4 /z Melt.asm
;tlink32.exe -x -c -Tpe Melt.obj,,,import32.lib

callw	macro   x
     	extern  x:PROC
     	call x
endm

.586
.model flat
locals @@

.data
	msg	db  ' /c del "',0

.code

Start:
  pushad
  mov ebp,esp
	
  sub esp,150h
  mov esi,esp
	
  push 000434550h
  push 0534d4f43h
  mov eax,esp	;压入ASCII "COMSPEC"					
  push 100h
  push esi
  push eax
  callw GetEnvironmentVariableA
	
  push offset msg
  push esi
  callw lstrcatA	;连接字符串
	
  push esi
  callw lstrlenA;计算字符串长度
  add eax,esi   ;计算出新的堆践指针地址--原字符串堆践地址+字符串长度
  mov esp,eax   ;设置堆践指针						
  push 100h
  push eax		;压入这个参数的时候esi中的数据就变动了Why???
  push 0	
  callw GetModuleFileNameA    ;获取自身路径
	
  mov esp,esi						
  push 0
  push esi	;数据已经全部变动了?为什么会这样..我没有使用到那一块堆践呀
  callw WinExec
			
  mov esp,ebp
  popad
  ret

end Start

阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

收藏
点赞7
打赏
分享
最新回复 (6)
雪    币: 291
活跃值: (208)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
thebutterfly 5 2006-4-18 15:16
2
0
试验过,确实如此
理论上栈指针上方的空间是自由空间, 它的内容是不确定的, 尽管之前已经对它进行了修改, 它的值还是会不断变化
猜想原因可能是:
1.栈指针上方的空间被映射到内存中的另一个页面上了(可能性不大)
2.系统API也会使用堆栈, 可能它们占用了栈指针上方的空间(用于局部变量保存等),导致栈内容发生改变

楼主碰到的情况应该是第2种, 就是调用系统API改变了堆栈自由空间的内容
雪    币: 291
活跃值: (208)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
thebutterfly 5 2006-4-18 15:41
3
0
写了一个小程序测试了一下, 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
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
dwing 1 2006-4-20 09:30
4
0
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
雪    币: 159
活跃值: (339)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
Lenus 3 2006-4-20 18:08
5
0
自由空间当然是会改变的...举个简单的例子来说。
系统要用到很多的SEH...这样就需要使用堆栈...我们一般能确定的可能只能是在api返回以后,esp指向原来的值(经管现在对于类似strcpy之类的函数也不能确定它一定能返回-_-b),所以对于系统来说低esp的地址空间里面就是他想怎么着就怎么着的地方咯..
雪    币: 1272
活跃值: (741)
能力值: ( LV13,RANK:810 )
在线值:
发帖
回帖
粉丝
Anskya 20 2006-4-21 19:49
6
0
To thebutterfly :Thank~~Boy

To Dwing:我是准备在已经获取长度的后面直接再次连接..字符串..
原来ASM不可以这么直接操作堆践..
最近VC坏了~~被"某人"删除了.不让阿拉写代码了..
只能用ASm直接写..原来不能这么直接操作堆践..

To Lenus:谢谢~~为什么再次sub esp,150就不会被覆盖??
这个如何解释?究竟有多少自由空间??~

谢谢楼上三位GG的~指教
雪    币: 222
活跃值: (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
drwch 3 2006-4-27 08:10
7
0
因为esp永远指向当前堆栈地址,你要用一段堆栈的空间,就应该将esp往前划一些,比如子程序中的局域变量区间。sub esp,150后这150个字节的空间都让你程序占了,其中的内容自然不会再被API改变
游客
登录 | 注册 方可回帖
返回