ii4gsp
[2] 버퍼 오버플로우 (Buffer Overflow) 개념 본문
프로그램 실행 시 Segment에서 무슨 일이 일어날지 알아보자.
프로그램이 실행되어 프로세스가 메모리에 적재되고 메모리와 레지스터가 어떻게 동작하는지에 대해 알아보기위해 간단한 프로그램을 만들어 보자.
[root@ftz root]# vi test.c
소스파일을 하나 만들어주고
사진에 보이는것과 같이 소스코드를 작성하였다.
[root@ftz root]# gcc -o test test.c
해당 소스파일을 컴파일 시켜서 test라는 파일 하나를 생성하였다.
[root@ftz root]# gdb test
디버깅하여 어셈블리코드와 메모리에 적재될 Logical address를 보기 위해 gdb를 실행한다.
위 사진은 test파일의 어셈블리 코드들이며 앞에 붙어 있는 주소는 Logical address이다.
disas는 disassemble의 약자로 특정 함수부터 컴파일을 시작하게 하는 명령어이다.
(gdb) disas main
main함수를 disas하겠다는 명령어이고
(gdb) disas function
function함수를 disas하겠다는 명령어이다.
프로그램이 실행할 때 Stack Segment 와 Code Segment 가 어떤 동작을 하는지 알아보자
1. test프로그램이 실행될 때의 Segment의 모습이다.
ESP 레지스터는 Stack Segment의 제일 꼭대기를 가리키고있다.
해당 Stack Segment의 지점에 "PUSH" or "POP"명령어를 수행 할 위치를 설정해주는 역할
EIP 레지스터는 다음에 실행시킬 명령어가 있는 주소값(Code Segment의 offset값)을 가진다.
2. <main + 0> ~ <main + 16>
push %ebp
Stack Segment에 main()함수가 실행 되기 전의 "Base Pointer"를 저장 시킨다.
push ebp로 ebp를 스텍에 저장하는 이유는 수행하던 함수의 데이터를 보존하기 위해서이다.
이것을 Base Pointer 이라고 한다. 함수가 시작할때에 스텍 포인터와 베이스 포인터를 새로 지정하는데 이러한 과정을 함수 프롤로그라고 한다.
mov %esp, %ebp
ESP값을 EBP의 값으로 복사한다.
Base Pointer와 Stack Pointer는 같은 지점을 가리키게 된다.
sub $0x8, %esp
ESP = ESP - 8
8byte만큼의 공간을 생성한다.
sub $0x4, %esp
ESP = ESP - 4
4byte만큼의 공간을 생성한다.
3. <main+19> ~ <main+25>
push $0x3
push $0x2
push $0x1
function의 인자로 들어갈 1, 2, 3이 push되었다.
call 0x80472f4<function>
"call"명령은 함수를 호출할 때 사용되는 명령으로 호출한 함수의 실행이 끝난 이후 명령이 있는 주소를 스텍에 넣은 다음 EIP에 함수의 시작 지점 주소를 넣는다 (add $0x10, %esp의 주소를 스텍에 push하고 function함수를 실행할 것이다.)
호출된 함수가 종료되고 이후에 실행될 명령어의 주소를 POP하여 어디에 있는 명령어를 수행해야 하는지 알 수 있다는 것 이것이 바로 "Return Address"이다 (호출된 함수 종료후 수행해야 할 명령어가 있는 주소)
이 "Return Address"를 조작하여 해커가 원하는 코드를 실행하는 것이 BOF의 공격기법이다.
4. <function+0> ~ <function+3>
push %ebp
function함수가 시작되기전 function함수가 종료되고 돌아갈 Base Pointer를 Stack에 PUSH 해놓는다.
mov %esp, %ebp
ESP의 값을 EBP에 저장시킨다.
sub $0x28, %esp
ESP = ESP - 40byte
40byte만큼의 공간을 생성한다.
40byte인 이유는 16진수로 28은 10진수 40이기때문이다.
5. <function+6>
leave
"leave"명령은 함수 프롤로그 작업의 반대의 작업을 수행시킨다.
mov %ebp, %esp
EBP의 값을 ESP에 저장시킨다. 즉 생성했던 40byte의 공간을 없앤다.
pop %ebp
PUSH 해놓았던 function의 Base Pointer를 꺼내온다.
6. <function+7>
ret
"ret"명령은 현재 ESP에 있는 'add' 명령의 주소를 스텍에서 POP하여 EIP 레지스터에 넣어주는 역할을 한다.
위에서 말했듯 add명령은 "Return Address"이다.
"ret"명령은 호출한 함수가 실행을 마치면 "Return Address"를 EIP에 넣어서 다음 실행할 명령어가 있는 주소로 이동시킨다.
7. <main+30>
add $0x10, %esp
"add"
main함수의 과정중에서 push $0x1, push $0x2, push $0x3, sub $0x4, $esp 네개의 과정이 있다.
각 과정을 위해 사용했던 16byte의 공간을 제거해주는 역할을 한다.
그리고 "leave"명령을 수행한다.
8. <main+33> ~ <main+39>
"leave", "ret"과정이 위에서 '5' 와 '6' 과정과 같은 흐름으로 진행된다.
mov %ebp %esp
생성시켰던 12byte를 제거
pop %ebp
이전에 저장시켰던 Base Pointer로 돌아간다.
main()함수를 실행하기 이전으로 돌아가게 될것이다. init_process()함수로 돌아갈 것이다.
이 함수는 운영체제가 호출하는 함수로 알아야 할 필요는 없다.
'시스템 해킹 > Technique' 카테고리의 다른 글
SEH Overwrite 기법 (0) | 2020.01.15 |
---|---|
구조적 예외 처리 SEH (Structured Exception Handler) (0) | 2020.01.15 |
윈도우 실행 파일 구조 (0) | 2020.01.13 |
쉘코드 모음 (0) | 2020.01.08 |
[1] 버퍼 오버플로우 (Buffer Overflow) 개념 (0) | 2019.11.16 |