成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入Linux | 如何在任意進程中修改內存保護(含PoC)

存儲 存儲軟件
在現(xiàn)代操作系統(tǒng)中,每個進程都有自己的虛擬地址空間(從虛擬地址映射到物理地址)。此虛擬地址空間由內存頁(某些固定大小的連續(xù)內存塊)組成,每個頁都有保護標志,用于確定允許此頁面訪問的類型(讀取,寫入和執(zhí)行)。

 前言

最近,我們遇到一個非常具體的問題:改變任意進程的內存區(qū)域的保護標志。這項任務看似微不足道,但是我們著實遇到了一些麻煩,在此過程中也學到了關于Linux機制和內核開發(fā)相關的東西。以下是一些簡要概述,其中包括了當時采取的三種方案,每次也在尋求更好解決方案。

[[254657]]

 

概述

在現(xiàn)代操作系統(tǒng)中,每個進程都有自己的虛擬地址空間(從虛擬地址映射到物理地址)。此虛擬地址空間由內存頁(某些固定大小的連續(xù)內存塊)組成,每個頁都有保護標志,用于確定允許此頁面訪問的類型(讀取,寫入和執(zhí)行)。這種機制依賴于架構頁表(有趣的是,在x64架構中,你不能使頁面只寫(write-only),就算你特意從操作系統(tǒng)請求,它也總是可讀的)。

在Windows中,你可以使用VirtualProtect或VirtualProtectEx這兩個API更改內存區(qū)域的保護。后者讓我們的任務變得非常簡單:它的***個參數(shù)hProcess是“要改變內存保護的進程的句柄”(參見MSDN.aspx))。

另一方面,在Linux中,我們并不那么幸運:更改內存保護的API是系統(tǒng)調用mprotect或pkey_mprotect,并且兩者始終在當前進程的地址空間上運行。 我們現(xiàn)在回顧一下在x64架構上的Linux中解決此任務的方法(我們假設是root權限)。

而在Linux中,我們就沒那么幸運了,更改內存保護的API是系統(tǒng)調用(mprotect或pkey_mprotect),并且兩者始終在當前進程的地址空間上運行。所以現(xiàn)在我們來回顧一下在Linux x64架構上解決此問題的方法(假設是root權限)。

方案一:代碼注入

如果mprotect總是作用于當前進程,那么我們就需要讓目標進程從它自己的上下文中調用它。這稱為代碼注入,可以通過許多不同的方式實現(xiàn)。我們選擇使用ptrace機制實現(xiàn)它,其允許一個進程“觀察并控制另一個進程的執(zhí)行”(參見手冊),包括更改目標進程的內存的能力。此機制用于調試器(如gdb)和跟蹤程序(如strace)。使用ptrace注入代碼所需的步驟如下:

1. 通過ptrace附加到目標進程。如果進程中有多個線程,那就終止所有其他線程

2. 找到可執(zhí)行內存區(qū)域(通過檢查/proc/PID/maps)并在那里寫操作碼(hex:0f 05)

3.根據(jù)調用約定修改寄存器:首先將rax更改為mprotect的系統(tǒng)調用號(即10)。然后三個參數(shù)(起始地址,長度和所需的保護)分別存儲在rdi,rsi和rdx中。***,將rip更改為步驟2中使用的地址

4. 恢復進程直到系統(tǒng)調用返回(ptrace允許你跟蹤系統(tǒng)調用的進入和退出)

5. 恢復被覆蓋的內存和寄存器,從進程中分離并恢復正常執(zhí)行

這種方法是***個也是最直觀的方法,但是我們之后發(fā)現(xiàn)Linux中的另一種叫seccomp的機制會工作得更好。它是Linux內核中的一個安全工具,允許進程自己進入某種封閉狀態(tài),除了read,write,_exit和sigreturn之外,它不能調用任何系統(tǒng)調用。不過也可以選擇任意系統(tǒng)調用及其參數(shù)來僅僅過濾指定的系統(tǒng)調用。

因此,如果進程啟用了seccomp模式并且我們嘗試將mprotect調用到其中,那么內核將終止進程,因為不允許此系統(tǒng)調用。所以我們要尋求更好的解決方案……

方案二:模仿內核模塊中的mprotect

由于seccomp,用戶態(tài)中每個解決方案都不可行,因此下一個方法肯定存在于內核態(tài)中。在Linux內核中,每個線程(用戶線程和內核線程)都由名為task_struct的結構表示,并且當前線程(任務)可通過指針訪問。內核中mprotect的內部實現(xiàn)使用指針current,所以我們首先想到的是將mprotect的代碼復制粘貼到我們的內核模塊,并用指向目標線程的task_struct的指針替換每次出現(xiàn)的current。

可能你已經(jīng)猜到了,復制C代碼并不是那么簡單,其中有大量我們無法訪問的,未導出的函數(shù),變量和宏。某些函數(shù)聲明在頭文件中導出,但內核不會導出它們的實際地址。如果內核是由kallsyms支持編譯的,那么這個特定的問題就可以解決,然后通過文件/proc/kallsysm導出所有內部符號。

盡管存在這些問題,我們仍以mprotect的本質進行嘗試,甚至僅用于教育目的。因此,我們開始編寫一個內核模塊,它獲取mprotect目標PID和參數(shù),并模仿其行為。首先,我們需要獲取所需的內存映射對象,它表示線程的地址空間:

 

現(xiàn)在我們有了內存映射對象,就需要深入挖掘。Linux內核實現(xiàn)了一個抽象層來管理內存區(qū)域,每個區(qū)域由結構vm_area_struct表示。為了找到正確的內存區(qū)域,我們使用函數(shù)find_vma,它通過所需的地址搜索內存映射。

vm_area_struct包含字段vm_flags,其以與結構無關的方式表示存儲器區(qū)域的保護標志,vm_page_prot以體系結構相關的方式表示。單獨更改這些字段不會真正地影響頁表(但會影響proc/PID/maps的輸出,我們已經(jīng)嘗試過)。 你可以點擊這里獲取更多內容。

在深入研究內核代碼之后,我們發(fā)現(xiàn)了真正改變內存區(qū)域保護所需的最基本工作:

1. 將字段vm_flags更改為所需的保護

2. 調用函數(shù)vma_set_page_prot_func來根據(jù)vm_flags字段更新vm_page_prot

3. 調用函數(shù)change_protection_func更新頁表中的保護位。

這段代碼雖然有效,但它有很多問題,首先,我們只實現(xiàn)了mprotect的基本部分,但原始函數(shù)比我們做的要多得多(例如通過保護標志分割和連接內存區(qū)域)。其次,我們使用兩個內核函數(shù),這些函數(shù)不是由內核導出的(vma_set_page_prot_func和change_protection_func)。我們可以使用kallsyms來調用它們,但是這很容易出問題(將來可能會更改它們的名稱,或者會改變內存區(qū)域的整個內部實現(xiàn))。所以我們想要一個更通用的解決方案,不考慮內部結構。

方案三:使用目標進程的內存映射

這種方法與***種方法非常相似,因為我們希望在目標進程的上下文中執(zhí)行代碼。但在這里,我們會用自己的線程中執(zhí)行代碼,同時使用目標進程的“內存上下文”,這意味著:我們會使用其地址空間。

通過幾個API可以在內核態(tài)下更改地址空間,我們使用了use_mm。如文檔明確指出的那樣,“此例程僅用于從內核線程上下文中調用”。這些是在內核中創(chuàng)建的線程,不需要任何用戶地址空間,因此可以更改其地址空間(地址空間內的內核區(qū)域在每個任務中以相同的方式映射)。

在內核線程中運行代碼有一種簡單方法,就是內核的工作隊列接口,它允許你使用特定例程和特定參數(shù)來安排工作。我們的例程獲取所需進程的內存映射對象和mprotect的參數(shù),并執(zhí)行以下操作(do_mprotect_pkey是內核中實現(xiàn)mprotect和pkey_mprotect系統(tǒng)調用的內部函數(shù)):

 

當我們的內核模塊在某個進程(通過一個特殊的IOCTL)獲得更改保護的請求時,它首先找到所需的內存映射對象,然后使用正確的參數(shù)來調度工作。這個方案仍有一個小問題:函數(shù)do_mprotect_pkey_func不由內核導出,需要使用kallsyms獲取。與前一個解決方案不同,這個內部函數(shù)不太容易發(fā)生變化,因為它與系統(tǒng)調用pkey_mprotect有關,而且我們無需處理內部結構。

如果你有興趣,可以在github中找到這個PoC內核模塊的源代碼。

責任編輯:武曉燕 來源: FreeBuf
相關推薦

2018-12-03 11:05:20

內存代碼Linux

2019-12-16 10:43:38

Linux內存消耗進程

2019-11-06 15:58:54

Linux內存消耗進程

2018-07-27 05:08:58

2021-08-30 06:59:07

x86處理器內存

2023-03-05 16:40:07

linux進程內存

2023-01-30 14:27:14

Linux進程

2018-05-31 11:58:06

Linux進程Early OOM

2010-08-05 16:08:12

輕松掌握DB2 9.5

2015-10-22 13:07:29

USB設備權限Linux

2023-01-27 09:17:02

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

2018-06-05 08:51:04

Linux結束進程中止程序

2019-12-16 09:10:38

Linux中央處理器進程

2019-12-16 11:00:04

LinuxCPU進程

2022-05-27 11:59:22

Linux內存CPU

2021-07-16 08:00:00

開發(fā)VSCode編輯器

2013-06-20 10:25:56

2018-10-08 08:20:25

Linux進程端口號

2009-12-09 10:07:19

Linux靜態(tài)路由

2011-01-26 13:26:32

Linux進程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲欧美中文字幕在线观看 | 精品福利一区二区三区 | 国产精品一区二区三区久久 | 国产伦精品一区二区三区四区视频 | 中文字幕乱码亚洲精品一区 | 成人免费在线观看 | 久久精品国产v日韩v亚洲 | 91网在线观看 | 超碰综合 | 亚洲视频一 | 久久久久久久一区二区三区 | 精品1区 | 成人黄色a| 日韩中文在线视频 | 亚洲欧美在线观看 | 日韩日韩日韩日韩日韩日韩日韩 | 欧美一区在线看 | 91久久精品一区二区二区 | 亚洲精品影院 | 蜜桃av鲁一鲁一鲁一鲁 | 国产一区二区精品在线观看 | 久草.com | 国产精品成人一区二区 | 伊人网伊人| 午夜精品一区二区三区在线播放 | 久久中文字幕一区 | 国产精品成人一区二区 | 成人在线一区二区三区 | 精品国产91乱码一区二区三区 | 中文字幕在线观看一区二区 | 在线高清免费观看视频 | 国产成人免费视频网站高清观看视频 | 99久久婷婷国产综合精品电影 | 午夜影院在线观看 | 久国久产久精永久网页 | 国产在线视频一区二区董小宛性色 | 欧美精品一区二区在线观看 | 国产精品久久影院 | 亚洲免费视频一区 | 久久久噜噜噜www成人网 | 伊人激情网 |