首页
社区
课程
招聘
[原创]ESP定律背后的原理之一:0x12FFC4,为什么是这个数
2008-2-5 16:13 10762

[原创]ESP定律背后的原理之一:0x12FFC4,为什么是这个数

2008-2-5 16:13
10762
ESP定律背后的原理之一:0x12FFC4
ESP定律:如果压缩壳执行前后的堆栈会维持平衡,在12FFC0上下读写断点,会中断在OEP的第一条指令push ebp上。那么各位有没有探究过ESP的尾数值为什么不是0xFFFC,而是0x0FFC4?这是由windows源代码的实现所确定的。

Windows创建进程的函数链为kernel32.dll!_CreateProcessInternalW -> … -> kernel32.dll!_BaseProcessStartThunk() -> kernel32.dll!_BaseProcessStart() -> EP

在进入_BaseProcessStartThunk()时,堆栈的状态确实为
+ 0012FFFC   00000000                <- ESP

---------------------------------------------------------<code>
   _BaseProcessStartThunk@8 proc near
xor     ebp, ebp
push    eax
push    0
jmp     _BaseProcessStart@4 ; BaseProcessStart(x)
_BaseProcessStartThunk@8 endp
----------------------------------------------------------</code>

在执行完_BaseProcessStartThunk时,堆栈的状态为
+ 0012FFFC   00000000               
+ 0012FFF8   EAX
+ 0012FFF4   0x00000000             <- ESP
   
---------------------------------------------------------<code>
    _BaseProcessStart proc
push    0Ch
push    offset dword_7C816FE0
call    __SEH_prolog
and     [ebp+ms_exc.disabled], 0
push    4
lea     eax, [ebp+8]
push    eax
push    9
push    0FFFFFFFEh
call    ds:__imp__NtSetInformationThread@16 ; NtSetInformationThread(x,x,x,x)
call    dword ptr [ebp+8]
push    eax             ; dwExitCode
call    _ExitThread@4
nop
nop
nop
---------------------------------------------------------</code>

在执行完BaseProcessStart()后,堆栈的状态为

+ 0012FFFC   0x00000000
+ 0012FFF8   OldEAX -2-> EntryPoint By NtSetInformationThread()
+ 0012FFF4   reserved, inited to 0x00000000
+ 0012FFF0   OldEBP(0x00000000)    <-p- NowEBP
+ 0012FFEC   TryLevel, inited to 0xFFFFFFFF
+ 0012FFE8   ScopeTable
+ 0012FFE4   __except_handler3 in kernel32.dll
+ 0012FFE0   0xFFFFFFFF            <-p- fs:00h
+ 0012FFDC   ExceptionInfo, Parameter of UnhandledExceptionFilter()
+ 0012FFD8   OldESP(0x0012FFC8)
+ 0012FFD4   ExceptionCode, Parameter of kernel32.dll!ExitProcess
+ 0012FFD0   EBX(pPEB)
+ 0012FFCC   ESI
+ 0012FFC8   EDI                   <-p- OldESP
+ 0012FFC4   retaddr in kernel32.dll!_BaseProcessStartThunk
                                               <-p- NowESP

附:
    DWORD   SizeOfStackReserve;                         // 0x48-4b
    DWORD   SizeOfStackCommit;                          // 0x4c-4f
    DWORD   SizeOfHeapReserve;                          // 0x50-53
    DWORD   SizeOfHeapCommit;                           // 0x54-57

这是IOH中的四个域。
Reserved保留的, Committed提交的是两种类型的虚拟内存。
Reserved指这段内存已有用途,不能再被分配;Committed提交的内存指的是已经与物理内存有映射的虚拟内存段(当然也可以被移到硬盘上的缓存文件pagefile.sys中)。因为Stack, Heap这两种类型的内存段都有随着程序的运行尺寸不断增大的特性,所以一开始不必占用太多宝贵的物理内存,当它们用完了,会引发内存异常,windows内存管理器就又为程序分配一部分。

SizeOfStackReserve  程序开始时保留用作堆栈空间的内存段的大小
SizeOfStackCommit   程序开始时在保留的堆栈内存段中与物理内存映射的提交的内存段的大小
SizeOfHeapReserve  程序开始时保留用作堆空间的内存段的大小
SizeOfHeapCommit   程序开始时在保留的堆内存段中与物理内存映射的提交的内存段的大小

[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞7
打赏
分享
最新回复 (8)
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
lunglungyu 1 2008-2-5 16:22
2
0
函数我还沒弄个清楚..
只能顶了
雪    币: 29412
活跃值: (18675)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2008-2-5 17:21
3
0
http://bbs.pediy.com/showthread.php?t=20366

注意:并不是所有程序加载时,ESP的值是0012FFC4,这个值是什么由操作系统决定,将SizeOfStackCOmmit改大ESP就会变,这是因为操作系统从这个页向上找一个足够大地方当作stack了(感谢forgot解释)。
雪    币: 297
活跃值: (27)
能力值: ( LV13,RANK:380 )
在线值:
发帖
回帖
粉丝
tnttools 9 2008-2-5 22:37
4
0
-------------------
注意:并不是所有程序加载时,ESP的值是0012FFC4,这个值是什么由操作系统决定,将SizeOfStackCOmmit改大ESP就会变,这是因为操作系统从这个页向上找一个足够大地方当作stack了(感谢forgot解释)。
-------------------

我曾仔细看过这段话,正是这句话引发了我探究的兴趣,这句话的错误在于错误理解了域SizeOfStackCommit, SizeOfStackReserve的作用,SizeOfStackCommit表示提交到物理内存的虚拟内存的大小,SizeOfStackReserve表示分配给当前程序的大小,注意是大小,不是地址。它们决定了程序初始化时堆栈空间的Commited内存的大小和Reserved内存的大小,但不是地址。

堆栈空间的顶端的值是否固定,我没有逆向windows,所以没有发言权,但不管堆栈空间的顶端是0x00130000,还是0x00120000,还是0x00110000,只要这里我提到的几个函数的源代码实现不变,最后几位的值就不会变:0x0012FFC4, 0x0011FFC4, 0x0010FFC4。
雪    币: 109
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
maokecheng 2008-2-5 22:44
5
0
不是所有的程序吧,00112ffc4   0012ffc0    0013ffc0我就碰到国
雪    币: 297
活跃值: (27)
能力值: ( LV13,RANK:380 )
在线值:
发帖
回帖
粉丝
tnttools 9 2008-2-5 22:55
6
0
操作系统的不同,源代码的实现有可能不同,这个值有可能不同。这个道理,我在文章中说明了。
2K, XP, Vista, Checked Version, Free Version都有可能不同。
我明白你们的意思,我写下来只是想弄清楚在堆栈上面到底存储了些什么东西。并不是探讨堆栈的顶端是否固定的问题。
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
发烧cyrix 2008-2-6 00:40
7
0
我早就有这样的疑问了,到今天也弄不清楚。
雪    币: 29412
活跃值: (18675)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2008-2-7 10:56
8
0
感谢分享心得,有规律的背后必有其原理性,学习你这深究的学习态度。
雪    币: 110
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zenner 2011-9-6 15:26
9
0
栈顶应该是不固定的,不然ESP怎么会一直在变,应该是栈底是否是固定的,以前我也有过这样的疑问,一直纠结于这个问题,这个是操作系统分配管理的了,反正咱们不需要知道栈底地址是否固定,是在哪,PUSH的时候就进栈,POP就出来,知道不知道栈底无所谓了......
堆栈里存的是本地变量,函数返回地址等
新手,说错了的地方请大家指正,以免误导!
游客
登录 | 注册 方可回帖
返回