반응형

어제 golem을 푸는데에 사용한 frame pointer overwrite에 대해 간단하게 아는만큼만 쓰려고 합니다.


#include <stdio.h>

#include <stdlib.h>


void problem_child(char *src)

{

        char buffer[40];

        strncpy(buffer, src, 41);

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

}


main(int argc, char *argv[])

{

        if(argc<2){

                printf("argv error\n");

                exit(0);

        }


        problem_child(argv[1]);

}


이 소스를 한번 뜯어봅시다.

void problem_child(char *src)

{

        char buffer[40];

        strncpy(buffer, src, 41);

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

}

-> buffer는 40바이트밖에 없는 반면, strncpy에서는 src에서 buffer으로 41바이트를 복사합니다.


(low)[buffer] [sfp] [ret](high) 가 있다 함은,(함수의 인자가 어떤 형식으로 스택에 보내지는지는 모르겠습니다) 41바이트를 복사하기 때문에 buffer를 지나 sfp 한 바이트를 변조 할 수 있는 것이죠.

problem_child의 sfp에는 후에 메인 함수로 복귀하기 위해 main 함수의 sfp전의 주소가 저장되어 있게 됩니다. 후에 실행할 명령이 더이상 없기 때문이죠.


이 함수의 leave 명령을 하게 되면,

leave:

mov ebp, esp

pop ebp


이 명령들에 의해 esp를 ebp가 있는 곳(sfp가 있는 곳)으로 이동시키고, pop ebp를 하여 ebp를 복귀시키며 동시에 esp에도 4를 더하게 됩니다.(여기서 알고있어야 하는것은 sfp에 있던 값이 변조된 값이라 sfp를 참고한 ebp는 메인으로 복귀하지 않고 이상한 곳으로 날아갔다는 점입니다. 이걸 악이용해 해커는 ebp가 원하는 곳으로 가게끔 변조할 수 있습니다.)

leave 후 ret 명령이 실행되는데요(모두 problem_child안에서 일어나고 있습니다), 이것은 eip에 ret(ebp+4)에 저장되어있는 주소를 넣어 후에 실행할 코드의 주소를 알려주게 됩니다. 여기서, ebp는 현재 변조된 sfp에 의해 이상한 주소로 날아가 있기 때문에, 그 주소에서부터 4바이트를 읽어들여 eip에 넣게 됩니다. 결과적으로 이상한 곳에 있는 이상한 데이터를 eip에 넣게 되는 것입니다.


어제 풀 때 사용한 노트를 보면,

 argv[1] = [one of the nopsled's addr] [nopsled] [shellcode] [the byte that overflows the fp]

 has to equal 41bytes

라는 내용이 있습니다. 


fp는 메인함수를 가르키고 있기 때문에 주소값의 앞 6자리는 같았습니다. 그 후, 우리가 사용할 수 있는 공간은 argv[1]이었기 때문에 fp를 변조해 ebp가 argv[1]-4의 주소를 가리키고 있게 하였습니다. argv[1]은 위에 구성한 것처럼 앞의 4바이트가 ret로 인해 읽혀야 하니 주소값을 넣어야 합니다. 고로, 앞의 4바이트는 뒤에 넣은 nopsled중 한 곳을 가리키게 하였습니다. ret가 실행된 후 nopsled를 타고 쉘코드가 실행되게 할 수 있기 위함이죠. strncpy에서 41바이트가 복사되어야 하니 마지막 바이트는 fp를 변조할 값을 넣었습니다. 이렇게 해서 leave에서 변조된 ebp가 &(argv[1])-4로 점프하고, pop esp로 esp는 problem_child 의 ret명령을 실행하고, ebp는 4바이트 늘어난 뒤 ret를 가리키는줄 알고 argv[1]의 첫 4바이트를 eip에 넣게 됩니다. 그러면 eip는 그 주소(이 경우 nopsled)로 점프하여 그 후 나오는 명령, (여기선 쉘코드)를 결과적으로 실행하게 됩니다.

 

fpo가 메인함수에서 안되는 이유는 모르겠지만, 제 생각으로는 타 함수들은 메인으로 돌아가기 위해 sfp를 주소 복구용으로 사용하는 반면, 메인 함수는 돌아가야 할 주소가 필요 없기 때문에 메인함수에서는 실행이 안되는것 같습니다. 메인 함수는 _libc_start_main으로 돌아가야하죠.. 없는 디버깅 실력을 모아 메인 함수를 따라가 봤는데, sfp가 있는 곳에는 0x00000000이 있드라구여. 그 후에 있는 ret 주소는 start함수를 가르키고 있었는데.. 워낙 디버깅 실력이 없어서 더는 못찾아봤어요.ㅋㅋ..


이거 쓰고보니 한국어 참 어렵네요.. 뭔가 설명이 오묘하다.


http://research.hackerschool.org/Datas/Research_Lecture/sfp.txt

꼭 참고하시기 바랍니다 :)

반응형

'STUDY > Documentation' 카테고리의 다른 글

strace, 제가 한번 사용해 보겠습니다.  (0) 2014.07.22
Buffer Overflow  (3) 2014.05.18
Key File  (0) 2014.05.16
Frame Pointer Overwrite/One Byte Overflow  (5) 2014.04.06
[CodeGate Junior Quals] RunCommand 250  (0) 2014.04.06
MISCCCCCCCCCC!  (0) 2014.03.11
  1. BlogIcon 로긴귀찮 2014.04.10 07:07

    fp는 메인함수를 가르키고 있기 때문에 앞의 6자리는 같았습니다 여기서 주소값 앞의 6자리로 정정

  2. BlogIcon 로긴귀찮 2014.04.10 07:07

    ebp가 argv[1]-4로 점프하고,
    여기도 argv[1]의 주소 -4로 정정

  3. BlogIcon 로긴귀찮 2014.04.10 07:08

    아 맞다 해쿨 자료 사용한것도 링크

  4. BlogIcon 나도 로그인귀찮음;; 2014.09.20 17:25

    rtrtrt ㄳㄳㄱㅎㄷㄱㄳㄳㅈㄳㅈㄳㄷㄳㄳ

+ Recent posts