gdbで,VirtualBox上のLinux kernelをデバッグできるようにする

Shuji Ohira
inet-lab
Published in
5 min readJul 17, 2020

Githubに公開されているLinux Kernel exploitation Tutorialの2章において,Kernelのデバッグ環境を整えるのですが,VMwareが前提となっています.同様の環境をVirtualBoxで構築したので,その全容をこの記事ではまとめています.

Linux Kernel exploitation Tutorialへのリンクは以下です.
https://github.com/Lazenca/Kernel-exploit-tech

こんな感じでカーネル内の関数にbreakpointがセットできるようになります

環境
HOST : macOS Catalina 1.15.16 (VirtualBox 6.0.22)
VM(debuggee, debugger) : Ubuntu 20.04 Linux 5.4.0–40-generic

まずは,debuggee側から設定します.

### パッケージのインストールなど
$ sudo apt install linux-source libncurses5-dev libssl-dev flex bison
$ mkdir mykernel
$ cd mykernel
$ tar xjf /usr/src/linux-source-<version>/linux-source-<version>.tar.bz2
$ cd linux-source-<version>
### 初期化されたコンフィグの生成
$ make oldconfig
$ vim .config
"KGDB"で検索し,それぞれのオプションがyになっていることを確認する.
$ make menuconfig
"Kernel Hacking->Compile kernel with debug info"を有効化[*]する.
### カーネルのビルド
$ make -j 4
$ make modules
$ make modules_install
$ make install
### ビルドによって生成されたvmlinuxのコピーを共有フォルダに入れる.
$ sudo cp vmlinux /[共有フォルダのパス]
### grub.cfgの変更
$ vim /boot/grub/grub.cfg
"Ubuntu"で検索し,一番初めに見つかった箇所周辺を以下のように編集する.
linux /boot/vmlinuz-5.40.0 … の末尾に kgdbwait kgdboc=ttyS0,115200 を追加

grub.cfgの編集が終わったら,debuggeeはシャットダウンしておいてください.

次に,debuggeeとdebuggerのシリアルポートの設定をVirtualBoxのアプリケーションから行います.
以下のように,シリアルポートを設定します.(違いは”存在するpipe/socketに接続”にcheckを入れるかどうかだけです.)

“debuggee”のシリアルポートの設定
“debugger”のシリアルポートの設定

VirtualBoxから行う設定が終わったので,2つのVMを起動します.
ここで注意なのですが,debuggerはdebuggeeによって作られる/tmp/serialがブート時に必要なため,debuggee->debuggerの順で起動してください.

最後に,debugger側を設定し,gdbでdebuggeeに接続します.

### gdbで使うvmlinuxを持ってくる
$ mkdir /boot/debuggee-image
$ cp /[共有ファイル]/vmlinux /boot/debuggee-image
### ブレイクポイントを打つときに参考にするkernelのコードを持ってくる
$ sudo apt install linux-source
$ mkdir debuggee-kernel
$ cd debuggee-kernel
$ tar xjf /usr/src/linux-source-<version>/linux-source-<version>.tar.bz2
$ sudo su
# cd /boot/debuggee-image
# gdb ./vmlinux
...
...
(gdb) target remote /dev/ttyS0 ### debuggeeにアタッチ
(gdb) b icmp_reply ### icmp_reply関数にbreakpointを設置
(gdb) c

debuggerからdebuggeeにpingを打ったり,debuggeeから直接debuggee自身にpingを打つと,icmp_reply関数でブレイクポイントにヒットすると思います.

終わりに

本記事は以下のYouTubeの動画を大いに参考にしてるので,こちらを見て頂いた方がわかりやすいこともあると思います.

--

--