Try   HackMD

2021q3 Homework1 (quiz1)

contributed by < starlinking >

0. 環境 (Ubuntu 20.04 VM running up)

$ uname -r
5.4.0-80-generic

$ sudo apt install linux-headers-`uname -r`

$ dpkg -L linux-headers-5.4.0-80-generic | grep "/lib/modules"
/lib/modules
/lib/modules/5.4.0-80-generic
/lib/modules/5.4.0-80-generic/build

$ tree -L 2 hideproc/
hideproc/
├── main.c
└── Makefile

$ make
make -C /lib/modules/`uname -r`/build M=/home/star/workspace/linux/hideproc modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-80-generic'
  CC [M]  /home/star/workspace/linux/hideproc/main.o
  LD [M]  /home/star/workspace/linux/hideproc/hideproc.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC [M]  /home/star/workspace/linux/hideproc/hideproc.mod.o
  LD [M]  /home/star/workspace/linux/hideproc/hideproc.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-80-generic'

$ tree -L 2 hideproc/
hideproc/
├── hideproc.ko
├── hideproc.mod
├── hideproc.mod.c
├── hideproc.mod.o
├── hideproc.o
├── main.c
├── main.o
├── Makefile
├── modules.order
└── Module.symvers

$ sudo insmod hideproc.ko

$ dmesg 
[ 3006.672989] hideproc: module verification failed: signature and/or required key missing - tainting kernel
[ 3006.673303] @ _hideproc_init

$ pidof cron
661
$ echo "add 661" | sudo tee /dev/hideproc
add 661
$ pidof cron
$ echo "del 661" | sudo tee /dev/hideproc
del 661
$ pidof cron
661

$ sudo rmmod hideproc
$ dmesg 
[ 3543.712336] @ _hideproc_exit

1. 解釋程式碼運作原理,包含 ftrace 的使用

Ftrace堪稱Linux官方tracer,一般只要有echo, cat指令的嵌入式環境,就可以開始。為了後續方便學習 Linux 核心,我們可以安裝 ftrace cmdline 工具 - trace-cmd。
sudo apt install trace-cmd

  • trace-cmd cheatsheet
usage:
  trace-cmd [COMMAND] ...
use case cmd
How to know what functions we can trace? sudo trace-cmd list -f
How to trace a function? sudo trace-cmd record -p function -l do_page_fault
How to trace a process? sudo trace-cmd record -p function -P 25314
-p run command with plugin enabled
-l filter function name 
-P pid
  • _hideproc_init
    • init_hook
      • hook_install: install the function hooks
  • _hideproc_exit
    • hook_remove(&hook): remove function hooks

enable hook_remove function (remove line 66 and 76)

#if 0 void hook_remove(struct ftrace_hook *hook) { int err = unregister_ftrace_function(&hook->ops); if (err) printk("unregister_ftrace_function() failed: %d\n", err); err = ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0); if (err) printk("ftrace_set_filter_ip() failed: %d\n", err); } #endif

增加幾行code,釋放相關資源,避免下次insmod hideproc.ko,出現錯誤,將dev_major宣告為全域變數。

$ dmesg
[ 9128.397812] sysfs: cannot create duplicate filename '/class/hideproc'
[ 9128.397814] CPU: 0 PID: 17645 Comm: insmod Tainted: G           OE     5.4.0-80-generic #90-Ubuntu
[ 9128.397815] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 9128.397816] Call Trace:
[ 9128.397821]  dump_stack+0x6d/0x8b
[ 9128.397824]  sysfs_warn_dup.cold+0x17/0x27
[ 9128.397827]  sysfs_create_dir_ns+0xb8/0xd0
[ 9128.397829]  kobject_add_internal+0xbd/0x2b0
[ 9128.397830]  kset_register+0x4c/0x70
[ 9128.397832]  __class_register+0xd8/0x190
[ 9128.397833]  __class_create+0x51/0x80
[ 9128.397836]  ? hook_remove.cold+0x26/0x26 [hideproc]
[ 9128.397837]  _hideproc_init+0x6c/0x1c5 [hideproc]
[ 9128.397839]  do_one_initcall+0x4a/0x200
[ 9128.397841]  ? _cond_resched+0x19/0x30
[ 9128.397844]  ? kmem_cache_alloc_trace+0x177/0x240
[ 9128.397846]  do_init_module+0x62/0x260
[ 9128.397847]  load_module+0x11e6/0x1320
[ 9128.397850]  __do_sys_finit_module+0xbe/0x120
[ 9128.397851]  ? __do_sys_finit_module+0xbe/0x120
[ 9128.397853]  __x64_sys_finit_module+0x1a/0x20
[ 9128.397854]  do_syscall_64+0x57/0x190
[ 9128.397856]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 9128.397857] RIP: 0033:0x7f1f4b2e989d
[ 9128.397858] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d c3 f5 0c 00 f7 d8 64 89 01 48
[ 9128.397859] RSP: 002b:00007ffc3ea5ab58 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
[ 9128.397860] RAX: ffffffffffffffda RBX: 0000557bf07c57a0 RCX: 00007f1f4b2e989d
[ 9128.397860] RDX: 0000000000000000 RSI: 0000557beeb2f358 RDI: 0000000000000003
[ 9128.397861] RBP: 0000000000000000 R08: 0000000000000000 R09: 00007f1f4b3bd260
[ 9128.397861] R10: 0000000000000003 R11: 0000000000000246 R12: 0000557beeb2f358
[ 9128.397862] R13: 0000000000000000 R14: 0000557bf07c5760 R15: 0000000000000000
[ 9128.397864] kobject_add_internal failed for hideproc with -EEXIST, don't try to register things with the same name in the same directory.
static void _hideproc_exit(void) { printk(KERN_INFO "@ %s\n", __func__); /* FIXME: ensure the release of all allocated resources */ hook_remove(&hook); device_destroy(hideproc_class, MKDEV(dev_major, MINOR_VERSION)); class_destroy(hideproc_class); cdev_del(&cdev); unregister_chrdev_region(MKDEV(dev_major, MINOR_VERSION), MINOR_VERSION); }

可以連續 insert, remove hideproc 核心模組!

$ dmesg
[ 1209.535616] @ _hideproc_init
[ 1299.288350] @ _hideproc_exit
[ 1323.978583] @ _hideproc_init
[ 1545.173048] @ _hideproc_exit
[ 1547.666741] @ _hideproc_init
[ 1549.172767] @ _hideproc_exit

整個程式碼運作原理還未完全理解,需要再花一點時間內化,再補上。

2. 本程式僅在 Linux v5.4 測試,若你用的核心較新,請試著找出替代方案

TODO: 先更新kernel版本,再試試!

3. 本核心模組只能隱藏單一 PID,請擴充為允許其 PPID 也跟著隱藏,或允許給定一組 PID 列表,而非僅有單一 PID

4. 指出程式碼可改進的地方,並動手實作

Resource(s)