튜기's blogggg

FC4 cruel -> enigma

by St1tch




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

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

int vuln(int canary,char *ptr)
{
        char buffer[256];
        int *ret;

	// stack overflow!!
	strcpy(buffer,ptr);

	// overflow protected
        if(canary != 0x31337)
        {
                printf("who broke my canary?!");
                exit(1);
        }

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

	// clearing attack buffer
	memset(ptr, 0, 1024);

        return 0;
}

int main()
{
	char buffer[1024];

	printf("enigma : The brothers will be glad to have you!\n");
	printf("you : ");
	fflush(stdout);

	// give me a food!
        fgets(buffer, 1024, stdin);

	// oops~!
        vuln(0x31337, buffer);

	// bye bye
	exit(0);
}


코드를 보면 main함수에서 buffer에 fgets함수와 stdin버퍼를 이용하여 입력을 받는다.

그리고 vuln함수에 특정 값을 넘겨주는데 vuln함수를 보면 canary라는 변수가 있다.

실제 메모리 보호기법중에 하나로 canary를 이용해 스택을 변조하였는지 확인하는 기법이 있다.

이와 유사하게 구현한 문제 인 것 같다.


일단 취약점은 vuln함수의 strcpy함수에서 발생한다.

sfp와 ret를 모두 덮을 수 있으며 canary값만 올바르면 공격을 할 수 있게된다.


우선 가젯이 없기 때문에 rop는 건너 뛰었다. (아마 방법이 있겠지만 지금은 모름)

그리고 sfp를 변조 할 수 있기때문에 fakeebp를 통해 다양한 방법을 시도 할 수 있다.

일단 rop가 안되기 때문에 필요한 문자열이나 쉘코드를 stdin버퍼를 통해 사용하였다.






strace를 통해 stdin의 주소를 확인 해보면 실행시 마다 계속 달라지는 것을 볼 수 있다.

근데 0xb7f까지는 같고 뒤의 3자리인 000도 항상 같다.

따라서 주소의 4,5번째 값을 브루트 포싱해서 풀면된다. (16 * 16 크기이므로 할만한 크기.)




익스플로잇은 다음과 같다.


nop과 쉘코드를 버퍼에 채우고, vuln함수에서 canary검사가 끝난 후 

vuln함수가 종료가 되면서 leaveret가 실행이 되면,

eip는 mprotect를 가리킨다. (빨간색 화살표 한 부분이 fakeebp)

mprotect함수가 stdin버퍼에 실행권한을 주고 난 뒤 종료가 되면 , stdin영역이 실행이 된다.

그러면 nop sled를 따라 쭉 진행되다가 쉘코드가 실행이 되고 쉘을 획득한다.


이 과정이 한번에 되는게 아니고 stdin주소가 바뀌기 때문에 브루트포싱으로 반복문에 넣어 실행을 시켰다.

대략 100-200번 정도면 쉘이 따졌다.




120번만에 성공.






-------------------------------------------------------------------------------------



시도하다가 안된 방법 2가지..




원래 처음에는 execl함수를 이용해서 문제를 풀려고 접근을 했는데

여러가지로 해봐도 쉘이 따지지가 않았다.





그리고 난 후 쉘코드를 이용하기로 생각하고 리버스 쉘을 이용해서 풀려고 했다.

근데 위의 일반 쉘코드를 했을때와 거의 다른게 없는데 쉘이 따지지가 않았다.



이 두 경우는 왜 이렇게 되는지 더 생각을 해봐야 겠다.;;

블로그의 정보

튜기's blogg(st1tch)

St1tch

활동하기