Notice
Recent Posts
Recent Comments
Link
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

trash houz

Linux Kernel Debugging with QEMU 본문

Linux

Linux Kernel Debugging with QEMU

applemasterz17 2019. 10. 21. 20:42

빌드를 위한 필수 패키지 설치

Documentation/Changes 문서에 커널 빌드시 사용되는 패키지의 최소 버전이 명시되어 있습니다.

sudo apt install build-essential kernel-package libncurses5-dev libssl-dev ccache flex bison libelf-dev bin86 qemu qemu-kvm

커널 소스코드 다운로드

아래 두 링크에서 다운로드 할 수 있습니다.

이외에도 토발즈 깃허브에서 받아온뒤 버전을 변경할수 있습니다.

git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux
git checkout v3.16

커널 config 파일 설정하기

make defconfig 를 통해 기본 설정을 할 수 있습니다.

make defconfig

추가 설정을 위해 make menuconfig 를 이용하면 됩니다. 직접 .config 파일을 수정해도 됩니다.

make menuconfig

다음과 같이 아키텍처의 직접적인 명시도 가능합니다.

make ARCH=x86_64 x86_64_defconfig
make ARCH=x86_64 menuconfig
  • 디버깅 심볼 추가: CONFIG_DEBUG_INFO=y
  • kallsyms 활성화: CONFIG_KALLSYMS=y,
  • kallsyms 에 추가 정보 출력: CONFIG_KALLSYMS_ALL=y
  • 드라이버 디버깅시 메시지 추가: CONFIG_DEBUG_DRIVER=y
  • KASLR 활성화: CONFIG_RANDOMIZE_BASE=y
  • KASAN 활성화: CONFIG_KASAN=y, CONFIG_KASAN_INLINE=y
  • UBSAN 활성화: CONFIG_UBSAN=y, CONFIG_UBSAN_SANITIZE_ALL=y
  • KCSAN 활성화: CONFIG_KCSAN=y
  • KFENCE활성화: CONFIG_KFENCE=y
  • Kmemleak 활성화: CONFIG_DEBUG_KMEMLEAK=y

 

커널 빌드

make 를 이용해 빌드하면 됩니다. -j 옵션을 통해 사용할 코어를 선택할 수 있습니다.

make -j4

만약 cc1: error: code model kernel does not support PIC mode 오류가 발생한다면 pie.patch 로 다음 코드를 저장합니다.

해당 오류는 특정 gcc 버전 이상에서 pie 적용이 기본으로 설정되어 발생하는것 입니다.

diff --git a/Makefile b/Makefile
index dda982c..f96b174 100644
--- a/Makefile
+++ b/Makefile
@@ -608,6 +608,12 @@ endif # $(dot-config)
 # Defaults to vmlinux, but the arch makefile usually adds further targets
 all: vmlinux

+# force no-pie for distro compilers that enable pie by default
+KBUILD_CFLAGS += $(call cc-option, -fno-pie)
+KBUILD_CFLAGS += $(call cc-option, -no-pie)
+KBUILD_AFLAGS += $(call cc-option, -fno-pie)
+KBUILD_CPPFLAGS += $(call cc-option, -fno-pie)
+
 # The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
 # values of the respective KBUILD_* variables
 ARCH_CPPFLAGS :=

이후 .config 파일 설정이 끝난 상태에서 아래 명령어로 패치를 진행한뒤 다시 빌드를 시작하면 됩니다.

patch -p1 < pie.patch

결과물 확인

정상적으로 컴파일이 완료되면 arch/x86/boot/bzImage 가 생성됩니다.

bzImage 는 vmlinux 에서 순수하게 명령어 셋만 뽑아낸 파일입니다.
vmlinux 는 디버깅에 유용한 심볼들이 포함된 파일입니다.

debug-kit 다운로드

다음 명령어를 통해 미리 작성해놓은 스크립트를 다운로드하여 사용하면 됩니다. .gdbinit 파일은 수정이 필요합니다.

git clone https://github.com/applemasterz17/linux-kernel-debug-kit.git

보호기법 설정

KPTI 를 설정하려면 -cpu kvm64 옵션을 사용하면 됩니다. 해제시 -cpu qemu64 옵션을 사용하면 됩니다. 혹은 -append "kpti=1" 을 사용해 활성화 하거나 -append "nopti" 를 사용해 해제할 수 있습니다.

SMEP, SMAP 을 설정하려면 -cpu +smep, +smap 옵션을 사용하면 됩니다. 해제시 -append "nosmep nosmap" 옵션을 사용하면 됩니다. 혹은 -cpu 에서 제거해도 됩니다.

KASLR 을 설정하려면 기본적으로 커널 빌드시 CONFIG_RANDOMIZE_BASE=y 인 상태로 빌드 된 이미지여야 합니다. 추가 설정이 필요없습니다. 해제시 -append "nokaslr" 옵션을 사용하면 됩니다.

KADR 보호기법은 파일 시스템 내부의 init 스크립트를 수정해야 합니다. 보호 기법을 해제하는것이 아닌 사용자 권한을 root 권한으로 변경해야 합니다. setuidgid0 으로 변경합니다.

#!/bin/sh

mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs devtmpfs /dev
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console

setsid cttyhack setuidgid 0 sh

umount /proc
umount /sys
poweroff -d 0 -f

GDB 로 디버깅하기

먼저 ~/.gdbinit 에 다음 스크립트를 추가해 gdb-script 를 자동으로 로드하도록 합니다.

 set auto-load safe-path /home/applemasterz17/kernel/linux-5.15.6/scripts/gdb

만약 모듈을 로딩해야한다면 insmod 명령어를 통해 모듈을 먼저 로딩합니다.
이후 .text 베이스 주소를 찾습니다.

sudo insmod test_module.ko
sudo cat /sys/module/test_module/sections/.text

QEMU 의 -s 옵션을 이용해 GDB 에서 Attach 할 수 있습니다.
모듈을 디버깅 하려면 모듈 심볼 로딩도 추가로 해줘야합니다.

gdb -q ./vmlinux
target remote:1234
add-symbol-file ./test_module.ko [.text 주소]

BP 를 설정할 함수의 주소를 찾아줍니다. KADR 을 해제한뒤 확인해야 합니다.

cat /proc/kallsyms | grep printk

커널 모듈의 베이스 주소를 확인하려면 /proc/modules 를 확인하면 됩니다.

sudo cat /proc/modules

루트 파일 시스템 생성하기 (BusyBox)

BusyBox 는 리눅스 커널 2.4.x 버전부터 모든 기능을 지원합니다. 다운로드 링크 에서 원하는 버전을 다운로드 합니다.

wget <https://busybox.net/downloads/busybox-1.32.0.tar.bz2>
tar xvf busybox-1.32.0.tar.bz2

make menuconfig 를 이용해 빌드 옵션을 설정해야 합니다.

make menuconfig
  • Settings -> --Build Options -> Build static binary [체크]
  • Networking Utilities -> inetd [체크 해제]

빌드 결과물이 저장될 디렉토리를 생성하고 소스코드를 빌드하면 됩니다.

mkdir ../target
make CONFIG_PREFIX=../target install

빌드 결과물이 담긴 디렉토리에서 필요한 디렉토리들을 생성해줍니다.

cd ../target
mkdir dev etc lib proc tmp sys

해당 디렉토리에 init 스크립트를 작성해주고 755 권한을 부여합니다. init 스크립트는 부팅 후 가장 먼저 실행되는 PID:1 프로세스 입니다.

#!/bin/sh

mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs devtmpfs /dev
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console

setsid cttyhack setuidgid 1000 sh

umount /proc
umount /sys
poweroff -d 0 -f
vim init
chmod 755 init

지금까지 생성한 파일들을 cpio 명령어로 전부 압축하면 rootfs.cpio 파일이 생성됩니다.

find . | cpio -o --format=newc > rootfs.cpio

파일 시스템에 파일을 추가하려면 아래의 명령어를 사용하면 됩니다.

cpio -idm  < ../rootfs.cpio
cpio -id -v < rootfs.cpio

보통 편리를 위해 아래와 같이 스크립트를 작성해 repack_fs.sh 로 저장해서 사용합니다.

-masm=intel 옵션은 인텔 어셈블리 문법 옵션입니다.

#!/bin/bash
gcc -masm=intel -static -o exploit exploit.c -no-pie
mkdir fs
cd fs
cpio -idm  < ../rootfs.cpio
mv ../exploit ./
find . | cpio -o --format=newc > ../rootfs.cpio
cd ..
rm -rf fs

QEMU 스크립트 작성하기

아래 스크립트는 BusyBox 파일 시스템을 사용한 QEMU 스크립트 예제입니다.

#!/bin/bash

qemu-system-x86_64 \\
    -m 512M \\
    -kernel ./bzImage \\
    -initrd  ./rootfs.cpio \\
    -append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet nokaslr" \\
    -netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \\
    -nographic  \\
    -cpu qemu64,smep,smap \\
    -s \\
    -pidfile vm.pid \\
  • -m 512M : 주 메모리 512mb 할당
  • -smp 2 : CPU 코어를 두개 사용
  • -kernel ./bzImage : bzImage 를 커널 이미지로 사용
  • -initrd ./rootfs.cpio : rootfs.cpio 를 파일 시스템으로 사용
  • -append "nokaslr" : KASLR 보호기법 해제
  • -append "quiet" : 부팅시 시끄러운것들 끄기
  • -cpu smep, smap, qemu64 : SMEP, SMAP 보호기법 해제, 프로세서 아키텍처
  • -s : GDB Attach 를 위해 1234번 포트를 오픈
  • -S : 부팅하자마자 멈춤
  • -nographic : 그래픽 옵션 사용 안함
  • -pidfile vm.pid : 부팅한 커널 pid 를 vm.pid 에 저장

실행된 가상머신을 종료하려면 아래 명령어를 이용해 종료합니다.

kill $(cat vm.pid)

'Linux' 카테고리의 다른 글

task_struct 에서 권한상승  (0) 2019.08.05