Linux漏洞挖掘:08---系統呼叫劫持之(通過IDT中斷向量表獲取sys_call_table系統呼叫表)
- 在前面兩篇文章中(https://blog.csdn.net/qq_41453285/article/details/103050710、https://blog.csdn.net/qq_41453285/article/details/103055369),我們介紹過兩種方式獲取sys_call_table系統呼叫表的地址,本片文章介紹使用IDT中斷向量表獲取sys_call_table系統呼叫表的地址並劫持改寫mkdir系統呼叫
一、IDT中斷向量表簡介
- IDT是中斷向量表,其被分為許多個段,一個段被分為中斷號和中斷處理函式
二、通過IDT中斷向量表獲取sys_call_table系統呼叫表
- IDT這個表的地址是在特殊暫存器中儲存的,而這個特殊暫存器的地址是我們可以通過程式設計設計獲取的
- 在系統呼叫詳細文章中(見文章:https://blog.csdn.net/qq_41453285/article/details/102810100),我們介紹過,sys_call_table的的中斷號為0x80。其也是存在於IDT中,因此我們可以先獲取IDT表的指標,再根據地址偏移,獲取中斷號為0x80的地址,再進一步獲取sys_call_table系統呼叫表的地址
三、編碼實現
- 這個演示案例中我們先通過IDT獲取sys_call_table的地址,然後再通過sts_call_table改寫mkdir系統呼叫系統呼叫
idt.c程式設計
//lkm.c #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/unistd.h> #include <linux/sched.h> #include <linux/kallsyms.h> #include <asm/cacheflush.h> #include <asm/page.h> #include <asm/current.h> unsigned long *sys_call_table; struct { unsigned short size; unsigned int addr; }__attribute__((packed)) idtr; struct { unsigned short offset_1; unsigned short selector; unsigned char zero; unsigned char type_attr; unsigned short offset_2; }__attribute__((packed)) idt; unsigned long *find_sys_call_table(void) { unsigned int sys_call_off; char *p; int i; unsigned int ret; asm("sidt %0":"=m"(idtr)); //通過idtr獲取IDT表的地址 printk("Arciryas:idt table-0x%x\n", idtr.addr); //將0x80處sys_call_table的地址存放到idt中 memcpy(&idt, idtr.addr+8*0x80, sizeof(idt));//IDT表一行佔8個位元組,所以8*0x80 sys_call_off = ((idt.offset_2<<16) | idt.offset_1); p = sys_call_off; for(i=0; i<100; i++) { if(p[i]=='\xff' && p[i+1]=='\x14' && p[i+2]=='\x85') //sys_call_table的call硬編碼 ret = *(unsigned int *)(p+i+3); } printk("Arciryas:sys_call_table-0x%x\n", ret); return (unsigned long**)ret; } asmlinkage long (*real_mkdir)(const char __user *pathname,umode_t mode); asmlinkage long fake_mkdir(const char __user *pathname, umode_t mode) { printk("Arciryas:mkdir-%s\n", pathname); return (*real_mkdir)(pathname, mode); } static int lkm_init(void) { sys_call_table = find_sys_call_table(); write_cr0(read_cr0() & (~0x10000)); real_mkdir = (void *)sys_call_table[__NR_mkdir]; sys_call_table[__NR_mkdir] = fake_mkdir; write_cr0(read_cr0() | 0x10000); printk("Arciryas:module loaded\n"); return 0; } static void lkm_exit(void) { write_cr0(read_cr0() & (~0x10000)); sys_call_table[__NR_mkdir] = real_mkdir; write_cr0(read_cr0() | 0x10000); printk("Arciryas:module removed\n"); } module_init(lkm_init); module_exit(lkm_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("dongshao"); MODULE_DESCRIPTION("hook mkdir");
Makefile設計
KVERS = $(shell uname -r) # Kernel modules obj-m += lkm.o # Specify flags for the module compilation. #EXTRA_CFLAGS=-g -O0 build: kernel_modules kernel_modules: make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules clean: make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean
程式碼解析
- 這個函式是核心模組的載入函式
- 我們首先通過自定義find_sys_call_table函式(下面介紹)獲取sys_call_table的地址
- 然後開啟核心記憶體防寫,準備改寫系統呼叫
- 我們先通過__NR_mkdir索引獲取原本核心的sys_mkdir函式,然後再將__NR_mkdir索引處的函式改為我們自己的函式fake_mkdir
- 之後關閉記憶體防寫,然後列印一些資訊
- 這個函式用來獲取sys_call_table的地址,然後通過返回值返回
- fake_mkdir是我們自定義的函式,我們使用strstr函式判斷:
- 如果建立的目錄名中有“CSDN”字串,那麼strstr就返回非NULL,就執行else返回0,返回0之後,sys_call_table[__NR_mkdir]索引處就被置空了,那麼mkdir系統呼叫就什麼都不會做了
- 如果建立的目錄名中沒有“CSDN”字串,那麼就呼叫返回我們儲存的原來sys_mkdir的函式指標
- 這個是核心模組的UI出清除模組,與核心載入模組類似,只是將核心原有的sys_mkdir指標重新賦值給sys_call_table系統呼叫表
演示效果
- 首先編譯模組
make
- 載入模組,然後檢視核心列印的資訊,可以看到核心模組列印的sys_call_table系統呼叫表地址
- 本人在實驗的時候不知道什麼原因,模組載入之後失敗了,好在模組列印了IDT表的地址。但是又不能解除安裝了,核心出錯了,我們只好重啟系統來重新引導核心
相關文章
- 作業系統 中斷異常系統呼叫作業系統
- Linux系統呼叫過程分析Linux
- 【作業系統2】作業系統啟動過程與異常/中斷,系統呼叫作業系統
- linux系統程式設計之檔案與IO(五):stat()系統呼叫獲取檔案資訊Linux程式設計
- Kernel Module實戰指南(四):系統呼叫劫持
- Linux系統呼叫原理Linux
- linux系統呼叫getoptLinux
- Linux系統呼叫列表Linux
- iOS中 讀取相簿,呼叫系統相機iOS
- perl中呼叫系統命令
- 系統呼叫篇——3環層面呼叫過程
- 4.系統呼叫如何安全地獲取引數
- dup()系統呼叫
- Windows 系統呼叫Windows
- 系統呼叫篇——0環層面呼叫過程(上)
- 系統呼叫篇——0環層面呼叫過程(下)
- Linux系統呼叫講義(轉)Linux
- C#中通過API呼叫獲取檔案圖示C#API
- 通過PowerShell獲取Windows系統密碼HashWindows密碼
- C程式函式呼叫&系統呼叫C程式函式
- Linux作業系統分析 | 深入理解系統呼叫Linux作業系統
- linux系統程式設計之訊號(七):被訊號中斷的系統呼叫和庫函式處理方式Linux程式設計函式
- x86_64系統呼叫過程
- 系統呼叫篇——SSDT
- Linux系統呼叫機制淺析Linux
- MacOS Big Sur系統不需要通過獲取系統許可權而獲取HidpiMac
- 作業系統動態庫呼叫過程作業系統
- android 呼叫系統介面Android
- 系統呼叫,上下文切換及中斷概念的彙總
- 線上環境 Linux 系統呼叫追蹤Linux
- Linux 下系統呼叫的三種方法Linux
- linux系統呼叫第一篇Linux
- 獲取系統字型,獲取系統預設字型
- Linux中斷子系統Linux
- xenomai核心解析之雙核系統呼叫(一)AI
- linux系統程式設計之檔案與IO(二):系統呼叫read和writeLinux程式設計
- Android呼叫系統相機,相容7.0系統Android
- Linux系統程式設計(七)檔案許可權系統呼叫Linux程式設計