드디어 리버싱에 대한 포스팅을 하게 되었다.
(진짜 예전부터 리버싱에 관심이 많았는데 딱 관심만 많았다..)
절대 혼자서는 의지박약문제로 공부시작을 못했을꺼 같았지만 모두의보안 스터디를 하면서 ftz 문제를 처음으로 풀게 되었다.
한 10번인가? 까지는 그냥 저냥 구글링 하면서 리눅스를 그래도 어느정도 다뤄본 나로서는 어렵지는 않은 문제들이였다. 수업시간에 배웠던 심볼릭 링크나 하드 링크, 공유 메모리 등등.. (내가 잘한다는게 아니라 쉬운 문제였긴함)
11번인가부터 20번 까지는 싹다 버퍼오버플로우 관련한 문제였다. 스택 메모리 구조도 공부한지 얼마 안됬고 레지스터의 개념도 잘 인지 못했으며 esp, ebp는 또 먼 개소린가...
사실 그냥 운영체제, 컴퓨터 구조에 대한 수업을 수강한 상태였고 이론적으로 스택이 머며 메모리가 머며 알고는 있었는데 실제로 문제를 풀려고 하니까 아.. 내가 제대로 공부한게 아니였구나.. 라는걸 깨달았다.
그 순간부터 수업때 배웠던 내용을 다시한번 복습하면서 컴퓨터의 구조에 대해서 전체적으로 다시한번 공부를 하였다.
여튼 다 개소리 집어치고 오늘은 ftz11번 부터 write-up을 하기 전 알고 있어야 하는 컴퓨터의 대략적인 구조에 대해서 설명을 하고자 한다.
1. 컴퓨터의 기본적 구성
프로그래밍을 처음 공부를 한 뒤 처음으로 짠 코드는 아마 이거일 것이다. 이건 아마 다 씹인정 할듯
처음에 책보고 하라는대로 코드를 따라 치고 컨트롤 f5 를 눌르는 순간.....!!!!!
콘솔창에 hello world....
나만 그런거 아닐꺼임.
저런 표정을 지으면서 나 천재아님? 개신기방구..
ㅋㅋㅋㅋ
당연히 그럴꺼임 ㅋㅋ 이것이 바로 배움의 묘미 아니겠음?
쨋든... 내가 말하고 싶은건 내가 비쥬얼 스튜디오로, 혹은 다른 것으로 코드를 짠 것이 어떻게 실행되어 내 눈앞에 실행 결과가 보여지는지의 일련의 과정을 설명하고 싶었다.
다음 사진을 보자
노트북 뒷판 뜯었을 때 보이는 것
나는 ㅈ 같은 뽑기운이 안좋은건지 모르겠는데 모 회사의 노트북을 구매한지 2년이 쫌 넘는 동안 메인보드 2번, ssd4번, 키보드 한번 이렇게 갈았었다. 그덕분에 노트북을 진짜 개많이 뜯어봤는데 처음에는 고장난 것에 대한 빡침이 너무 컸는데 하도 고장나니까 이제는 그냥 그려려니 하면서 이건 멀까? 저건 멀까? 이러면서 실제 물리적 장치들을 눈으로 많이 봤다.
위 사진은 인터넷에서 가져온 노트북 뒷판인데 대부분 다 비슷하게 생겼다.
컴퓨터를 구성하는 기본적 구성 요소
1. CPU
2. 메모리
3. 입출력 장치
4. 하드 디스크
컴퓨터의 기본적 구성요소는 전체적으로는 위 4개가 주를 이루고 있다. 위 사진에 빨간색으로 구성요소의 위치를 표시해 놨다.
CPU가 사람의 대가리에 해당하는 녀석이다. 현재 사진에는 하드가 없는 것으로 보인다. 그리고 ssd는 m.2 방식으로 메모리 스틱 형태로 구성되어 있는것을 알수 있다.
배터리가 하단에 위치하고 메모리가 왼쪽에 위치해 있는 것을 볼수 있다.
그리고 초록색으로 표시한 부분을 메인 보드라고 한다.
전체적인 구성은 이렇게 되고 이제 내가 코딩을 해서 어떠한 프로그램을 만들었다고 가정하자. 이는 윈도우 상에 만들었으며 실행파일의 형태로 저장되있다고 해보자.
하드디스크 내용물
내 하드디스크에는 정말 많은 자료들이 들어있다. 강의자료, 피피티, 한글파일, 워드파일, 텍스트 파일, 영상 등등 ..
여기서 하나 알아야 하는 것이 있는데 바로 PE 파일 이다.
PE파일이란?
윈도우 상에서 실행할 수 있는 프로그램을 PE(Portable Excutable)이라고 한다.
대부분 .exe 파일이라고 많이들 알고 있는 것이 대표적인 예이다. exe파일 말고도 .scr, .dll 등 많은 실행파일 확장자도 많다. (dll은 단독으로 실행되는게 아니라 exe파일을 실행시키기 위해 필요한 기능 파일 이라고 보면됨)
여튼 PE파일이란 건 윈도우 상의 실행 파일이라고 보면됨.
PE 파일의 구성
1) 헤더 : 프로그램을 실행하는데 필요한 기본 정보와 메모리 어디에 저장해야 하는지에 대한 배치 정보가 담김
2) 바디 : 파일에 대한 코드 및 데이터가 들어 있음.
2. 프로그램 동작 과정
이러한 PE파일이 현재 하드디스크에 저장되어 있고 내가 해당 파일을 실행시키려고 더블 클릭 직전의 상황을 보면
아직 하드디스크에 있는 PE파일
다음과 같이 보여짐. 하드디스크에 PE파일이 있고 PE파일의 구조는 초록색으로 된 구조를 띔.
이제 저 파일을 더블 클릭을 한 순간
로더에 의해 메모리에 적재됨
하드디스크에 있는 PE 파일은 메인 메모리에 적재됨.
그 과정은 다음과 같음
1. PE파일이 실행되는 순간 윈도우의 Loader라는 녀셕이 하드디스크의 있는 PE파일의 헤더 부분을 봄
2. 로더는 PE파일의 헤더를 참조하여 이 녀석이 메모리의 어디 부분에 배치시키면 좋을지 판담함
3. 판단한 결과를 가지고 바로 메모리 상에 바로 적재해 보림
그럼 이제 PE파일이 실행될 수 있는 환경이 갖춰진거임.
그럼 이제 PE파일이 올라가는 메모리는 어떠한 구조로 이루어 지고 있는지 살펴보자
메모리 구조
1. 스택 영역 : 지역변수, 매개변수, 리턴 값 등이 저장됨
2. 힙 영역 : 필요에 의해 동적으로 메모리를 할당 하고자 할 때 위치하는 메모리 영역.
3. 데이터 영역 : 전역변수, 정적변수, 배열, 구조체 등이 저장. 초기화 되지 않은 전역변수, 초기화 된 전역변수가 저장됨
4. 코드 영역 : 프로그램 코드 자체가 기계어로 저장되는 영역. CPU가 이 영역에 있는 명령을 읽고 처리함
메모리 구조
위가 높은 주소, 아래가 낮은 주소인데, 스택은 높은 주소에서 낮은 주소로 쌓이고 나머지는 낮은 주소에서 높은 주로소 쌓임.
이는 만약 스택이 낮은 주소에서 높은 주소로 쌓인다면 위쪽에 있는 커널영역까지 침범하여 오류를 일으킬 수 있기 때문에 스택과 힙은 마주보는 방향으로, 즉 높은 주소에서 낮은 주소로 스택이 쌓인다고 함
간단한 설명을 다음과 같으며 직접 프로그램 코드와 위 그림의 영역부분을 매칭시키면 다음과 같음
위 사진은 높은 주소가 아래쪽이고 낮은 주소가 위 쪽이라고 보면 된다
bss영역은 초기값이 없는 데이터 영역, 데이터 영역은 초기값이 있는 데이터 영역이다.
데이터 영역에는 전역변수, 구조체 등이 들어간다고 했으므로 오른쪽 코드를 보면 알맞게 들어가 있는 것을 볼수가 있다
약간 헷갈릴수 있는데 그냥 BSS - rodata 까지의 영역이 다 데이터 영역이라고 보면된다
그리고 전체 소스코드가 컴파일 되어 기계어로 바뀌면 코드 영역, 저기서 text 영역에 들어간다
그다음 힙 영역에는 동적할당 한 데이터들이 들어가고
마지막 스택영역에는 지역변수 가 들어 가는 걸 볼 수 있다.
그럼 아래의 그림에서 보이는 메모리는 위에서 설명한 4개의 영역으로 구조화 되어있는 스택, 힙, 코드, 데이터 영역에 PE파일의 정보가 나뉘어서 들어가져 있는 상태이다
3. PE파일의 실제 실행 절차
PE파일이 메모리에 로딩되고 c언어 같은 경우는 main 함수부터 실행이 된다
윈도우가 메모리에 있는 PE파일을 실행시키기위해 PE 파일의 헤더속에 있는 엔트리 포인트라는 걸 찾고 그 주소부터 실행을 시킨다.
CPU가 프로그램 명령어를 실행시킬때 실행시에 필요한 데이터를 모두 메모리에서 레지스터로 가져온다.
사실 이 과정도 굉장히 복잡하고 설명할게 많지만 그건 나중에 설명하기로 하고 CPU는 이러한 메인 메모리 상에 있는 프로그램들을 가져와서 레지스터에 저장시키고 연상을 막 하게 된다.
막 실행을 하다가 인터럽트가 걸리거나 용량이 부족하거나 등등 의 이유로 현재 레지스터의 내용을 비우고 다른걸로 스위칭하고 막 이러한 과정을 컨텍스트 스위칭 이라고 한다.
결론으로..
이러한 전체적인 과정을 통해서 내가 짠 프로그램이 실행이 된다.
이제 위에서 설명한 내용중 프로그램이 메모리 상에 올라갈때 4개의 영역으로 각 내용이 들어가는데 해당 내용을 버퍼오버플로를 위해서 다음 챕터에서는 자세히 설명하 겠음