ESP interpretation in the Assembly

Source: Internet
Author: User

Recently, when I was learning about encryption and decryption and used od for disassembly, I studied compilation again .. In particular, we made an in-depth study on ESP .. The following information is found on the Internet. Let's take a look at it here ..

There are many registers in the register, although their functions and use are no different, but in the long-term programming and use, in programmer habits, each register has been assigned a special meaning by default, such as eax, ECx, and so on. In the Win32 environment, the EBP register is used with the ESP value stored after the call is entered, so that the ESP value can be returned when the call is exited to achieve stack balancing.
The application has previously said:
The OEP of the original program usually starts with push EBP, mov EBP, and esp. I don't need to say that everyone knows that the meaning of these two sentences is to replace ESP with EBP, as a pointer to the stack.
Why? Why is the beginning of almost every program? If we have written functions such as C, we should be clear that the program starts with a main function main, the most important thing in the function access process is to ensure the balance of the stack, and the way to maintain the balance in the Win32 environment is as follows:
1. Let EBP Save the ESP value;
2. Call at the end
Two forms mean one thing.
The advantage of this is that you do not need to consider the number of ESP equal to, the number of push times, and the number of pop times, because we know that the EBP contains the ESP value at the beginning.
2. Extended ESP Law
When looking for OEP, often broken HW ESP-4 is not successful, in addition to the shell code to delete the hardware breakpoint, it is very likely that when the shell code is running to the OEP, its ESP is no longer the ESP (12ffc4) at the EP. In this case, the disconnection is of course unsuccessful.
The key is how to find the stack value when the shell reaches the OEP.
Here, the key to our application is
Push EBP
MoV EBP, esp ---- the key is this sentence
Let me explain that when the program reaches OEP, the push EBP statement is a ESP-4 for the ESP value, and then the ESP-4 is assigned to EBP, the value of the EBP register used to save the ESP value in this "Top program" will never change. Although it may change temporarily after entering the sub-call (used for the stack balance of the sub-call), after exiting, the original EBP value will be restored according to * Pop EBP.
Taking this sentence as a breakthrough means that as long as we can break through the "top-Layer Program", we can observe the ESP value of EBP when the shell is between JMP and OEP.
3. Practice
Let's take a look at the pespin1.1 shell. In the pespin1.0 shell, we can easily find the place of stolen code using HW 12ffc0, but we won't be able to find it by pespin1.1. HW 12ffc0 cannot be disconnected.
Now we will use this extended ESP law to load the program and come to the final exception.
0040ed85 2bdb sub EBX, EBX // stop here
0040ed87 64: 8f03 pop dword ptr fs: [EBX]
0040ed8a 58 pop eax
0040ed8b 5d pop EBP
0040ed8c 2bff sub EDI, EDI
0040ed8e EB 01 JMP short pespin1 _. 0040ed91
0040ed90 c466 81 les ESP, fword ptr ds: [esi-7F]
I used the memory breakpoint method to come to the foep.
004010d3 0000 add byte ptr ds: [eax], Al
004010d5 0000 add byte ptr ds: [eax], Al
004010d7 0000 add byte ptr ds: [eax], Al
004010d9 0000 add byte ptr ds: [eax], Al
004010db 0000 add byte ptr ds: [eax], Al
004010dd 0000 add byte ptr ds: [eax], Al
004010df 75 1B jnz short pespin1 _. 004010fc // here is foep
004010e1 56 push ESI
004010e2 ff15 99f44000 call dword ptr ds: [40f499]
004010e8 8bf0 mov ESI, eax
004010ea 8a00 mov Al, byte ptr ds: [eax]
Well, here is the "top-Layer Program". Let's look at the registers.
Eax 00141e22
ECX 0040c708 pespin1 _. 0040c708
EdX 0040c708 pespin1 _. 0040c708
EBX 0040c708 pespin1 _. 0040c708
ESP 0012f978
EBP 0012f9c0 // note this
ESI 00141ee0
EDI 0040e5cd pespin1 _. 0040e5cd
EIP 004010df pespin1 _. 004010df
See, EBP = 0012f9c0. Let's imagine how this value is obtained.
First, it must be through mov ESP, EBP, that is to say, ESP is 0012f9c0 at this time. However, there is also a push EBP above, that is, esp should be 0012f9c4 when it reaches OEP. Now, we can quickly find the stolen code.
An error occurred while stopping again.
0040ed85 2bdb sub EBX, EBX // stop here
0040ed87 64: 8f03 pop dword ptr fs: [EBX]
0040ed8a 58 pop eax
0040ed8b 5d pop EBP
0040ed8c 2bff sub EDI, EDI
0040ed8e EB 01 JMP short pespin1 _. 0040ed91
0040ed90 c466 81 les ESP, fword ptr ds: [esi-7F]
Then disconnected HW 0012f9c0, F9 run, come here
0040d8fb 61 popad
0040d8fc 55 push EBP
0040d8fd EB 01 JMP short pespin1 _. 0040d900 // stop here
0040d8ff 318b eceb01ac xor dword ptr ds: [EBX + ac01ebec], ECx
0040d905 83ec 44 sub ESP, 44
0040d908 EB 01 JMP short pespin1 _. 0040d90b
0040d90a 72 56 JB short pespin1 _. 0040d962
0040d90c EB 01 JMP short pespin1 _. 0040d90f
0040d90e 95 xchg eax, EBP
0040d90f ff15 6cf34000 call dword ptr ds: [40f36c]
0040d915 EB 01 JMP short pespin1 _. 0040d918
So we quickly found the location of stolen code.
4. Summary
The above method can summarize the following steps:
(1). directly or indirectly disconnected from the "top program.
(2) obtain the EBP value of the "top program.
(3). Use two fixed statements initialized by the program to find the stack value from shell JMP to OEP. This method has great limitations, because only the VC and Delphi programs use the beginning of this initialization.
However, there are still many methods in addition to memory breakpoints to find the "Upper-Layer Program" method. For example, for VC, using BP exitprocess is also a good breakpoint, and EBP values can be obtained directly.
5. Later
It turns out that this method has a strong precondition. It is not a very universal method. I didn't want to propose it separately, however, for the anti-esp law of the jney2 brother, this solution is a solution.
Of course, there are more ways to do this. Here I just want to say that many things have yundun, and there is no way to be free from loopholes. I just hope this article will give you a wide range of ideas, it plays a leading role.
When a function is called
The original EBP value has been pushed to the stack (located at the top of the stack), and the new EBP just points to the top of the stack.
At this time, the EBP register is already in a very important position, which stores an address in the stack (the top of the stack after the original EBP enters the stack ),
From this address as the benchmark, the returned address and parameter value can be obtained up (at the bottom of the stack), and the local variable value of the function can be obtained down (at the top of the stack,
This address stores the EBP value of the previous function call!

10 variable assignment,

Whether the assignment process of variables is very important in algorithm research. Because the variable is accessed with an address, the code for BBB, such as mov [AAA], is usually used to modify the variable (the address is AAA, or AAA is the value of AAA when the address is a register) is BBB (BBB is the value of BBB when the BBB is a register ).
The variables described in the subroutine are called local variables, and the scope of local variables is the subroutine where they are located. From the assembly point of view, a local variable is a temporary stack cache that is used up for release.
00401000>/$ 6a 04 Push 4;/arg2 = 00000004
00401002 |. 6a 03 Push 3; | arg1 = 00000003
00401004 |. E8 16000000 call 0040101f;/add.0040101f
00401009 |. 8bd8 mov EBX, eax
0040100b |. 6a 00 push 0;/exitcode = 0
0040100d/. ff15 00204000 call [<& kernel32.exitprocess>];/exitprocess

0040101f/$55 push EBP; protects the original EBP pointer on site
00401020 |. 8bec mov EBP, esp; set a new EBP pointer pointing to the top of the stack
00401022 |. 83ec 04 Sub ESP, 4; allocate all space for local variables
00401025 |. 8b45 0C mov eax, [EBP + C]; call parameter 2
00401028 |. 8b5d 08 mov EBX, [EBP + 8]; call parameter 1
0040102b |. 895d FC mov [ebp-4], EBX; parameter 1 put in local variable
0040102e |. 0345 FC add eax, [ebp-4]; parameter 2 addition to local variables
00401031 |. 83c4 04 add ESP, 4; release all space of the local variable
00401034 |. 5D pop EBP; restore the EBP pointer on site
00401035/. C2 0800 retn 8

When analyzing assembly code, there are always countless calls. For these calls, we should try to judge the call function based on the parameters passed before the call and the return value of the call. The operation of passing parameters must be coordinated by the function caller and the function itself. The computer provides a data structure called Stack to support parameter transfer.
When there are more than one parameter, the parameter is pushed to the stack in what order. Who will recover the stack after the function is called. In advanced languages, the two problems are described through the function call convention. Common call conventions include:
[Example] Call the Test2 (par1, par2) function according to _ stdcall)
Push par2; parameter 2
Push par1; parameter 1
Call Test2;
Push EBP to protect the original EBP pointer on site
MoV EBP, esp; set a new EBP pointer to the top of the stack
MoV eax, [EBP + 0C]; call parameter 2
MoV EBX, [EBP + 08]; call parameter 1
Sub ESP, 8; if a function uses a local variable, leave some space in the stack.
Add ESP, 8; release the stack occupied by local variables
Pop EBP; recovery site EBP pointer
RET 8; Return (equivalent to ret; add ESP, 8)
Its stack call:

1.2 Return Value

When debugging a program, do not follow up with the call. All the push actions and register operations performed before the call may be passing parameters to the function, function return values are generally placed in eax. Of course, this value may be a pointer pointing to a data structure. From the assembly point of view, there are mainly the following forms:

1) return function values through registers;
2) return function values by referencing parameters;
3) return function values through global variables;
4) return the function value through the processor flag;
Generally, the value returned by the retrun operator is placed in the eax register. If the result exceeds the bit capacity of the Register, the 32-bit high value of the result is loaded into the edX register. If a structure containing several hundred bytes or an approximate size object is returned, the compiler will pass an implicit parameter to the function without telling the program, this Pointer Points to the saved return result.
If a * = 4, shl a and 2 can be used. The left shift of the logic is equivalent to the square of 2.

; CBW (convert byte to word): expands Al to ax
; Cwde (convert Word to extended double): expands ax to eax
; CDQ (convert doubleword to quadword): expands eax to 64-digit edX: eax
; CWD (convert Word to doubleword): expands ax to DX: ax

If a/= 2, sar a and 1 can be used to shift right to the power of 1 except 2

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: 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.