Syscall 劫持 x64 - 无法在 ffffffff91000018 处理内核分页请求

Posted

技术标签:

【中文标题】Syscall 劫持 x64 - 无法在 ffffffff91000018 处理内核分页请求【英文标题】:Syscall hijacking x64- unable to handle kernel paging request at ffffffff91000018 【发布时间】:2018-03-17 08:09:33 【问题描述】:

我编写了一个替换syscall 的内核模块,但遇到了问题。模块无法加载,因为内存有问题。我尝试修复它 3 小时,但它仍然无法正常工作。当我选择内存更接近sys_call_table(例如来自/proc/kallsyms 的linux_banner 地址)时,此代码有效,但它并不总是有效。

问题通常是,当搜索系统调用表的函数指向地址的一端是 18 时(例如ffffffff91000018ffffffff81000018)。

为什么它不起作用?

代码:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/list.h>
#include <linux/unistd.h>
#include <linux/kobject.h>
#include <linux/init.h>

 /* start of 64-bit kernel space is 0xffffffff80000000 */
#define END_MEM   0xffffffffffffffff /* end of 64-bit kernel */
#define START_MEM 0xffffffff81000000

unsigned long long **syscall_tab;
asmlinkage long (*orig_mkdir)(const char __user *pathname, umode_t mode);

asmlinkage long my_mkdir(const char __user *pathname, umode_t mode)

  long ret;
  ret = orig_mkdir(pathname, mode);
  printk("Creating dir: %s", pathname);
  return ret;


static void hide(void)

  list_del(&THIS_MODULE->list);
  kobject_del(&THIS_MODULE->mkobj.kobj);

static unsigned long long **find(void) 
    unsigned long long **sctable;
    unsigned long long i = START_MEM;

    while (i < END_MEM) 
        sctable = (unsigned long long **) i;

        if ( sctable[__NR_close] == (unsigned long long *) sys_close) 
            printk("syscall_tab %lx", syscall_tab);
            return &sctable[0];
        
        i += sizeof(void *);
    

    return NULL;


static int __init init(void)

  write_cr0(read_cr0() & (~0x10000));
  if(!(syscall_tab = find())) 
    return 0;
  
  orig_mkdir = (void *) syscall_tab[__NR_mkdir];

  printk("write_cr0");
  syscall_tab[__NR_mkdir] = (unsigned long long*) my_mkdir;
  printk("po podmiance");
  write_cr0(read_cr0() | (~0x10000));
  return 0;


static void __exit exitt(void)

  write_cr0(read_cr0() & (~0x10000));
  syscall_tab[__NR_mkdir] = (unsigned long long*) orig_mkdir;
  write_cr0(read_cr0() | (~0x10000));

module_init(init);
module_exit(exitt);
MODULE_LICENSE("GPL");

错误:

[  299.273838] BUG: unable to handle kernel paging request at ffffffff91000018
[  299.273856] IP: init+0x23/0x1000 [hijack1]
[  299.273860] PGD b6a0c067 
[  299.273861] P4D b6a0c067 
[  299.273863] PUD b6a0d063 
[  299.273866] PMD 0 

[  299.273872] Oops: 0000 [#1] PREEMPT SMP
[  299.273877] Modules linked in: hijack1(O+) fuse rfcomm bnep nls_iso8859_1 nls_cp437 vfat fat intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel pcbc aesni_intel joydev ppdev hp_wmi mousedev iTCO_wdt aes_x86_64 sparse_keymap iTCO_vendor_support mei_wdt crypto_simd psmouse glue_helper pcspkr evdev input_leds cryptd mac_hid intel_cstate intel_rapl_perf uvcvideo videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_core btusb btrtl btbcm btintel bluetooth cdc_ether ecdh_generic usbnet videodev uas media mii hid_generic nouveau mxm_wmi ttm arc4 drm_kms_helper iwldvm drm syscopyarea sysfillrect mac80211 sysimgblt iwlwifi fb_sys_fops parport_pc parport snd_hda_codec_hdmi i2c_algo_bit snd_hda_codec_idt cfg80211
[  299.273953]  rfkill snd_hda_codec_generic hp_accel thermal lis3lv02d wmi input_polldev tpm_infineon video ac battery button snd_hda_intel snd_hda_codec snd_hda_core snd_hwdep snd_pcm shpchp snd_timer e1000e snd ptp soundcore tpm_tis mei_me mei pps_core lpc_ich tpm_tis_core tpm sch_fq_codel vboxnetflt(O) vboxnetadp(O) pci_stub vboxpci(O) vboxdrv(O) sg ip_tables x_tables ext4 crc16 jbd2 fscrypto mbcache sr_mod sd_mod cdrom usb_storage usbhid hid serio_raw atkbd libps2 ahci libahci libata scsi_mod xhci_pci xhci_hcd ehci_pci sdhci_pci ehci_hcd sdhci firewire_ohci led_class firewire_core mmc_core crc_itu_t usbcore usb_common i8042 serio
[  299.274005] CPU: 2 PID: 3384 Comm: insmod Tainted: G           O    4.12.4-1-ARCH #1
[  299.274009] Hardware name: Hewlett-Packard HP EliteBook 8560w/1631, Bios 68SVD Ver. F.60 03/12/2015
[  299.274014] task: ffff90127cc0c740 task.stack: ffffb72907298000
[  299.274019] RIP: 0010:init+0x23/0x1000 [hijack1]
[  299.274023] RSP: 0018:ffffb7290729bc88 EFLAGS: 00010206
[  299.274027] RAX: 0000000080040033 RBX: ffffffff91000000 RCX: 0000000000000000
[  299.274031] RDX: 00000000004bec82 RSI: 00000000004bec82 RDI: 0000000080040033
[  299.274036] RBP: ffffb7290729bc90 R08: ffff901339003980 R09: ffffffffa018970a
[  299.274040] R10: ffffe481c211ebc0 R11: 0000000000000000 R12: ffffffffc0030000
[  299.274044] R13: ffff9012377965e0 R14: ffffffffc0a81050 R15: ffff90132e0eca80
[  299.274049] FS:  00007f9a842a4b80(0000) GS:ffff90133dc80000(0000) knlGS:0000000000000000
[  299.274053] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080040033
[  299.274057] CR2: ffffffff91000018 CR3: 000000007cdb9000 CR4: 00000000000406e0
[  299.274061] Call Trace:
[  299.274068]  do_one_initcall+0x50/0x190
[  299.274073]  ? do_init_module+0x27/0x1e6
[  299.274077]  do_init_module+0x5f/0x1e6
[  299.274082]  load_module+0x2610/0x2ab0
[  299.274087]  ? vfs_read+0x115/0x130
[  299.274091]  SYSC_finit_module+0xf6/0x110
[  299.274095]  ? SYSC_finit_module+0xf6/0x110
[  299.274100]  SyS_finit_module+0xe/0x10
[  299.274105]  entry_SYSCALL_64_fastpath+0x1a/0xa5
[  299.274109] RIP: 0033:0x7f9a839b3bb9
[  299.274111] RSP: 002b:00007ffd2386ee28 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[  299.274120] RAX: ffffffffffffffda RBX: 00007f9a83c74aa0 RCX: 00007f9a839b3bb9
[  299.274124] RDX: 0000000000000000 RSI: 000000000041aada RDI: 0000000000000003
[  299.274128] RBP: 00007f9a83c74af8 R08: 0000000000000000 R09: 00007f9a83c76e40
[  299.274132] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000001020
[  299.274136] R13: 0000000000001018 R14: 00007f9a83c74af8 R15: 0000000000000001
[  299.274141] Code: <48> 81 7b 18 40 a8 21 a0 75 2d 48 8b 35 14 13 a5 00 48 c7 c7 35 00 
[  299.276347] RIP: init+0x23/0x1000 [hijack1] RSP: ffffb7290729bc88
[  299.277333] CR2: ffffffff91000018
[  299.283408] ---[ end trace 63ac9e1e3a0e12c3 ]---

【问题讨论】:

【参考方案1】:

Syscall 劫持 x64 - 无法在 ffffffff91000018 处处理内核分页请求...

我编写了替换系统调用的内核模块并且有问题。模块无法加载,因为内存有问题。我尝试修复它 3 小时,但它仍然无法正常工作......

问题是,劫持系统调用在技术上是不可行的。你不能用 Linux 做到这一点。 Linux 没有支持这种东西的分层设计(与 Windows 或其他操作系统相反)。

您能做的最好的事情就是插入,它将通过 PLT 进行的调用重定向到您的共享对象中。我相信这就是 Valgrind 在替换 mallocfree 时的工作方式。

另请注意,某些系统调用通过 PLT 路由。请参阅 glibc wiki 上对 Double-underscore names for public API functions 的讨论。

另请参阅 Kernel Newbies 邮件列表上的 Query regarding kernel modules intercepting system call 和 Stack Overflow 上的 Multiple kernel modules intercepting same system call and crash during unload。第一个是内核开发人员告诉 OP 不可能的问题。我只是重申内核开发人员已经说过的内容。

【讨论】:

谢谢,但是在 32 位系统中系统调用劫持是可能的,那么为什么在这种情况下它在技术上不可行? @Wiktoria - 这不是我的专业领域,所以请谨慎对待。但是,当内核开发人员说不可能时,我倾向于相信他们。也许你应该在内核新手邮件列表上要求澄清。内核开发人员在内核新手邮件列表上更加平易近人。你和其他内核邮件列表上的鲨鱼一起游泳:)

以上是关于Syscall 劫持 x64 - 无法在 ffffffff91000018 处理内核分页请求的主要内容,如果未能解决你的问题,请参考以下文章

text WinLogon Windows 7 x64 COM劫持

x64: 如何做一个相对的 jmp *%rax?

ptrace x64 转

Google VR 查看错误 - 无法从 ffff.jpg 加载纹理

无法在 x64 中构建 gdal

IOCP 无法在 x64 平台上运行