linux kernel image
커널 소스를 컴파일하여 리눅스 커널 이미지인 bzImage를 빌드하는 방법에 대해 알아보자.
리눅스 커널 이미지?
리눅스 커널을 컴파일 했을 때 생기는 이미지로, 부팅 과정에서 메모리에 로드된다. 커널 이미지 종류는 다양하지만 대표적으로 아래 두 가지가 있다.
-
- vmlinux
- 압축되지 않은 리눅스 커널 실행 파일이다. ELF 형식이며 디버깅 심볼이 담겨있어서 디버깅에 용이하다.
-
- bzImage
- 1번보다 더 큰 커널 이미지를 지원하기 위한 형식이다. 이는 압축된 이미지 형이며 커널을 부팅할 떄 사용한다.
이러한 커널 이미지는 커널 소스에서 make 명령을 통해 컴파일하여 생성할 수 있다.
패키지 설치 + 커널 소스 코드 다운로드
sudo apt-get install build-essential libncurses5 bin86 libncurses5-dev libssl-dev bison flex libelf-dev
mkdir ~/kernel-build && cd ~/kernel-build
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.3.9.tar.xz
tar xf linux-6.3.9.tar.xz
cd linux-6.3.9
커널 이미지 빌드
make defconfig
위 명령어는 커널 설정 파일 .config를 생성한다. 이때 아키텍처는 호스트의 아키텍처로 설정된다.
make menuconfig
위 명령을 통해 커널 옵션을 추가적으로 설정할 수 있다.
디버깅 정보를 포함하기 위해서는 Kernel hacking -> Compile-time checks and compiler options -> Generate DWARF Version 5 debuginfo 로 설정 해주어야 한다.
이후 make -jN 명령으로 커널 이미지를 빌드하는데, 이때 N은 현재 시스템의 CPU core로 설정한다.
make -j24
빌드가 완료되면 vmlinux와 arch/x86/boot/bzImage가 생성된다.
QEMU & BusyBox
해당 단락에서는 리눅스 커널 디버깅을 위한 환경 구축을 해볼 것이다.
QEMU
sudo apt install qemu-utils qemu-system-x86 qemu-kvm
위와 같이 설치 후,
$ qemu-system-x86_64 -version
QEMU emulator version 6.2.0 (Debian 1:6.2+dfsg-2ubuntu6.19)
Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers
위와 같이 뜨는지 확인하자.
qemu-system-x86_64 \
-m 4G -smp 4,cores=4,threads=1 \
-kernel ./bzImage \
-initrd ./rootfs.cpio \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet nopti" \
-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
-nographic \
-cpu host \
-enable-kvm \
-s \
위처럼 QEMU 스크립트를 실행할 수 있다.
특히 -s 옵션을 사용하면 1234 TCP 포트가 열리는데, 이 포트로 gdb 원격 디버깅이 가능하다.
BusyBox
BusyBox로 RootFS를 빌드할 수 있다. RootFS는 리눅스의 최상위 디렉토리에 마운트 되는 파일 시스템이다. 해당 루트 파일 시스템이 없으면 리눅스는 부팅될 수 없다.
RootFS 빌드
make menuconfig로 아래 두 가지를 설정해준다.
- Settings -> Build Options -> Build static binary 설정
- Networking Utilities -> inetd 해제
드림핵은 이러한데 내가 실습해볼 ksmbd에 맞게 다르게 환경 구축해볼 예정이다.
# 업데이트 + 필수 패키지
sudo apt update
sudo apt upgrade -y
sudo apt install -y build-essential libncurses-dev bison flex libssl-dev libelf-dev bc wget git \
qemu-system-x86 qemu-utils debootstrap gdb binutils
mkdir -p ~/kernel-build && cd ~/kernel-build
# 예시: 실제 취약 버전으로 바꿔서 wget 하자
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.x.y.tar.xz
tar xf linux-6.x.y.tar.xz
cd linux-6.x.y
# 빠른 방법: 기존 시스템 config 복사 후 menuconfig
cp /boot/config-$(uname -r) .config
make olddefconfig
make menuconfig
# menuconfig에서:
# - Enable DEBUG_INFO, FRAME_POINTER
# - 검색: ksmbd 또는 smb, SMB server 관련 항목 M/Y
#!/bin/bash
set -e
KDIR=~/kernel-build/linux-6.x.y # 실제 경로로 바꿀 것
cd $KDIR
# 병렬 빌드 (CPU 수에 맞춰 조절)
make -j$(nproc)
# 출력: arch/x86/boot/bzImage, vmlinux (심볼)
echo "built: $KDIR/arch/x86/boot/bzImage"
echo "vmlinux: $KDIR/vmlinux"
chmod +x build-kernel.sh
./build-kernel.sh
# 이미지 크기와 마운트 포인트
IMG=~/guest-image.img
MNT=~/mnt_guest
ROOTFS=jammy # 또는 본인이 선호하는 릴리스
# 이미지 파일 생성 (20GB 예시, 필요시 조절)
fallocate -l 20G $IMG
sudo parted $IMG --script mklabel msdos mkpart primary ext4 1MiB 100%
# 루프장치 연결, 포맷, 마운트
LOOP=$(sudo losetup --show -Pf $IMG)
sudo mkfs.ext4 ${LOOP}p1
mkdir -p $MNT
sudo mount ${LOOP}p1 $MNT
# debootstrap으로 최소 우분투 설치 (네트워크 필요)
sudo debootstrap --arch=amd64 $ROOTFS $MNT http://archive.ubuntu.com/ubuntu/
# 최소 설정: fstab, hosts, 네트워크 설정, 계정
sudo chroot $MNT /bin/bash -c "echo 'root:root' | chpasswd"
sudo chroot $MNT /bin/bash -c "apt update && apt install -y systemd-sysv ssh"
# /etc/fstab 설정 (간단)
echo "/dev/sda1 / ext4 defaults 0 1" | sudo tee $MNT/etc/fstab
# umount & detach
sudo umount $MNT
sudo losetup -d $LOOP
echo "guest image created: $IMG"
#!/bin/bash
KERNEL=~/kernel-build/linux-6.x.y/arch/x86/boot/bzImage
ROOTIMG=~/guest-image.img
GDBPORT=1234
HOSTPORT=1445 # 호스트(=Ubuntu VM) 포트
MEM=4G
CPU=2
qemu-system-x86_64 \
-m $MEM -smp $CPU \
-kernel $KERNEL \
-append "root=/dev/sda1 nokaslr console=ttyS0 earlyprintk=serial" \
-hda $ROOTIMG \
-netdev user,id=net0,hostfwd=tcp::${HOSTPORT}-:445 \
-device e1000,netdev=net0 \
-nographic \
-s -S
gdb ~/kernel-build/linux-6.x.y/vmlinux
(gdb) target remote :1234
# 이제 중단점 설정 등 가능