-
-
Stack Part1--- Basic Conception Of Stack
-
发表于: 2007-5-15 13:09 2417
-
Breaking The Secretes ----Dissecting The Stack Part1
Basic Conception Of Stack
Preface:
Stack is one of the most important topics about Windows Memory Management. Every programmar who is willing to understand how eveything does work should have a clear idea of how stack works. Today I am trying to let you understand how stack works in windows, what is "stack overflow" and how to debug stack overflow. Heap overflow is another topics I will cover in the future.
I will cover much basic information of Stack in Part1.
Basic Conception Of Stack.
I'm not going very detail about the basic concepts of stack since I can not explain as well as an article which name is: Writing Stack Based Overflows on Windows by Nish Bhalla. The first part of the article has a clear idea about what's stack, what's Stack Frame, the rule of push and pop, what's the use of ESP and EBP, how function call does work, everything is here :StackBasedOverflows-Windows-Part1.pdf
There are two things that I still need to cover for the basic conception.
Firstly: Stack Frame.
The reason why I talk about Stack Frame is that it's inexplicit discussed in Nish's article. Again, there's a very very cool book which has very clear idea about what is Stack Frame:
Buffer Overflow Attacks, Chapter5. This time I won't redirect you to another URL because I gonna explain myself . But if you are intersted in Buffer Overflow, the ebook is avaliable at:http://forum.eviloctal.com/.
A stack frame is the name given the entire stack section used by a given function,including all the passed arguments, the saved EIP and potentially any other saved
registers, and the local function variables. Actually how does a stack frame look like?
The code below will give you a clear idea about the secrete of stack frame. Since we have several call conversions like std_call and _cdel, now I'm using" __stdcall" in windows.
Mention: The code below is mostly copied from the book: Buffer OverFlow Attacks.
The code below is compiled by Microsoft Visual C++ 6.0
// stackFrame.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
/* stack2.c */
#include
#include
int __stdcall callex(char *buffer, int int1, int int2)
{
/* This prints the input variables to the screen:*/
printf("%s %d %d\n",buffer,int1, int2);
return 1;
}
int main(int argc, char **argv)
{
char buffer[15]="Hello Buffer" /* a 15-byte character buffer with 12 characters filled*/
int int1=1, int2=2; /* two four-byte integers */
callex(buffer,int1,int2); /*call our function*/
return 0;
}
Now let's run windebug, using command "uf callex" to disassembly the function which is callex.
Below is the information in my computer:
10 00401020 55 push ebp
10 00401021 8bec mov ebp,esp
10 00401023 51 push ecx
10 00401024 c745fccccccccc mov dword ptr [ebp-4],0CCCCCCCCh
12 0040102b 8b4510 mov eax,dword ptr [ebp+10h] // EAX = 2
12 0040102e 50 push eax
12 0040102f 8b4d0c mov ecx,dword ptr [ebp+0Ch]
12 00401032 51 push ecx // ECX = 1
12 00401033 8b5508 mov edx,dword ptr [ebp+8]
12 00401036 52 push edx // EDX Point To "Hello Buffer"
12 00401037 68304a4100 push offset stackFrame!__xt_z+0x104 (00414a30)
12 0040103c e8af000000 call stackFrame!printf (004010f0)
12 00401041 83c410 add esp,10h
13 00401044 c745fc00000000 mov dword ptr [ebp-4],0
14 0040104b 8b450c mov eax,dword ptr [ebp+0Ch]
14 0040104e 034510 add eax,dword ptr [ebp+10h]
14 00401051 8945fc mov dword ptr [ebp-4],eax
15 00401054 8b45fc mov eax,dword ptr [ebp-4]
16 00401057 83c404 add esp,4
16 0040105a 3bec cmp ebp,esp
16 0040105c e80f010000 call stackFrame!_chkesp (00401170)
16 00401061 8be5 mov esp,ebp
16 00401063 5d pop ebp
16 00401064 c 20c00 ret 0Ch
The font with Bold is what I have added. Do you understand something?
Everything function call look like this:
Push Ebp
mov ebp, esp
The _stdlcall has two rules: one is parameter pass by from right to left, don't you think so from the EAX ECX AND EDX.
Another thing is: ret 0CH.
16 00401061 8be5 mov esp,ebp
16 00401063 5d pop ebp
16 00401064 c 20c00 ret 0Ch
why 0CH? Think about it, we have 3 parameter passed in, 3*4 = 12 = 0CH, understand?
The picutre below give you a clear idea about the stack frame about the code above:
http://advdbg.org/blogs/advdbg_system/articles/334.aspx
There is one thing I would like to warn you.
The real word about function call may look like the document below:
With a function that uses local variables (and/or stack-based arguments), the compiler needs a mechanism to reference these values on the stack. Typically, this is done in one of two ways:
Access local variables directly from the stack pointer (esp). This is the behavior if FPO optimization is enabled. While this does not require a separate register to track the location of locals and arguments, as is needed if FPO optimization is disabled, it makes the generated code slightly more complicated. In particular, the displacement from esp of locals and arguments actually changes as the function is executed, due to things like function calls or other instructions that modify the stack. As a result, the compiler must keep track of the actual displacement from the current esp value at each location in a function where a stack-based value is referenced. This is typically not a big deal for a compiler to do, but in hand written assembler, this can get a bit tricky.
Dedicate a register to point to a fixed location on the stack relative to local variables and and stack-based arguments, and use this register to access locals and arguments. This is the behavior if FPO optimization is disabled. The convention is to use the ebp register to access locals and stack arguments. Ebp is typically setup such that the first stack argument can be found at [ebp+08], with local variables typically at a negative displacement from ebp.
I hate omit frame pointers because it makes everything much more complicated. You can find the optimized options which is /oy in Visual C++ 6.0 2003 and 2005, don’t ask me more, I don’t know about 5.0 or early version, because when they are alive, I was a boy.
In the real world, the compile is trying to optimize code with …. Whatever it does, who cares. Every compile has its own method to implement it, anyway, it makes the concept about Stack Frame does not work anymore. It seems the URL below may give you some more information about FIO:
http://www.nynaeve.net/?p=91
Also refer to here
Anyway, I don’t know about it though it does exist. I suggest do not enable this option for ever because it makes it much more difficult to debug your program unless performance is so important for your application.
No more magic about Stack Frame. No more discussion either.
Let's come back, what about the another basic conception?
How many stack do we have? Where are they? Actually very very little documentation talk about this secrets:
The reality for micorosoft 32 bits Windows is: Stack is per- threading. That means every thread has it's own stack.
How about 16 bits Windows and 64 bits? Honestly I don't know because I'm only a beginner to windows kernel too.
Let's using windebug again to see where are they:
0:000> !address -RegionUsageStack
00040000 : 00040000 - 000fc000
Type 00020000 MEM_PRIVATE
Protect 00000000
State 00002000 MEM_RESERVE
Usage RegionUsageStack
Pid.Tid f88.ff4
0013c000 - 00001000
Type 00020000 MEM_PRIVATE
Protect 00000104 PAGE_READWRITE | PAGE_GUARD
State 00001000 MEM_COMMIT
Usage RegionUsageStack
Pid.Tid f88.ff4
0013d000 - 00003000
Type 00020000 MEM_PRIVATE // This is our memory Stack.
Protect 00000004 PAGE_READWRITE
State 00001000 MEM_COMMIT
Usage RegionUsageStack
Pid.Tid f88.ff4
The stack starts from 0013d000 size 00003000 (12kb.)
How do windebug know this? Good question. This is consulting another windows secret structure, yes, you are correct, TIB.
Continue using Windebug:
0:000> dt -v _NT_TIB $teb
struct _NT_TIB, 8 elements, 0x1c bytes
+0x000 ExceptionList : 0x0013ffb0 struct _EXCEPTION_REGISTRATION_RECORD, 2 elements, 0x8 bytes
+0x004 StackBase : 0x00140000
+0x008 StackLimit : 0x0013d000
+0x00c SubSystemTib : (null)
+0x010 FiberData : 0x00001e00
+0x010 Version : 0x1e00
+0x014 ArbitraryUserPointer : (null)
+0x018 Self : 0x7ffde000 struct _NT_TIB, 8 elements, 0x1c bytes
See stackLimit is 0013d000 and 0013d000 + 0x3000 = 0x00140000
How can I get information without debug?
Simply two assembly:
mov EAX,fs:[4];
mov EAX, fs:[8];
How can I get TIB?
Please refer to the "Under The Hood": http://www.microsoft.com/msj/archive/S2CE.aspx
Where are we now?
We have discussed basic concetion of stack, you should be clear about where our stack are in momeory?
What's happending throughout a function call, how push pop ret works.
What's The Next?
Look at the picture above: familiar with it? Yes, it's Process Explorer.
How does it work, how can I get call stack information?
Cool questions. There we are:
Section2: Tracing The Call Stack Tree.
Orginal Address:http://blog.csdn.net/SGYHMSLY/archive/2007/05/05/1596778.aspx
MSN: SGYHMSLY@HOTMAIL.COM
EMAIL:SGYHM@163.COM
Written By Jim.Secrets.
2007.05.04
Basic Conception Of Stack
Preface:
Stack is one of the most important topics about Windows Memory Management. Every programmar who is willing to understand how eveything does work should have a clear idea of how stack works. Today I am trying to let you understand how stack works in windows, what is "stack overflow" and how to debug stack overflow. Heap overflow is another topics I will cover in the future.
I will cover much basic information of Stack in Part1.
Basic Conception Of Stack.
I'm not going very detail about the basic concepts of stack since I can not explain as well as an article which name is: Writing Stack Based Overflows on Windows by Nish Bhalla. The first part of the article has a clear idea about what's stack, what's Stack Frame, the rule of push and pop, what's the use of ESP and EBP, how function call does work, everything is here :StackBasedOverflows-Windows-Part1.pdf
There are two things that I still need to cover for the basic conception.
Firstly: Stack Frame.
The reason why I talk about Stack Frame is that it's inexplicit discussed in Nish's article. Again, there's a very very cool book which has very clear idea about what is Stack Frame:
Buffer Overflow Attacks, Chapter5. This time I won't redirect you to another URL because I gonna explain myself . But if you are intersted in Buffer Overflow, the ebook is avaliable at:http://forum.eviloctal.com/.
A stack frame is the name given the entire stack section used by a given function,including all the passed arguments, the saved EIP and potentially any other saved
registers, and the local function variables. Actually how does a stack frame look like?
The code below will give you a clear idea about the secrete of stack frame. Since we have several call conversions like std_call and _cdel, now I'm using" __stdcall" in windows.
Mention: The code below is mostly copied from the book: Buffer OverFlow Attacks.
The code below is compiled by Microsoft Visual C++ 6.0
// stackFrame.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
/* stack2.c */
#include
#include
int __stdcall callex(char *buffer, int int1, int int2)
{
/* This prints the input variables to the screen:*/
printf("%s %d %d\n",buffer,int1, int2);
return 1;
}
int main(int argc, char **argv)
{
char buffer[15]="Hello Buffer" /* a 15-byte character buffer with 12 characters filled*/
int int1=1, int2=2; /* two four-byte integers */
callex(buffer,int1,int2); /*call our function*/
return 0;
}
Now let's run windebug, using command "uf callex" to disassembly the function which is callex.
Below is the information in my computer:
10 00401020 55 push ebp
10 00401021 8bec mov ebp,esp
10 00401023 51 push ecx
10 00401024 c745fccccccccc mov dword ptr [ebp-4],0CCCCCCCCh
12 0040102b 8b4510 mov eax,dword ptr [ebp+10h] // EAX = 2
12 0040102e 50 push eax
12 0040102f 8b4d0c mov ecx,dword ptr [ebp+0Ch]
12 00401032 51 push ecx // ECX = 1
12 00401033 8b5508 mov edx,dword ptr [ebp+8]
12 00401036 52 push edx // EDX Point To "Hello Buffer"
12 00401037 68304a4100 push offset stackFrame!__xt_z+0x104 (00414a30)
12 0040103c e8af000000 call stackFrame!printf (004010f0)
12 00401041 83c410 add esp,10h
13 00401044 c745fc00000000 mov dword ptr [ebp-4],0
14 0040104b 8b450c mov eax,dword ptr [ebp+0Ch]
14 0040104e 034510 add eax,dword ptr [ebp+10h]
14 00401051 8945fc mov dword ptr [ebp-4],eax
15 00401054 8b45fc mov eax,dword ptr [ebp-4]
16 00401057 83c404 add esp,4
16 0040105a 3bec cmp ebp,esp
16 0040105c e80f010000 call stackFrame!_chkesp (00401170)
16 00401061 8be5 mov esp,ebp
16 00401063 5d pop ebp
16 00401064 c 20c00 ret 0Ch
The font with Bold is what I have added. Do you understand something?
Everything function call look like this:
Push Ebp
mov ebp, esp
The _stdlcall has two rules: one is parameter pass by from right to left, don't you think so from the EAX ECX AND EDX.
Another thing is: ret 0CH.
16 00401061 8be5 mov esp,ebp
16 00401063 5d pop ebp
16 00401064 c 20c00 ret 0Ch
why 0CH? Think about it, we have 3 parameter passed in, 3*4 = 12 = 0CH, understand?
The picutre below give you a clear idea about the stack frame about the code above:
http://advdbg.org/blogs/advdbg_system/articles/334.aspx
There is one thing I would like to warn you.
The real word about function call may look like the document below:
With a function that uses local variables (and/or stack-based arguments), the compiler needs a mechanism to reference these values on the stack. Typically, this is done in one of two ways:
Access local variables directly from the stack pointer (esp). This is the behavior if FPO optimization is enabled. While this does not require a separate register to track the location of locals and arguments, as is needed if FPO optimization is disabled, it makes the generated code slightly more complicated. In particular, the displacement from esp of locals and arguments actually changes as the function is executed, due to things like function calls or other instructions that modify the stack. As a result, the compiler must keep track of the actual displacement from the current esp value at each location in a function where a stack-based value is referenced. This is typically not a big deal for a compiler to do, but in hand written assembler, this can get a bit tricky.
Dedicate a register to point to a fixed location on the stack relative to local variables and and stack-based arguments, and use this register to access locals and arguments. This is the behavior if FPO optimization is disabled. The convention is to use the ebp register to access locals and stack arguments. Ebp is typically setup such that the first stack argument can be found at [ebp+08], with local variables typically at a negative displacement from ebp.
I hate omit frame pointers because it makes everything much more complicated. You can find the optimized options which is /oy in Visual C++ 6.0 2003 and 2005, don’t ask me more, I don’t know about 5.0 or early version, because when they are alive, I was a boy.
In the real world, the compile is trying to optimize code with …. Whatever it does, who cares. Every compile has its own method to implement it, anyway, it makes the concept about Stack Frame does not work anymore. It seems the URL below may give you some more information about FIO:
http://www.nynaeve.net/?p=91
Also refer to here
Anyway, I don’t know about it though it does exist. I suggest do not enable this option for ever because it makes it much more difficult to debug your program unless performance is so important for your application.
No more magic about Stack Frame. No more discussion either.
Let's come back, what about the another basic conception?
How many stack do we have? Where are they? Actually very very little documentation talk about this secrets:
The reality for micorosoft 32 bits Windows is: Stack is per- threading. That means every thread has it's own stack.
How about 16 bits Windows and 64 bits? Honestly I don't know because I'm only a beginner to windows kernel too.
Let's using windebug again to see where are they:
0:000> !address -RegionUsageStack
00040000 : 00040000 - 000fc000
Type 00020000 MEM_PRIVATE
Protect 00000000
State 00002000 MEM_RESERVE
Usage RegionUsageStack
Pid.Tid f88.ff4
0013c000 - 00001000
Type 00020000 MEM_PRIVATE
Protect 00000104 PAGE_READWRITE | PAGE_GUARD
State 00001000 MEM_COMMIT
Usage RegionUsageStack
Pid.Tid f88.ff4
0013d000 - 00003000
Type 00020000 MEM_PRIVATE // This is our memory Stack.
Protect 00000004 PAGE_READWRITE
State 00001000 MEM_COMMIT
Usage RegionUsageStack
Pid.Tid f88.ff4
The stack starts from 0013d000 size 00003000 (12kb.)
How do windebug know this? Good question. This is consulting another windows secret structure, yes, you are correct, TIB.
Continue using Windebug:
0:000> dt -v _NT_TIB $teb
struct _NT_TIB, 8 elements, 0x1c bytes
+0x000 ExceptionList : 0x0013ffb0 struct _EXCEPTION_REGISTRATION_RECORD, 2 elements, 0x8 bytes
+0x004 StackBase : 0x00140000
+0x008 StackLimit : 0x0013d000
+0x00c SubSystemTib : (null)
+0x010 FiberData : 0x00001e00
+0x010 Version : 0x1e00
+0x014 ArbitraryUserPointer : (null)
+0x018 Self : 0x7ffde000 struct _NT_TIB, 8 elements, 0x1c bytes
See stackLimit is 0013d000 and 0013d000 + 0x3000 = 0x00140000
How can I get information without debug?
Simply two assembly:
mov EAX,fs:[4];
mov EAX, fs:[8];
How can I get TIB?
Please refer to the "Under The Hood": http://www.microsoft.com/msj/archive/S2CE.aspx
Where are we now?
We have discussed basic concetion of stack, you should be clear about where our stack are in momeory?
What's happending throughout a function call, how push pop ret works.
What's The Next?
Look at the picture above: familiar with it? Yes, it's Process Explorer.
How does it work, how can I get call stack information?
Cool questions. There we are:
Section2: Tracing The Call Stack Tree.
Orginal Address:http://blog.csdn.net/SGYHMSLY/archive/2007/05/05/1596778.aspx
MSN: SGYHMSLY@HOTMAIL.COM
EMAIL:SGYHM@163.COM
Written By Jim.Secrets.
2007.05.04
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
看原图
赞赏
雪币:
留言: