본문 바로가기

Programming

Extracting Kernel ELF image from bzImage

리눅스 커널을 컴파일하고나면 압축된 형태의 bzImage(vmlinuz 라고도함) 가 생성된다.

ARM 의 경우는 다르지만 x86 리눅스의 경우 커널이미지가 내부적으로 ELF 포맷으로 저장되어있다.

먼저 file 명령으로 이를 확인해보면 아래와 같다.



사실 이것은 compressed 폴더 밑의 vmlinux 파일을 encapsulate 하고있는 파일이다.

그런데 vmlinux 또한 IDA 로 분석해보면 기본적인 zlib, memcpy, strcmp 등의 함수들을 내장하고있고 kernel 을 런타임에 GZ decompress 하는 로직을 가지고있다.  즉 이또한 실제 ELF 커널 이미지의 wrapper 이다.


한마디로 bzImage(vmlinuz) > vmlinux > kernel 이런 형태가 된다. (ARM 이나 다른 아키텍쳐는 다를 수 있다)


실제 커널 ELF 이미지가 GZ 압축되어 리소스형태로 온전히 내장되있기 때문에 GZ 헤더를 통해서 이를 추출해볼수 있다.

아래와같이 grep 으로 GZ 헤더 패턴을 검색해보면 offset 17085 에서부터 GZ 헤더가 검출된 것을 확인 할 수 있다.



참고로 바이너리 패턴을 바이너리 파일에서 grep 할때는 -obUaP 옵션을 주면된다.

(이거 grep 으로 패턴이 안잡히는경우도 있음. 안되면 hexdump 로도 해볼것)

(P : 펄 정규식, a : 출력을 텍스트처럼 다룸, b : 바이너리로 처리해서 개행문자 등을 일반 데이터로 처리... 등등)

GZ 헤더의 오프셋을 찾았으니 dd 를 이용해서 이를 아래처럼 꺼낸뒤에 gunzip 으로 풀어주고 file 로 확인해보니 최종적인

커널 ELF 이미지가 나타났다.



이를 IDA 로 열어보면 시스템콜 테이블, 전역변수데이터 및 모든 커널 함수들에 대한 디스어셈블리를 아래처럼 볼 수 있다.

그런데 디폴트로 컴파일 했었는데 strip 이 되어있다.



ELF 이미지의 심볼테이블은 존재하지 않지만 System.map 이 모든 심볼정보를 가지고 있으므로 아래와 같이 참조하면서 분석이 가능하다.


'Programming' 카테고리의 다른 글

Linux Kernel System Call Implementation  (0) 2013.08.10
Linux kernel slab allocator  (0) 2013.08.10
Compile a x86 vanilla Linux and test with QEMU  (0) 2013.08.08
using IPv6 address  (0) 2013.07.20
Linux ARM system call table  (0) 2013.07.18