Home > Software engineering >  Hooking to system call in ubuntu 22.04(The kernel version is 5.15)
Hooking to system call in ubuntu 22.04(The kernel version is 5.15)

Time:05-01

i tried to create kernel module that make hooking to system call of "bind"(sys_bind).the module:

#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/ptrace.h>
#include <linux/socket.h>
#include <linux/kallsyms.h>
#include <linux/kprobes.h>



unsigned long kaddr_lookup_name(const char *fname_raw)
{
  int i;
  unsigned long kaddr;
  char *fname_lookup, *fname;

  fname_lookup = kvzalloc(NAME_MAX, GFP_KERNEL);
  if (!fname_lookup)
      return 0;

  fname = kvzalloc(strlen(fname_raw) 4, GFP_KERNEL);
  if (!fname)
      return 0;

  /*
   * We have to add " 0x0" to the end of our function name
   * because that's the format that sprint_symbol() returns
   * to us. If we don't do this, then our search can stop
   * prematurely and give us the wrong function address!
   */
   strcpy(fname, fname_raw);
   strcat(fname, " 0x0");

   /*
    * Get the kernel base address:
      * sprint_symbol() is less than 0x100000 from the start of the kernel, so
      * we can just AND-out the last 3 bytes from it's address to the the base
      * address.
      * There might be a better symbol-name to use?
    */
   kaddr = (unsigned long) &sprint_symbol;
   kaddr &= 0xffffffffff000000;

   /*
     * All the syscalls (and all interesting kernel functions I've seen so far)
     * are within the first 0x100000 bytes of the base address. However, the kernel
     * functions are all aligned so that the final nibble is 0x0, so we only
     * have to check every 16th address.
   */
   for ( i = 0x0 ; i < 0x100000 ; i   )
   {
      /*
        * Lookup the name ascribed to the current kernel address
      */
      sprint_symbol(fname_lookup, kaddr);

      /*
       * Compare the looked-up name to the one we want
      */
      if ( strncmp(fname_lookup, fname, strlen(fname)) == 0 )
      {
          /*
            * Clean up and return the found address
           */
          kvfree(fname_lookup);
          return kaddr;
      }
      /*
       * Jump 16 addresses to next possible address
       */
      kaddr  = 0x10;
   }
   /*
    * We didn't find the name, so clean up and return 0
    */
   kvfree(fname_lookup);
   return 0;
}


MODULE_LICENSE("Dual BSD/GPL");

typedef int (* syscall_wrapper)(struct pt_regs *);

unsigned long sys_call_table_addr;

#define SOCKETLOG "[SOCKETLOG]"


int enable_page_rw(void *ptr){
   unsigned int level;
   pte_t *pte = lookup_address((unsigned long) ptr, &level);
   if(pte->pte &~_PAGE_RW){
     pte->pte |=_PAGE_RW;
   }
   return 0;
 }

 int disable_page_rw(void *ptr){
    unsigned int level;
    pte_t *pte = lookup_address((unsigned long) ptr, &level);
    pte->pte = pte->pte &~_PAGE_RW;
    return 0;
  }

  syscall_wrapper original_bind;

 //asmlinkage int log_bind(int sockfd, const struct sockaddr *addr, int addrlen) {
 int log_bind(struct pt_regs *regs) {
    printk("bind was called");
    return (*original_bind)(regs);
 }

 static int __init start(void) {

    printk("socketlog module has been loaded\n");

    sys_call_table_addr = kaddr_lookup_name("sys_call_table");

    printk("sys_call_table@%lx\n", sys_call_table_addr);

    enable_page_rw((void *)sys_call_table_addr);
    original_bind = ((syscall_wrapper *)sys_call_table_addr)[__NR_bind];
    if (!original_bind) return -1;
    ((syscall_wrapper *)sys_call_table_addr)[__NR_bind] = log_bind;
    disable_page_rw((void *)sys_call_table_addr);

    printk("original_bind = %p", original_bind);
    return 0;
 }

 static void __exit stop(void) {
    printk("socketlog module has been unloaded\n");

    enable_page_rw((void *)sys_call_table_addr);
    ((syscall_wrapper *)sys_call_table_addr)[__NR_bind] = original_bind;
    disable_page_rw((void *)sys_call_table_addr);
 }

 module_init(start);
 module_exit(stop);

I compile this module and tried to run "sudo insmod name_module.ko".And then the command got stuck and kiled, like that: enter image description here

And the module does not apload.System I use it Ubuntu 22.04(the kernel version is 5.15).

CodePudding user response:

It should be caused by the value returned by kaddr_lookup_name is 0,

you try to change

for ( i = 0x0 ; i < 0x100000 ; i   ) 

to

( i = 0x0 ; i < 0x200000 ; i   )
  • Related