2016年12月7日水曜日

カーネルモジュールを学ぼうとして得たこと

Linux の中核の処理であるタスク切り替え。その切り替えするタスクの情報を構成する task_struct

それをCのプログラムで見れないものか、と調べたらカーネルモジュールでやるんだよ、と突き止めた。

まずはカーネルモジュールを試してみようと思って、"Hello, World" だけを書き出すカーネルモジュールを作ってみた。環境は Ubuntu 16.04 (カーネルバージョンは4.4.0-51)。

Makefile に下記のテキストを書く。makefile にすると、「Makefileが見つからん」とコンパイラがお怒りになる。

obj-m += hello.o

hello.c に下記のコードを書く。

#include <linux/module.h>

int init_module(void)
{
    printk(KERN_ALERT "Hello World!\n");
    return 0;
}

void cleanup_module(void)
{
    return;
} 

次のようにコマンド実行して、コンパイルすると、hello.ko が出来上がった。

$ make -C /lib/modules/4.4.0-51-generic/build SUBDIRS=~/Develop/kernel.modules/hello modules
make: ディレクトリ '/usr/src/linux-headers-4.4.0-51-generic' に入ります
  CC [M]  /home/kernel.modules/hello/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/kernel.modules/hello/hello.mod.o
  LD [M]  /home/kernel.modules/hello/hello.ko
make: ディレクトリ '/usr/src/linux-headers-4.4.0-51-generic' から出ます
$ ls
Makefile        hello.c   hello.mod.c  hello.o
Module.symvers  hello.ko  hello.mod.o  modules.order

そして、この hello.ko を実行しようとして、以下のように蹴られた。

$ sudo insmod hello.ko

insmod: ERROR: could not insert module hello.ko: Required key not available
$ 

こちらのサイトで紹介されているように、カーネルモードで動くマルウェアをインストールさせないために、最近のカーネルバージョンではセキュアブートしているのだという。

今、使用している10インチノートPCは2012年仕様で、BIOSでのセキュアブートができないので困った...。

上記のキーワードで検索すると、mokutil というものを使うことでセキュアブートを無効にできるらしいと、ここから分かった。早速、

$ sudo apt-get install mokutil
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
mokutil はすでに最新バージョン (0.3.0-0ubuntu3) です。
アップグレード: 0 個、新規インストール: 0 個、削除: 0 個、保留: 342 個。 

セキュアブート対応のカーネルバージョンを持つ Ubuntu 16.04 にはデフォルトで付いている。ひき続いて、

sudo mokutil --disable-validation

パスワードを求められたので、入力してPCを再起動後、そのパスワードを入力すると、"Booting insecure mode"と表示されて、デスクトップ起動後に以下を実行。

$ sudo insmod hello.ko
[sudo] emeraudequeen のパスワード: 
$ dmesg | tail
[  358.598562] hello: module license 'unspecified' taints kernel.
[  358.598574] Disabling lock debugging due to kernel taint
[  358.598685] hello: module verification failed: signature and/or required key missing - tainting kernel

[  358.599138] Hello World! 

どうやらカーネルモジュールが動いた。これで task_struct を覗いてみる準備が整った。
それはまた後日に、ってところにしておいて、ちょっとおさらい。

カーネルモジュール動作時に dmesg で見た"module verification failed"は、正規のやり方でないので、出るのは当然。Windows でよくフリーのアプリをインストールするときに、「署名されていないパッケージだけどインストールしていいの?」と聞かれてくるものに置き換えると分かりやすいか...。

上記での参照先では「余計なことを」と書いておられるようだが、Linux にも知らない間にバックドアを仕掛けるカーネルレベルのモジュールが入り込むリスクはやはり避けたい。スヌープしたものの送信先が支那や朝鮮であれば、悲惨なことになる。

0 件のコメント:

コメントを投稿