Phantom

Dark_eyes – Hell_fire 본문

Pwnable/[Wargame]FC3

Dark_eyes – Hell_fire

Ph4nt0m_ 2016. 2. 23. 21:47
반응형

이번 문제는 setuid가 걸려 있지 않고, xinetd가 hell_fire권한으로 문제를 실행 하고 있다. 라고 어느 블로그에 글이 있다.

뭔 소린지 이해가 가지 않아서 찾아 보기로 했다.

Xinetd로 문제를 실행 하고 있다는 뜻은 이것이었다.

Xinetd.d로 바이너리를 서비스하면 자동으로 입출력을 연결시켜주며 쉘코드없이 /bin/sh를 해주는 것만으로도 쉘을 딸 수 있다고 한다.

우리는 이 문제를 7777포트를 이용하여 풀면 되는 것이다.

 

이번 문제는 풀이가 3개나 있다고 한다.

Do_system()을 이용한 풀이, another Fake EBP, GOT OverWrite 이렇게 있다고 한다.

  

  1. Do_system()을 이용한 풀이

    Do_system()이란 원래 system()함수 내에 호출되는 함수로, do_system() 내에서 ret에 execve()를 호출한다고 한다.

    Disas do_system

    풀이를 보니 do_system의 0x00750784를 RET에 넣는 것을 볼 수 있다. 아마 sigprocmask호출 후 인자들을 넣기 위함으로 생각한다.

    그렇다면 페이로드는…아! 버퍼와 더미 등등을 알아보지 않았다.

     

    Buffer는 256

    Temp는 1024

    디스 어셈블을 해보면

    0x518 => 1304를 할당 받았고, 이제 1024만큼 넣어보면

    Temp가 상당히 아래에 있었다.

    Gdb로 보니 argv 다음 env 의 아스키값 사이에 있었다.

     

    이제 다음 BP인 strcpy를 실행하기 전에 temp는 ebp-0x518이다.

    그리고 strcpy를 실행 하기 전에 ebp-0x108의 주소를 넣고 실행한다 그렇다면


     

    빨간 것이 Buffer, 노란색이 Dummy, 초록색이 argc, argv, env이다.

    그러면 우리는 256 + 12 = 268을 임의의 값으로 주고 ret에 do_system의 0x00750784를 주면 쉘이 따질 것이다.

    맨 뒤의 \x00이 빠지면 왜 쉘이 안 따지는지는 잘 모르겠다.

     

     

    Another Fake EBP or GOT overwriting

     

    Another Fake EBP라길래 삽질을 은근히 했다.


    GOT를 이용하려 해보기도 해보고 했는데 SFP가 보존되기에 되지 않았다.

     

    Main이 종료되고 먼저 실행 되었던 __libc_start_main함수로 돌아가는데 이 곳의 SFP를 이용 하면 가능하다.

     

    허나 Stack에는 x권한이 없다. 그렇다면 어디에 써야 할까?

     

    __libc_start_main의 SFP를 이용해 memcpy, memset을 사용 했을 때 로딩되는 mprotect 함수로 stdin에x권한을 부여한다. Mprotect에 대한 자세한 설명은 따로 알아보기를 바란다.

    그리고 ebp를 stdin으로 옮겨 쉘코드를 실행할 수 있게 만드는 것이다!!

     

    그럼 우리는 __libc_start_main의 EBP를 조작해야 하기 때문에 main 이전에__libc_start_main의 Buffer와 SFP, RET의 위치를 알아야 한다

    그러기 위해서는 main부터 해놓아야 한다

    Buffer의 시작주소 – 0xfefff960

    EBP – 0xfefffa68

    ESP – 0xfefff540

    SFP – 0xfefffac8

     

    크기(Buffer+Dummy) 구하기 : EBP – Buffer의시작주소

    Main의 크기 – 0xfefffa68 – 0xfefff960 = 0x108

    이것이 그것이다. 이전단계에서는 스택프레임 이후 공간 확보 시에 sub esp, 0x108 이렇게 된다.

     

    __libc_start_main의 크기를 구하는 것은 다음과 같다

    Size of __libc_start_main = SFP – EBP – 0x8(SFP와RET의 4바이트씩)

    main이전에 이 함수가 실행 되기 때문이다

     

    그렇다면 __libc_start_main의 크기는 – 0xfefffac8 – 0xfefffa68 – 0x8 = 0x58(88)이다.

     

    크기들은 구했고 mprotect@plt의 주소를 구해야 한다.

    두 주소가 다르지만… 위에 것은 로딩된 함수의 주소를 불러온 것이고 아래에 있는 것은 info function을 통해 구한 원래 함수 위치이다

    Info files로 알아보니 text영역이던데..왜인지…

     

    mprotect@plt는 0x00714670이다.

    함수의 주소도 구했고 stdin으로 EBP를 옮긴다 했는데 stdin은 다행히 고정되어 있었다.

    이것이 fgets(temp, 1024(0x400), stdin)이다. Stdin의 주소는 0x8049788이다.

    여기서 중요한 것은 0x8049788에 있는 것이 아니라 0x8049788이 가리키는 곳이 stdin의 버퍼이다.

    맨 앞의 저 값은 뭔값인지 모르겠다.

    그 다음의 값은 stdin의 크기 등등.. 이고 다음이 stdin의 임시 버퍼이다.

     

    그러면 우리는 페이로드를 이렇게 짤 수 있다.

     

    [ Dummy(268) | Leave-ret | Dummy(88) | 0xf6ffe16c(leave-ret) | leave-ret | mprotect | 0xf6ffe1b0(stdin buffer의 중간)(mprotect's retn) | 0xf6ffe000(arg1) | 0x800(arg2) | 0x7(arg3) | NOP+Shellcode

     

    처음 Leave-ret을 만나서 다시 leave-ret을 거치고 ret을 하면 __libc_start_main으로 돌아간다 그리면 esp에는 0xf6ffe16c가 저장되어있고 다음의 leave-ret에서 ret을 하면서 esp+4되어 0xf6ffe170이 EBP에 들어가게 된다.
    그리고 ret를 하면서 mprotect를 실행하고 인자들이 들어가면서 stdin에 x권한이 주어지고 mprotect의 Return주소에 stdin 버퍼시작주소를 넣었으니 그리로 돌아가 NOP와 shellcode를 수행하는 것이다!!!

     

익플코드를짜려고 했으나

이러한 문제와.. 애초에 내가 gets함수 종류의 익플 코드 실행법을 위의 방법 말곤 모른다..

 

페북의 어느 지인이 os.execve 쓰라고 하는데 방법을 찾아봐야 하다.


반응형

'Pwnable > [Wargame]FC3' 카테고리의 다른 글

[FC3] Gate – Iron_golem  (0) 2017.04.21
Hell_fire – evil_wizard  (0) 2016.02.25
[FC3] Iron_golem – Dark_eyes  (0) 2016.02.19
Comments