ubuntu - 在 ubuntu 22.04 中挂接系统调用(内核版本为 5.15)

标签 ubuntu linux-kernel kernel kernel-module

我试图创建内核模块,以 Hook 到“bind”(sys_bind)的系统调用。模块:

#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);
我编译了这个模块并尝试运行“sudo insmod name_module.ko”。然后命令被卡住并被杀死,就像这样:
enter image description here
而且模块没有apload。系统我用的是Ubuntu 22.04(内核版本是5.15)。

最佳答案

应该是kaddr_lookup_name返回的值为0造成的,
你试着改变

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

关于ubuntu - 在 ubuntu 22.04 中挂接系统调用(内核版本为 5.15),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72071979/

相关文章:

linux - 如何强制禁用 intel_pstate?即使在 grub 中使用 intel_pstate=disable 选项,intel_pstate 也会在重新启动时启用

linux - Linux 中的上下文切换内核进程

linux - 如何定义设备标签名称,g_mass_storage 模块

linux - 如何将/dev/sda 与/dev/sdb 交换?

c - 当用户空间程序调用系统调用时,执行如何转移回内核空间?

Ubuntu 13.04 中的 Qt5 QtCreator 丑陋字体

Ubuntu 16.04无法安装Python 3.6.0?

ubuntu - 安装时 sublime text 3 包控制卡住

shell - sed 命令不会替换我想要的模式?

在 64 位 arch 上转换一个指向整数的问题警告