튜기's blogggg

FC4 enigma -> titan , FC4 clear

by St1tch




/*
        The Lord of the BOF : The Fellowship of the BOF
        - titan
        - Remote BOF on Fedora Core 4
        - hint : ?
	- port : TCP 8888
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

static char buffer[40];
static void (*ftn)();

void print()
{
        printf("nothing here\n");
	fflush(stdout);
}

int main()
{
        char buf[48];
        ftn = print;

        printf("titan : What a tragic mistake.\n");
        printf("you : ");
        fflush(stdout);

	// give me a food
        fgets(buf,48,stdin);

	// buffer overflow!!
        strcpy(buffer,buf);

	// preventing RTL
        if(((int)ftn &amp; 0xff000000) == 0)
        {
                printf("I've an allergy to NULL");
                exit(1);
        }

	// clearing buffer
	memset(buffer, 0, 40);

        ftn();
}





이번 문제도 remote bof이다.

이전에 풀었던거와는 달리 생각보다 좀 어려웠다.

일단 main함수와 print함수가 있고, main함수의 buf의 크기는 48이다. 

fgets를 통해 정확히 48바이트만 buf에 입력을 받는데 제일 마지막 바이트 0x00을 빼고 총 47바이트가 저장된다.

그리고 strcpy함수에 의해 static 배열인 buffer에 buf의 내용이 복사가 된다.

여기서 static 배열인 buf와, static 함수 ftn이 있다.

static이 붙으면 컴파일 타임에 미리 메모리에 할당을 하는데, 이문제와 같이 초기값이 없으면 .bss섹션에 순서대로 할당이 된다.

따라서 strcpy함수가 실행되고 buffer에 buf를 복사할때 bss섹션에서 buffer의 뒤에 할당 되어있는 ftn의 값을 덮어 씌울수 있다.


그런데 strcpy를 이용해 bss섹션을 덮어씌워 원하는 함수를 실행시킬수 있다고 해도, 함수에 인자를 넣기에는 buffer사이즈가 작다.

일단 이상태에서 rop이나 rtl 기법을 사용하더라도 인자를 제대로 넣을수가 없다. 

마찬가지로 표준입력으로 48바이트를 받기때문에 fake ebp등도 어렵다.


그렇다면 어떻게 공격을 해야될까 막막하다.

이전 문제들을 풀면서 leave ret 를 실행시켜 fakeebp를 하는 것 처럼, 코드를 다시한번 실행시키는 방법을 찾아 보았다.

우선 eip를 원하는 곳으로 이동하려면 함수가 종료되는 시점에서 ebp + 4 ,즉 함수의 ret를 바꿀수 있는 방법을 찾아야한다.

이 문제의 조건에서는 esp를 증가시켜 특정 함수가 종료 되고 난 이후 ret를 덮어 씌워 원하는 함수를 실행 시킬수 있는 방법을 이용했다.




우선 esp를 증가 시키기 위해 add *, esp명령어를 찾아보았다.

보라색 줄이 fgets함수를 호출하는 부분이고, 빨간색 줄이 add esp 부분이다.


fgets함수 이전의 add *. esp명령어를 찾은 이유는

fgets함수를 실행시킬때 마다 main함수의 buf에 원하는 값을 넣을 수 있고, 그 buf에 payload를 넣을 수 있기 때문이다.

만약 add *. esp명령어를 fgets함수 이후에 넣으면, 원하는 payload를 한번의 fgets함수로 넣어야 하는데 esp를 한번에 원하는 buffer까지 올릴수가 없다.

또 fgets함수 이전의 다른 함수의 스택프레임을 통해 eip를 수정하고 싶어도, 결국에 fgets함수가 종료되면서 fgets함수의 스택프레임을 통해 원하는곳으로 가게된다.

(5번째 fgets함수를 통해 RTL페이로드를 입력받고, fgets함수가 종료되며 eip가 원하는 곳으로 가게된다.)


따라서 함수 ftn의 값을 빨간색 밑줄인 add esp, 0x10부분 3군데 중에 아무곳이나 지정하고,

보라색 부분에서(fgets함수 호출)의 스택프레임을 관찰하여 esp를 main의 buffer영역까지 올려야 한다.




fgets함수를 실행 시킬때의 esp와 buf와의 차이는 36바이트이다.

따라서 3번 + 1번(정상적인 흐름) 총 4번을 반복하면 main의 buf영역에 esp가 들어오게 된다.


그리고 5번째 fgets함수에서 buf에 dummy + RTL페이로드를 넣으면 fgets함수가 종료되면서 RTL을 하게된다.




위 표와 같이 스택프레임이 구성이된다.


5번째 실행에서 표준입력으로 RTL payload말고 GOT나 다른 공격방법을 사용해도 된다.

하지만 바로 system('/bin/sh') 실행을 시키는게 제일 간단하다.


따라서 A * 40 + add esp + '\n'으로 4번 반복하고 난 뒤,

fgets함수의 ret는 buffer의 주소 + 8이므로 더미를 8byte입력하고 system함수 주소 + dummy + &'/bin/sh' 형태로 공격을 하면 된다.

'/bin/sh'는 stdin을 이용하거나 라이브러리에서 주소를 찾거나 등 편한 방법을 이용하면 된다.





위의 정보를 토대로 exploit을 작성하였다.






성공 !







FC4도 클리어 했다.

하나씩 시간날때 마다 풀고 있는데 어느덧 이 이상한 문양을 3번째 보게 됬다





















블로그의 정보

튜기's blogg(st1tch)

St1tch

활동하기