/************************/ /** **/ /** PLT section **/ /** **/ /************************/ // insmod error: module PLT section(s) missing __attribute__((section(".plt"))) char plt = 0; __attribute__((section(".init.plt"))) char initplt = 0; __attribute__((section(".text.ftrace_trampoline"))) char textftrace_trampoline = 0; // TODO: probably an overkill /************************/ /** **/ /** .modinfo **/ /** **/ /************************/ // objdump -s -j .modinfo $KMODULE #define AUTHOR "someone" #define DESCRIPTION "Simple =^.^= kernel module" #define NAME "bmod" #define LICENSE "GPL" #define VERMAGIC "4.14.186-perf-00288-g7df34d2ae6db SMP preempt mod_unload modversions aarch64" __attribute__((section(".modinfo"))) char modinfo_strings[] = "author=" AUTHOR "\0" "description=" DESCRIPTION "\0" "license=" LICENSE "\0" "vermagic=" VERMAGIC "\0" "name=" NAME "\0" ; /*******************************/ /** **/ /** .gnu.linkonce.this_module **/ /** **/ /*******************************/ // 1 - section size // objdump -h $KMODULE | grep .gnu.linkonce.this_module // .gnu.linkonce.this_module 00000340 0000000000000000 0000000000000000 00109800 2**6 // ^^^^^^^^ section size // 2 - section content // objdump -s $KMODULE -j .gnu.linkonce.this_module // Contents of section .gnu.linkonce.this_module: // 0000 00000000 00000000 00000000 00000000 ................ // 0010 00000000 00000000 6d657400 00000000 ........met..... // <<-- NAME offset 0x18 // 0020 00000000 00000000 00000000 00000000 ................ // 3 - entry points offsets // readelf -a $KMODULE -W // Relocation section '.rela.gnu.linkonce.this_module' at offset 0x109b40 contains 2 entries: // <--- Offset ---> Info Type Symbol's Value Symbol's Name + Addend // 0000000000000150 000006c500000101 R_AARCH64_ABS64 0000000000000000 init_module + 0 // 0000000000000310 000006ee00000101 R_AARCH64_ABS64 0000000000000000 cleanup_module + 0 #define L_ONCE_SIZE 0x340 #define L_ONCE_OFFSET_NAME 0x18 #define L_ONCE_OFFSET_INIT 0x150 #define L_ONCE_OFFSET_CLEANUP 0x310 int init_module(void); void cleanup_module(void); __attribute__((section(".gnu.linkonce.this_module"), aligned(8))) struct module { char __pad0[L_ONCE_OFFSET_NAME]; char name[sizeof(NAME)]; char __pad1[L_ONCE_OFFSET_INIT - L_ONCE_OFFSET_NAME - sizeof(NAME)]; int (*init_module)(void); char __pad2[L_ONCE_OFFSET_CLEANUP - L_ONCE_OFFSET_INIT - sizeof(void*)]; void (*cleanup_module)(void); char __pad3[L_ONCE_SIZE - L_ONCE_OFFSET_CLEANUP - sizeof(void*)]; } __attribute__((packed)) __this_module = { .name = NAME, .init_module = &init_module, .cleanup_module = &cleanup_module, }; /*******************************/ /** **/ /** __versions **/ /** **/ /*******************************/ // objdump -s $KMODULE -j '__versions' #dump binary // modprobe --dump-modversions $KMODULE #dump readable char __attribute__((section("__versions"))) ____versions[] = { /* module_layout */ // <<-- MUST BE PROVIDED 0xe8, 0xd6, 0xfc, 0x68, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* printk */ 0xa1, 0x58, 0x55, 0x98, 0x00, 0x00, 0x00, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; /* * The Module */ // load: insmod module_name.ko // logs: dmesg | grep insmod // unload: rmmod MODULE_NAME # from .gnu.linkonce.this_module section int printk(const char *fmt, ...); #define MTAG "["NAME"] " int init_module(void) { printk( MTAG"Hello, world!\n"); return 0; } void cleanup_module(void) { printk( MTAG"Goodbye, world!\n"); }