View the buffer overflow attack mechanism in the memory

Source: Internet
Author: User

When an application is running, its memory image can be divided into three parts: code segment, Data Segment and stack segment.

 

1. the code segment corresponds to the Text Section in the running file, where the code of the program is stored. This Section is generally marked as read-only in the memory, any command that attempts to modify the data in this segment will cause a Segmentation Violation error. the worker area can be shared by multiple processes that run the executable file. 2. the Data segment corresponds to the Data Section in the running file, which can be divided into the INIT Section and the non-initialized Data Section. The initialized Data (INIT) the zone is used to store the initialization data in the executable file, and the non-initialization data (BSS) zone is used to store the static variables of the program. The BSS zone memory is initialized to zero. 3. the stack segment is the object we will focus on below. To illustrate the stack segment, we must first explain the stack frame of the function. To illustrate the stack frame of the function, we 'd better look at a small example: void proc (int I)

{

Int local;

Local = I;

}

Int main (void)

{

Proc (2 );

Return 0;

}

After the code is compiled, the disassembly result is roughly (here, the core part of the disassembly is extracted to illustrate the stack segment, and the actual situation is more complex): main: push 2

 

Call proc

 

...

 

Proc: push ebp

 

Mov ebp, esp

 

Sub esp, 4

 

Mov eax, [ebp + 08]

 

Mov [ebp-4], eax

 

Add esp, 4

 

Pop ebp

 

Ret 4

 

Let's take a bit of patience to analyze this code: main: push 2

Call proc

First, press parameter 2 required for function calling into the stack, and then call proc

Note: When calling proc, the system will automatically press the address returned by the function, that is, the address of the next statement (return 0) of the main function, to the stack. Therefore, the situation of the stack segment is as follows: (high-end memory) + ------------------- ++ 2 ++ --------------- ++ the return address of the function RET ++ ----------------- + (bottom of memory)

Next, proc: push ebp

Mov ebp, esp

We know that ebp is the base address register of the stack, esp is the stack pointer register, esp points to the top of the stack. First, store the original value of ebp into the stack, and then assign the value of esp to ebp.

Sub esp, 4

4 (A 32-bit server, where an int occupies four bytes) is subtracted from esp, and an int location is reserved for the local variable. mov eax, [ebp + 08]

Mov [ebp-4], eax

Is local = I; at this time, the image of the stack segment in the memory is: (high-end memory) + ---------------- + + (I) 2 ++ ---------------- +

+ Return address: RET ++ ---------------- ++ original ebp ++ ------------------ + <-current ebp + (local) 2 ++ ------------------ + <-current esp (low memory) add esp, 4

Pop ebp

Ret 4

First, esp + 4, reclaim the space of the local variable, pop ebp, restore the original ebp value, and finally ret 4, get the return address from the stack, change the EIP to this address, add esp to 4 to reclaim the space occupied by parameters. the above analysis shows the stack frame structure of the called function when calling a function. To sum up, it is: (high-end memory) + -------------------- ++ parameter 1 ++ -------------------- ++ parameter 2 ++ -------------------- ++ ...... ++ Response ++ parameter N ++ ---------------------- ++ RET ++ ---------------------- ++ original ebp ++ ---------------------- ++ local param N ++ -------------------- ++ ...... ++ -------------------- ++ Local param two ++ ---------------------- ++ local param one ++ ---------------------- + (low-end memory) can be seen, the stack frame created during function calling contains the following information: I) space allocated for the local variables that call the function.

Ii) return address of the call function. Whether the return address is stored in the stack frame of the call function or the stack frame of the called function depends on the implementation of different systems.

Iii) stack frame information of the call function, that is, bsp.

Iv) The space allocated for the parameters of the called function depends on the implementation of different systems. 4. at this point, the core part has been finished. Let's concatenate the segments and then look at the memory when the program is running: Let's assume there is a program, and its function call sequence is as follows.

Main (...)-> func_1 (...)-> func_2 (...)-> func_3 (...)

That is, the main function calls func_1, func_1, func_2, and func_3.

When a program is transferred to the memory for running by the operating system, the corresponding process's memory image is shown in: (high memory) + -------------------- ++ memory that does not need to be concerned ++ -------------------- ++ Env String (Environment Variable String) ++ -------------------- ++ Argv String (command line parameter String) ++ -------------------- ++ Env Pointers (Environment Variable pointer) ++ ---------------------- ++ Argv Pointers (command line parameter pointer) ++ -------------------- ++ Argc (number of command line parameters) ++ coding ++ main function stack frame ++ ---------------------- ++ func_1 stack frame ++ ---------------------- ++ func_2 stack frame ++ -------------------- ++ func_3 stack frame ++ -------------------- ++ Stack) ++ -------------------- ++ Heap (Heap) ++ ---------------------- ++ BSS data (non-initialized data zone) ++ -------------------- ++ INIT data (initialized data zone) ++ -------------------- ++ Text (primary area) ++ ---------------------- + (low-end memory) 5. the Buffer Overflow mechanism is described as follows:

Void function (char * str)

{

Char buffer [16];

Strcpy (buffer, str );

}

Void main ()

{

Char large_string [256];

Int I;

For (I = 0; I <255; I ++)

Large_string [I] = 'a ';

Function (large_string );

}

 

The Buffer Overflow problem exists in this program. we can see that the string length passed to the function is much larger than the buffer, and the function directly uses strcpy to merge the long string into the buffer without any length verification. if you execute this program, the system will report a Segmentation Violation error. next, let's analyze why this happens?

First, let's take a look at the situation in the stack when strcpy is not executed: (high-end memory) + ---------------- ++ large_string address ++ ---------------- +

+ Return address: RET ++ ---------------- ++ original ebp ++ ------------------ + <-current ebp + ...... ++ ---------------- ++ ...... ++ ---------------- + <-When strcpy is executed in the current esp (low-end memory), the program will merge 256 Bytes into the buffer, but the buffer can only accommodate 16 Bytes, what will happen at this time? Because the C language does not perform a boundary check, the result is that the content of the 250 bytes after the buffer is overwritten, which naturally includes the ebp, ret address, and large_string address. because the ret address is changed to 0x41414141 h at this time, when the process ends, it will return to the 0x4141414141h address for further execution, however, the system reports Segmentation Violation because the address is not within the range of the virtual storage space actually used by the program.

 

From the above example, we can use Buffer Overflow to change the return address of the stored process in the stack, thus changing the process of the entire program, turn it to any place we want it to go. this provides hackers with an opportunity. The most common method is to embed a piece of code in a long string and overwrite the return address of the process to the address of the Code, in this way, when the process returns, the program starts to execute this self-compiled code. in general, this code runs a Shell program (such as \ bin \ sh). Because of this, when we intrude into a program with Buffer Overflow defects and suid-root attributes, we will get a shell with root permissions, in which we can do anything. Therefore, this code is generally called Shell Code.6. buffer overflow occurs in the stack in front of the Heap (Heap) or BBS (non-initialized data) zone, because the space of the local variable of the function is allocated to the stack. We know that the process's dynamic application for memory occurs in Heap (Heap. the non-initialized data (BSS) area is used to store static variables of the program. The memory is initialized to zero.

I) If the buffer memory space is obtained through dynamic application in the function (for example, applying using the malloc () function ), in the stack frame of the function, the pointer is allocated to the memory space allocated to the Heap (Heap. in this case, overflow occurs in the (Heap) Heap, and it seems almost impossible to overwrite the corresponding function return address. the possibility of using this situation depends on the specific situation, but it is not impossible.

Ii) if the buffer is defined as static in the function, the buffer memory space is located in the non-initialized (BBS) area, which is similar to the Heap (Heap, exploitation is possible. however, there is another special case, that is, it can be used to overwrite the function pointer, so that the process can call the corresponding function to call the code we specified. 7. the program UNIX with the suid-root attribute allows other users to execute the file with the user ID or user group ID of the file owner of an executable file, this is achieved by setting the File Attribute of the executable file to SUID or SGID. that is to say, if an executable file is set to SUID or SGID, when other users in the system execute the file, it is equivalent to executing the file as the file owner or user group. if the owner of an executable file is root and SUID is set for this file, if the executable file has the available buffer overflow vulnerability, we can use it to execute the code we have prepared as root. nothing is better than making it generate one for us A shell with the root user identity is more attractive.

Ii) various port daemon (service) Processes

In UNIX, many daemon (service) processes run as root. If these programs have available buffer overflow,

Then we can let them run the code we have prepared as the current user -- root. because the daemon is already running as root, we do not need the SUID or SGID attribute for the corresponding executable file. because such exploitation is usually caused by malicious data being sent from a remote machine to a port on the target machine, it is called remote overflow. what we need to do next is an exciting buffer overflow attack.

 

Reference

An article about buffer overflow in the Shui Mu community: http://www.bkjia.com/Article/201112/113257.html

 

XXX community an article: http://www.lilacbbs.com/bbscon.php? Bid = 91 & id = 72

 

The principle and Countermeasures of buffer overflow attack in Linux: http://www.bkjia.com/Article/201112/113262.html

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.