[Assembly Learning] For beginners in assembly-function call stack Change Analysis (from hacker situation)

Source: Internet
Author: User
When talking to a friend about the stack, I wrote this text. By the way, I sent it here to show you what I needed.
Compilation of a headache for beginners
//////////////////////////////////////// ////////////////////////////
For example, we have a C function 1 # include <stdio. h>
2 long test (int A, int B)
3 {
4 A = a + 1;
5 B = B + 100;
6 Return A + B;
7}
8 void main ()
9 {
10 printf ("% d", test (1000,2000 ));
11}
12

Writing a 32-bit assembly is like this 1; /**///////////////////////////////////// //////////////////////////////////////// //////////////////////////
2.386
3. Module flat, stdcall; here, stdcall is used as the function parameter to press the stack from the last one, and the called function is responsible for clearing the stack.
4 Option Casemap: none; case sensitive
5
6. Introduce delib msvcrt. Lib. Here we introduce the class library equivalent to # include <stdio. h>.
7 printf proto C: DWORD,: vararg; this is to declare the function header we will use. Then the assembler will automatically find it in msvcrt. Lib.
8;: The parameters behind the vararg table are unknown because C is like printf (const char *,);
9. This function is not called to clear the stack because it does not know how many parameters there are.
10; instead, the caller is responsible for clearing the stack.
11. Data
12 sztextfmt byte '% d', 0; this is used for type conversion. It is the same as that of C, and the character is of the byte type.
13a DWORD 1000; hypothesis
14B DWORD 2000; the processed values are all double-character, no difference between int and long.
15
16; /**///////////////////////////////////// //////////////////////////////////////// /////////////
17. Code
18
19_test proc a: DWORD, B: DWORD
20 push EBP
21 mov EBP, ESP
22 mov eax, dword ptr ss: [EBP + 8]
23 add eax, 1
24 mov edX, dword ptr ss: [EBP + 0ch]
25 add EDX and 100
26 add eax, EDX
27 pop EBP
28 retn 8
29_test endp
30
31_main proc
32 push dword ptr ds: B; disassembly we can see that B is not B, but a [*****] Number DWORD PTR is what we have in DS (data segment) set [*****]
33; the start value is a double-character length value.
34 push dword ptr ds: A; the corresponding byte PTR *** is to take a byte, for example, mov Al, byte ptr ds: sztextfmt.
35; get % instead of D.
36 call _ Test
37. Push eax; assume that the address of push eax is XXX.
38 push offset sztextfmt
39 call printf
40 add ESP, 8
41 RET
42_main endp
43end _ main
44
45; /**///////////////////////////////////// //// // The stack changes are described below
46

The first thing to understand is that the operation of the stack segment SS can only use ESP or EBP registers, other registers eax ebx edx and so on are not enough, and ESP always points to the top of the stack EBP used in the stack segment

Inner addressing
Push command is pressure stack ESP = ESP-4
Pop command is output stack ESP = ESP + 4
Assume that the initial stack of the main function is ESP = 400.
Push dword ptr ds: B; ESP-4 = 396-> the value is 2000 is the value of B
Push dword ptr ds: A; ESP-4 = 392-> the value is 1000 is the value of
Call test; ESP-4 = 388-> what is the value in it? This is too important because the principle we use to find game functions lies.
The value is the address of the next command in the call test command-> that is, the address of push eax ××××

Go to the test function.

Push EBP; ESP-4 = 384-> it saves the current EBP value instead of clearing EBP
MoV EBP, esp; here ESP = 384 is not changed, but EBP = ESP = 384, why do we need to do this because we need to use EBP to find parameters in the stack
MoV eax, dword ptr ss: [EBP + 8]; disassembly is like this. Why is a [EBP + 8 ]?
Let's look up the address 392 in the stack and save the value of A. Here EBP = 384 plus 8 is exactly 392.
In this way, the passed 1000 is taken out. eax = 1000
Add eax, 1; equivalent to a + 1 eax = 1001
MoV edX, dword ptr ss: [EBP + 0ch]; 0ch = 12 in the same way, the address pointing to the stack here is 384 + 12 = 396, that is, 2000, EDX = 2000
Add edX, 100; equivalent to B + 100 edX = 2100
Add eax, EDX; eax = eax + EDX = 1001 + 2100 = 3101 here eax has saved the final result
Because Win32 Assembly generally uses eax to return results, if the final result is not in eax, put it in eax.
For example, if my results are stored in the nret variable, the mov eax, dword ptr nret should be the last one.
Pop EBP; esp = 384 + 4 = 388, and the value stored in the top 384 of the stack is saved to EBP to restore the original value of EBP.
In the beginning, we pressed the EBP value to the stack. mov EBP and ESP have changed the value of EBP. Restoring here ensures the stack balance.
Retn 8; esp + 8-> 396 here, retn is called by the system. We don't need to worry that the system will automatically direct the EIP pointer to the next instruction of the original call.
Because the system automatically restores the call pressure stack, esp + 4 restores the call pressure stack.
At this time, esp = 400 is the stack at the beginning of the function call, that is, the stack before the function call is the same as that after the function call.
; This is the stack balance
Because retn 8 in stdcall indicates that the caller is responsible for restoring the stack, and the test function is called, the caller is responsible for adding the stack to 8 and the call function is automatically restored.

Push eax; ESP-4 = 396-> contains the eax value 3101
As shown above, eax stores the returned value. We want to pass it to printf through Stack
Push offset sztextfmt; ESP-4 = 392-> contains the address of sztextfmt, that is, the pointer in C, there is actually nothing to pass the string, we pass is the address
DWORD is the most widely used string type in the Assembly, whether in assembly or C. The parameter passing in the game is much simpler.
Call printf; ESP-4 = 388-> contains the address of the next instruction
Add ESP, 8; esp + 8 = 400 restores the stack status before calling printf
As mentioned above, because the parameters following printf are vararg and the type is called to restore the stack, there are no commands such as retn 8 in printf.
The caller is responsible for clearing the stack. Main is the caller. So the following sentence is "add esp". 8. Restore the stack before calling printf.
While the pressure stack in call printf is restored by the system and completed by the system. We don't need to worry about it, but it is enough to know that it is saved as the return address.

;
RET; the main function returns other things because the system automatically handles the tasks.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.