偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

如何在任意進(jìn)程中修改內(nèi)存保護(hù)屬性

存儲(chǔ) 存儲(chǔ)軟件
最近,我們?cè)谶M(jìn)行一項(xiàng)安全研究時(shí),需要在任意進(jìn)程中修改內(nèi)存空間的保護(hù)標(biāo)志。在解決這些問(wèn)題的過(guò)程中,我們學(xué)到了一些新的東西,主要是關(guān)于Linux機(jī)制和內(nèi)核開(kāi)發(fā)的。本文將介紹我們所采取的三種方法以及每次尋求更好解決方案的原因。
最近,我們?cè)谶M(jìn)行一項(xiàng)安全研究時(shí),需要在任意進(jìn)程中修改內(nèi)存空間的保護(hù)標(biāo)志。起初,我們發(fā)現(xiàn)這項(xiàng)任務(wù)看起來(lái)很簡(jiǎn)單,但在實(shí)際操作中,卻發(fā)現(xiàn)困難重重,還好這些都不是什么大問(wèn)題。在解決這些問(wèn)題的過(guò)程中,我們還學(xué)到了一些新的東西,主要是關(guān)于Linux機(jī)制和內(nèi)核開(kāi)發(fā)的。在以下的詳解中,我們會(huì)介紹我們所采取的三種方法以及每次尋求更好解決方案的原因。
 
背景介紹
 
在現(xiàn)代操作系統(tǒng)中,每個(gè)進(jìn)程都有自己的虛擬地址空間(從虛擬地址到物理地址的映射)。此虛擬地址空間由內(nèi)存頁(yè)面(某些固定大小的連續(xù)內(nèi)存塊)組成,且每個(gè)頁(yè)面都有保護(hù)標(biāo)志,這些保護(hù)標(biāo)志決定了允許對(duì)該頁(yè)面的訪問(wèn)類(lèi)型(讀取、寫(xiě)入和執(zhí)行)。不過(guò),這種機(jī)制依賴(lài)于架構(gòu)頁(yè)表(architecture page table)。不過(guò)要注意的是,在x64的架構(gòu)中,你不能只進(jìn)行頁(yè)面寫(xiě)入,即使你是特意從操作系統(tǒng)請(qǐng)求的,也都同時(shí)具有頁(yè)面寫(xiě)入和可讀的功能。
 
在Windows中,你可以使用API函數(shù)VirtualProtect或VirtualProtectEx修改內(nèi)存空間的保護(hù)。VirtualProtectEx使我們的修改任務(wù)變得非常簡(jiǎn)單:因?yàn)樗?**個(gè)參數(shù)hProcess是“要修改其內(nèi)存保護(hù)的進(jìn)程的句柄”。
 
不過(guò),在Linux中,修改過(guò)程就沒(méi)有這么簡(jiǎn)單了,因?yàn)樾薷膬?nèi)存保護(hù)的API是系統(tǒng)調(diào)用mprotect或pkey_mprotect的結(jié)果,并且這兩個(gè)函數(shù)始終在當(dāng)前進(jìn)程的地址空間上運(yùn)行?,F(xiàn)在讓我們想辦法解決一下如何在x64架構(gòu)上的Linux中解決修改的問(wèn)題,不過(guò)前提條件是,我們具有修改設(shè)備的root權(quán)限。

[[251304]]

 
方法一:代碼注入
 
如果mprotect總是在當(dāng)前進(jìn)程中運(yùn)行,我們需要讓目標(biāo)進(jìn)程從它自己的上下文中調(diào)用它。這時(shí)就要用到代碼注入了,該方法可以通過(guò)許多不同的方式實(shí)現(xiàn)。我們可以選擇使用ptrace機(jī)制實(shí)現(xiàn)它,該機(jī)制允許一個(gè)進(jìn)程“觀察和控制另一個(gè)進(jìn)程的執(zhí)行”,包括修改目標(biāo)進(jìn)程的內(nèi)存和寄存器的能力。這種機(jī)制用于調(diào)試器(如gdb)和跟蹤實(shí)用程序(如strace),使用ptrace注入代碼所需的步驟如下:
 
1.使用ptrace附加到目標(biāo)進(jìn)程,如果進(jìn)程中有多個(gè)線程,那么***停止所有其他線程;
 
2.找到一個(gè)可執(zhí)行的內(nèi)存空間(通過(guò)檢查/ proc / PID / maps),并在這個(gè)空間編寫(xiě)操作碼syscall(十六進(jìn)制:0f05);
 
3.根據(jù)調(diào)用約定來(lái)修改寄存器,首先,將rax修改為mprotect的系統(tǒng)調(diào)用號(hào)(即10);然后,前三個(gè)參數(shù)(即起始地址、長(zhǎng)度和所需的保護(hù))分別存儲(chǔ)在rdi、rsi和rdx中;***,將rip修改為步驟2中使用的地址;
 
4.繼續(xù)這個(gè)過(guò)程,直到系統(tǒng)調(diào)用返回(ptrace允許你跟蹤系統(tǒng)調(diào)用的進(jìn)入和退出);
 
5.恢復(fù)被修改的內(nèi)存和寄存器,從進(jìn)程中將其分離并恢復(fù)正常執(zhí)行;
 
這種方法是我們的采用的***個(gè)也是最直觀的方法,并且非常有效。不過(guò)在我們發(fā)現(xiàn)了Linux中的另一種完全破壞機(jī)制:利用seccomp進(jìn)行破壞之后,該方法就不是我們的***選擇了?;旧?,它是Linux內(nèi)核中的一個(gè)安全工具,允許進(jìn)程輸入某種形式的“監(jiān)獄”,除了read,write,_exit和sigreturn之外,它不能進(jìn)行任何系統(tǒng)調(diào)用。還有一個(gè)選項(xiàng),可以指定任意的系統(tǒng)調(diào)用及針對(duì)它們的過(guò)濾參數(shù)。
 
因此,如果進(jìn)程啟用了seccomp模式并且我們嘗試將一個(gè)對(duì)mprotect的調(diào)用注入其中,那么內(nèi)核將終止進(jìn)程,因?yàn)樵撨M(jìn)程是不允許使用此系統(tǒng)調(diào)用的。因此,要對(duì)這些進(jìn)程進(jìn)行調(diào)用,就要采用方法二。
 
方法二:在內(nèi)核模塊中模擬mprotect系統(tǒng)調(diào)用
 
seccomp(全稱(chēng)securecomputing mode)是linuxkernel從2.6.23版本開(kāi)始所支持的一種安全機(jī)制。
 
在Linux系統(tǒng)里,大量的系統(tǒng)調(diào)用直接暴露給用戶(hù)態(tài)程序。但是,并不是所有的系統(tǒng)調(diào)用都被需要,而且不安全的代碼濫用系統(tǒng)調(diào)用會(huì)對(duì)系統(tǒng)造成安全威脅。通過(guò)seccomp,我們限制程序使用某些系統(tǒng)調(diào)用,這樣可以減少系統(tǒng)的暴露面,同時(shí)是程序進(jìn)入一種“安全”的狀態(tài)。
 
由于Linux中存在另一種完全破壞機(jī)制:利用seccomp進(jìn)行破壞,因此這個(gè)方法肯定要在內(nèi)核模式中進(jìn)行。在Linux內(nèi)核中,每個(gè)線程(包括用戶(hù)線程和內(nèi)核線程)都由一個(gè)名為task_struct的結(jié)構(gòu)表示,并且當(dāng)前線程(任務(wù))可以通過(guò)pointer current訪問(wèn)。內(nèi)核中mprotect的內(nèi)部實(shí)現(xiàn)使用了pointer current,因此我們的***個(gè)想法是,只要將mprotect的代碼復(fù)制粘貼到內(nèi)核模塊中,并將每次出現(xiàn)的current替換為指向目標(biāo)線程task_struct的指針,不就可以了嗎?
 
接下來(lái)的事情你可能已經(jīng)猜到了,就是復(fù)制C代碼,不過(guò)復(fù)制過(guò)程并不是你想的那么簡(jiǎn)單,因?yàn)槠渲写嬖诖罅渴褂梦覀儫o(wú)法訪問(wèn)的未導(dǎo)出的函數(shù)、變量和宏。某些函數(shù)說(shuō)明會(huì)在標(biāo)頭文件中導(dǎo)出,但是它們的實(shí)際地址不是由內(nèi)核導(dǎo)出的。如果內(nèi)核是用linux內(nèi)核符號(hào)表kallsyms編譯的,那么通過(guò)文件/ proc / kallsysm導(dǎo)出所有內(nèi)部符號(hào),這個(gè)特定的問(wèn)題就可以解決。因?yàn)閗allsyms在進(jìn)行源碼調(diào)試時(shí)具有相當(dāng)重要的作用,它可以描述所有不處在堆棧上的內(nèi)核符號(hào)。linux內(nèi)核在編譯的過(guò)程中,將內(nèi)核中所有的符號(hào)(所有的內(nèi)核函數(shù)以及已經(jīng)裝載的模塊)及符號(hào)的地址以及符號(hào)的類(lèi)型信息都保存在了/proc/kallsyms文件中。
 
盡管存在這個(gè)特定問(wèn)題,我們?nèi)匀辉噲D實(shí)現(xiàn)mprotect調(diào)用。為此,我們特意編寫(xiě)一個(gè)內(nèi)核模塊,利用該模塊獲取目標(biāo)PID和參數(shù)以進(jìn)行mprotect,并模仿其調(diào)用行為。首先,我們需要獲取所需的內(nèi)存映射對(duì)象,用它表示線程的地址空間:
  1. /* Find the task by the pid */ 
  2.     pid_struct = find_get_pid(params.pid); 
  3.     if (!pid_struct) 
  4.         return -ESRCH; 
  5.  
  6.     task = get_pid_task(pid_struct, PIDTYPE_PID); 
  7.     if (!task) { 
  8.         ret = -ESRCH; 
  9.         goto out
  10.     } 
  11.  
  12.     /* Get the mm of the task */ 
  13.     mm = get_task_mm(task); 
  14.     if (!mm) { 
  15.         ret = -ESRCH; 
  16.         goto out
  17.     } 
  18.  
  19.     … 
  20.     … 
  21.  
  22. out
  23.     if (mm) mmput(mm); 
  24.     if (task) put_task_struct(task); 
  25.     if (pid_struct) put_pid(pid_struct); 
現(xiàn)在我們已經(jīng)獲得了內(nèi)存映射對(duì)象,這大大方便了以后的操作。 Linux內(nèi)核實(shí)現(xiàn)了一個(gè)抽象層來(lái)管理內(nèi)存空間,每個(gè)空間由結(jié)構(gòu)vm_area_struct表示。為了找到正確的內(nèi)存空間,我們使用函數(shù)find_vma,該函數(shù)會(huì)根據(jù)所需地址搜索內(nèi)存映射。
 
vm_area_struct包含字段vm_flags,它以獨(dú)立于架構(gòu)的方式來(lái)表示內(nèi)存空間的保護(hù)標(biāo)志,vm_page_prot也以獨(dú)立于架構(gòu)的方式來(lái)表示內(nèi)存空間的保護(hù)標(biāo)志。單獨(dú)修改這些字段并不會(huì)真正影響頁(yè)表(但會(huì)影響/proc/PID/maps的輸出,我們已經(jīng)嘗試過(guò)了),詳情請(qǐng)點(diǎn)擊這里。
 
在對(duì)內(nèi)核代碼進(jìn)行了一些閱讀和深入研究之后,我們發(fā)現(xiàn)要真正攻破內(nèi)存空間的保護(hù),最重要的工作是以下3方面:
 
1.將字段vm_flags修改為所需的保護(hù);
 
2.調(diào)用函數(shù)vma_set_page_prot_func,再根據(jù)vm_flags字段來(lái)更新字段vm_page_prot;
 
3. 調(diào)用change_protection_func函數(shù)來(lái)實(shí)際修改頁(yè)表中的保護(hù)位;
 
雖然以上的那段代碼很有效,但其中也存在著很多問(wèn)題。首先,我們只實(shí)現(xiàn)了mprotect的基本部分,但原始函數(shù)的基本功能卻比我們能開(kāi)發(fā)的要多得多,例如,通過(guò)保護(hù)標(biāo)志分離和連接內(nèi)存空間。其次,我們使用了兩個(gè)內(nèi)核函數(shù)(vma_set_page_prot_func和change_protection_func),這些函數(shù)不是由內(nèi)核導(dǎo)出的。此時(shí),我們可以使用kallsyms來(lái)調(diào)用它們,但是這很容易出現(xiàn)問(wèn)題,因?yàn)閷?lái)我們可能會(huì)修改它們的名稱(chēng),或者將內(nèi)存空間的整個(gè)內(nèi)部實(shí)現(xiàn)進(jìn)行修改。不過(guò),我們想要一個(gè)更通用的解決方案,即不考慮內(nèi)部結(jié)構(gòu)的方案,此時(shí),就有了方法三。

方法三:使用目標(biāo)進(jìn)程的內(nèi)存映射
 
方法三與***種方法非常相似,即都要目標(biāo)進(jìn)程的上下文中執(zhí)行代碼。雖然,這兩個(gè)方法都可以在我們自己的線程中執(zhí)行代碼,但在方法三中,我們使用的是目標(biāo)進(jìn)程的“內(nèi)存上下文”,這意味著,我們要使用內(nèi)存中的地址空間。
 
我們通過(guò)幾個(gè)API函數(shù)就可以在內(nèi)核模式下修改地址空間,其中就用到了use_mm。正如use_mm的介紹中明確指出的那樣“此例程僅會(huì)被用于從內(nèi)核線程上下文中進(jìn)行調(diào)用”。由于這些線程是在內(nèi)核中創(chuàng)建的,不需要任何用戶(hù)地址空間,因此可以修改它們的地址空間(地址空間內(nèi)的內(nèi)核區(qū)域在每個(gè)任務(wù)中都以相同的方式映射)。
 
在內(nèi)核線程中運(yùn)行代碼的一種簡(jiǎn)單方法就是通過(guò)內(nèi)核的運(yùn)行隊(duì)列接口(queue interface),它允許你使用特定例程和特定參數(shù)來(lái)進(jìn)行進(jìn)程調(diào)用。我們的工作例程也非常簡(jiǎn)單,它會(huì)獲取所需進(jìn)程的內(nèi)存映射對(duì)象和mprotect的參數(shù),并執(zhí)行以下操作(do_mprotect_pkey是內(nèi)核中實(shí)現(xiàn)mprotect和pkey_mprotect系統(tǒng)調(diào)用的內(nèi)部函數(shù)):
  1. use_mm(suprotect_work->mm); 
  2. suprotect_work->ret_value = do_mprotect_pkey(suprotect_work->start, 
  3.                                              suprotect_work->len, 
  4.                                              suprotect_work->prot, -1); 
  5. unuse_mm(suprotect_work->mm); 
當(dāng)我們的內(nèi)核模塊在某個(gè)進(jìn)程(通過(guò)一個(gè)特殊的IOCTL)獲得修改保護(hù)的請(qǐng)求時(shí),該請(qǐng)求首先會(huì)找到所需的內(nèi)存映射對(duì)象(正如我們?cè)谇懊娴姆椒ㄖ兴忉尩哪菢樱?,然后再使用正確的參數(shù)來(lái)調(diào)用進(jìn)程。
 
不過(guò)這個(gè)解決方案仍有一個(gè)小問(wèn)題,即函數(shù)do_mprotect_pkey_func不會(huì)由內(nèi)核導(dǎo)出,需要使用kallsyms獲取。與***個(gè)解決方案不同,這個(gè)解決方案中的內(nèi)部函數(shù)不太容易被修改,因?yàn)樵摵瘮?shù)與系統(tǒng)調(diào)用pkey_mprotect有關(guān),而且我們也不用處理內(nèi)部結(jié)構(gòu),因此我們只能將其稱(chēng)為“小問(wèn)題”。
 
我們希望你在這篇文章中找到一些有趣的信息和技巧,學(xué)會(huì)如何在任意進(jìn)程中修改內(nèi)存保護(hù)屬性。如果你有興趣,可以在github中找到這個(gè)概念驗(yàn)證內(nèi)核模塊的源代碼。
責(zé)任編輯:武曉燕 來(lái)源: 4hou
相關(guān)推薦

2019-01-03 16:04:13

內(nèi)存Linux PoC

2018-07-27 05:08:58

2010-08-05 16:08:12

輕松掌握DB2 9.5

2019-12-16 10:43:38

Linux內(nèi)存消耗進(jìn)程

2019-11-06 15:58:54

Linux內(nèi)存消耗進(jìn)程

2021-08-30 06:59:07

x86處理器內(nèi)存

2023-01-27 09:17:02

操作系統(tǒng)虛擬化內(nèi)存

2023-03-05 16:40:07

linux進(jìn)程內(nèi)存

2023-01-30 00:05:02

操作系統(tǒng)虛擬化安全

2021-07-16 08:00:00

開(kāi)發(fā)VSCode編輯器

2018-05-31 11:58:06

Linux進(jìn)程Early OOM

2016-07-29 11:21:16

Ubuntulinux程序

2023-01-30 14:27:14

Linux進(jìn)程

2018-08-23 10:50:08

Windows 10Windows隱私

2020-05-19 11:54:04

腳本語(yǔ)言Linux命令

2019-01-07 10:24:41

2022-07-05 17:49:34

元宇宙安全隱私保護(hù)

2021-01-13 07:33:41

API數(shù)據(jù)安全

2021-08-14 22:29:42

Backstab進(jìn)程安全工具

2015-10-22 13:07:29

USB設(shè)備權(quán)限Linux
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)