PWN1

fake ebp

#include <stdio.h>

int main(){
    char buf[80];
    read(0, &buf, 88);
    if(buf[87] == "\xbf"){
    printf("exit");
    return 0;
    }
    write(1, &buf, 80);
    return 0;
}

이러한 프로그램이 있다고 해보자.

앞서 설명한 bufferoverflow의 개념이 잡혀있다면, 이 바이너리는 바로 bof가 터지는 바이너리라는 것을 어렵지 않게 알 수 있을 것이다.

하지만 앞에서 봤던 문제와는 달리 ret자리에 넣을 주소의 부분에 우리가 보통 써왔던 것을 막아놓는 부분이 있다.

이러한 경우는 흔한 경우이다.

이럴때, 우리가 사용할 수 있는 기법은 많지만 이번에는 그 중에서도 fake ebp라는 기법을 통해서 exploit을 해보자.

fake ebp는 SFP변조와 leave-ret 가젯을 이용하여 leave-ret동작이 한 번 더 일어나게 하여 shell을 얻어내는 기법이다.

 

우리는 버퍼 공간에 먼저 nop sled를 깔 것 이다. nop sled를 깔아주는 이유는 메모리의 값이 미세하게 변할 수 있기 때문에 쉘코드의 위치로 바로 ret를 하게 될 시 쉘이 따지지 않을 수 있는 경우가 발생하기 때문이다.

nop sled 다음에는 shellcode를 삽입할 것이다.

그리고 남는 공간은 dummy값을로 채워주고,

SFP 영역에 buffer 시작주소 - 4byte값을 넣을 것이다.

RET영역에는 leave-ret 명령어 주소를 넣을 것이다.

buffer의 시작부분에 nop sled를 넣기 전에,

처음 4byte는 nop sled가 깔려있는 곳의 주소를 집어 넣을 것이다.

 

buffer - 4  nop의 임의의 주소 nop sled shellcode dummy SFP(buffer-4) RET(leave-ret gadget)

가시적으로 표현하면 이러하게 memory를 채우는 payload를 작성할 것이다.

 

프로그램의 흐름을 살펴보면,

SFP에 담겨있는 값을 ebp에 담으면서 ebp가 가리키는 곳이 buffer-4가 될 것이다.

그 후, ret를 통해서 leave-ret동작을 한 번 더 하는데,

이때 leave를 통해서 esp가 ebp와 같은 값을 같게 되어 buffer-4를 가리키게 된다.

pop ebp를 통해 ebp는 buffer-4에 써있는 값을 주소로 가지는 어떠한 영역을 가리키게 되고,

esp는 4byte 높은 주소를 가리키게 되어 buffer의 시작부분을 가리키게 된다.

다시 ret을 통해서 buffer의 시작부분에 있는 주소를 eip에 담아 실행시키는데, 쉘이 따지게 된다.

압축적으로 이야기를 했다.

fake ebp가 뭘 하는 건지 아직 잘 감이 오지 않는다면, 함수 프롤로그, 함수 에필로그의 동작을 복습하는 것을 추천한다.

댓글

댓글 본문
graphittie 자세히 보기