그래서 kernel이 뭔데?
요약하자면, 운영체제의 핵심이 되는 소프트웨어이다.
우리가 실행하는 프로그램들은 CPU, memory, device 들과 상호작용을 직접적으로 하는 것 같아 보이지만, 실제로는 kernel을 통해 모두 이루어진다.
즉, 각 자원들을 관리하는 것이 kernel이다.
어디에 있는가?
일반적인 binary exploit 시에 많이 보던 메모리 구조는 아래와 같다.
[ Legend: Code | Heap | Stack ]
Start End Offset Perm Path
0x00555555554000 0x00555555558000 0x00000000000000 r-- /usr/bin/dash
0x00555555558000 0x0055555556c000 0x00000000004000 r-x /usr/bin/dash
0x0055555556c000 0x00555555571000 0x00000000018000 r-- /usr/bin/dash
0x00555555571000 0x00555555573000 0x0000000001c000 r-- /usr/bin/dash
0x00555555573000 0x00555555574000 0x0000000001e000 rw- /usr/bin/dash
0x00555555574000 0x00555555576000 0x00000000000000 rw- [heap]
0x007ffff7d83000 0x007ffff7d86000 0x00000000000000 rw-
0x007ffff7d86000 0x007ffff7dae000 0x00000000000000 r-- /usr/lib/x86_64-linux-gnu/libc.so.6
0x007ffff7dae000 0x007ffff7f43000 0x00000000028000 r-x /usr/lib/x86_64-linux-gnu/libc.so.6
0x007ffff7f43000 0x007ffff7f9b000 0x000000001bd000 r-- /usr/lib/x86_64-linux-gnu/libc.so.6
0x007ffff7f9b000 0x007ffff7f9f000 0x00000000214000 r-- /usr/lib/x86_64-linux-gnu/libc.so.6
0x007ffff7f9f000 0x007ffff7fa1000 0x00000000218000 rw- /usr/lib/x86_64-linux-gnu/libc.so.6
0x007ffff7fa1000 0x007ffff7fae000 0x00000000000000 rw-
0x007ffff7fbb000 0x007ffff7fbd000 0x00000000000000 rw-
0x007ffff7fbd000 0x007ffff7fc1000 0x00000000000000 r-- [vvar]
0x007ffff7fc1000 0x007ffff7fc3000 0x00000000000000 r-x [vdso]
0x007ffff7fc3000 0x007ffff7fc5000 0x00000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x007ffff7fc5000 0x007ffff7fef000 0x00000000002000 r-x /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x007ffff7fef000 0x007ffff7ffa000 0x0000000002c000 r-- /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x007ffff7ffb000 0x007ffff7ffd000 0x00000000037000 r-- /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x007ffff7ffd000 0x007ffff7fff000 0x00000000039000 rw- /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x007ffffffde000 0x007ffffffff000 0x00000000000000 rw- [stack]
-----------------------------------------------------------------
여기, 스택 아래에 커널 영역이 존재한다.
위에서 보는 것과 같이 kernel은 stack 영역 아래에 위치하고 있다.
다만 이는 가상 메모리이다.
실제로는 물리 메모리에 이들이 위치하고 있으며, 특히 kernel 영역의 경우 모든 task 들이 공통으로 사용한다.
그래서 가상 메모리와 실제 물리 메모리 주소를 변환하기 위해 kernel 내부에서 "페이징 기법"을 사용한다.
페이징의 자세한건 별도로 작성 예정.
* 덧붙임 - 물리 메모리와 가상 메모리는?
물리 메모리는 말 그대로 물리적인 메모리이다.
어플리케이션이 실행되면 실제 물리 메모리에 특정 영역을 할당하고 바이너리가 실행될 것이다.
다만 물리 메모리 주소로 모든 바이너리의 메모리 주소가 관리된다면?
메모리가 부족해질 확률이 커지며, 메모리 주소를 통한 데이터 관리가 어려워질 것이다.
그래서 가상 메모리를 통해 관리한다.
추가적인 내용은 아래를 참고하자.
가상 메모리 - 위키백과, 우리 모두의 백과사전 (wikipedia.org)
가상 메모리 - 위키백과, 우리 모두의 백과사전
위키백과, 우리 모두의 백과사전. 가상 메모리는 활성 RAM과 DASD 상의 비활성 메모리로 결합되어 있다. 가상 메모리 또는 가상 기억 장치(문화어: 가상기억기, virtual memory, virtual storage)는 메모리
ko.wikipedia.org
유저모드와 커널모드
유저모드 (apprication, binary) : ring 3
커널모드 : ring 0
높을수록 권한이 높고, 낮을수록 권한이 낮다.
ring 0에서는 컴퓨터의 모든 자원에 접근할 수 있고, 내려갈수록 제한적이다.
참고로 ring 1과 2는 device driver의 영역이다.
system call
유저모드에서는 읽고 쓰는 권한이 사실은 없다.
그래서 유저모드에서 커널모드로 바꾼 뒤 작업후에 다시 유저모드로 돌아오는 것이다.
예를 들어 open 함수를 실행한다고 가정하자.
파일을 open하려면 결국 저장매체에 있는 파일의 위치를 확인하고, 이를 열어야한다.
즉 ring 1과 2의 영역에 접근해야하는데, 직접적으로 접근할 권한이 없는 것이다.
그래서 kernel에 파일을 열어달라고 요청을 한다.
즉, 유저모드에서 rax를 2로 syscall 어셈블리어가 실행되면 커널에서 system_call() 함수 (트랩 핸들러라고 한다)를 통해 rax 값을 토대로 sys_open()를 실행하게 된다.
(왜 2인지는 알거라 생각한다.)
이를 실행하고나면 다시 역방향으로 기존 위치로 돌아오게 된다.
그러므로 아래와 같은 다이어그램으로 표현할 수 있다.
커널의 종류
서두에 이야기했어야하나, 대략적인 맥락을 먼저 설명하고 꺼내는 것이 더 이해하기 좋을 것 같아서 뒤로 보냈다.
모놀리딕 커널
위와 같은 방식의 커널을 모놀리딕 (단일형) 커널이라고 한다.
현재 대부분의 유닉스는 이 모놀리딕 커널을 기반으로 구성되어있다.
모놀리딕 커널의 장점은 아무래도 속도라고 생각된다.
커널에 대부분의 주요 코드를 넣어두고, 위에서 설명한 것과 같이 모든 task 들이 불러와서 사용만 하면 되기 때문이다.
문제는 대부분의 주요 코드를 커널에 넣어놨기 때문에, 만일 코드에 문제가 있다면 모든 어플리케이션에서 동일하게 문제가 발생한다는 점이다.
우리는 이를 이용해서 커널 익스플로잇을 한다.
마이크로 커널
이런 모놀리딕 커널의 문제와 더불어 커널의 역할을 최소화하여 문제 발생을 함께 줄일 수 있는 방법을 택한 것으로 보인다.
마이크로 커널에서는 아주 필수적인 부분 몇개만 커널에서 관리하고 나머지는 유저 영역에서 실행되도록 한다.
만일 문제가 생기더라도 커널의 문제가 아니기 때문에 해당 어플리케이션만 종료해버리면 된다.
하이브리드 커널
모놀리딕과 마이크로 커널 둘을 적절히 섞은 것이다.
이를 다이어그램으로 포현하면 아래와 같아진다.
'Kernel Exploit' 카테고리의 다른 글
Kernel exploit - 모듈 프로그래밍 (0) | 2023.08.06 |
---|---|
Kernel exploit - 디바이스 드라이버 (0) | 2023.08.06 |
Kernel exploit - 슬랩 할당자 (0) | 2023.08.06 |
Kernel exploit - task란 (0) | 2023.08.06 |
Kernel exploit - 들어가며. (0) | 2023.08.05 |