进程挂靠 详解
文章目錄
- 1.進程與線程的關系:
- 2.線程與進程如何關聯
- 3.養父母負責提供Cr3
- 4.Cr3的值可以隨便改嗎?
- 5.NtReadVirtualMemory函數
- 6.總結:
1.進程與線程的關系:
一個進程可以包含多個線程
一個進程至少要有一個線程
進程為線程提供資源,也就是提供Cr3的值,Cr3中存儲的是頁目錄表基址,Cr3確定了,線程能訪問的內存也就確定了
線程代碼:
mov eax,dword ptr ds:[0x12345678]
CPU會如何解析這個0x12345678這個地址呢?
1.CPU解析線性地址時通過頁目錄表來找對應的物理頁,頁目錄表基址存在Cr3寄存器中
2.當前的Cr3的值來源于當前的進程(_KPROCESS.Directory TableBase(+0x018))
2.線程與進程如何關聯
_ETHREAD結構體:
+0x034 ApcState
+0x000 ApcListHead
+0x010 Process
+0x014 KernelApcInProgress
+0x015 KernelApcPending
+0x016 UserApcPending
+0x220 ThreadsProcess
3.養父母負責提供Cr3
線程切換的時候,會比較_KTHREAD結構體0x044處指定的EPROCESS是否為同一個,如果不是同一個,會將0x044處指定的EPROCESS的DirectoryTableBase的值取出,賦值給Cr3
所以,線程需要的Cr3的值來源于0x044處偏移指定的EPROCESS
進行線程切換時,會比較兩個線程所屬進程(這里比較的是0x44h)是否一樣,不一樣的話又要進行Cr3的切換(也就是進行進程的切換)
此時近一步來看看,把eax放入Cr3中,那么eax如何得到的?
得到頁目錄表的基址,那么edi值從何處而來,近一步探索:
從KTHEAD+0x44位置處取出
總結:
0x220親生父母:這個線程誰創建的
0x044 養父母:誰在為這個線程提供資源(也就是提供Cr3)
一般情況下,0x220與0x044指向的是同一個進程
4.Cr3的值可以隨便改嗎?
正常情況下,Cr3的值是由養父母提供的,但Cr3的值也可以改成和當前線程毫不相干的僅存的DirectoryTableBase
線程代碼:
mov Cr3,A.DirectoryTableBase
mov eax,dword ptr ds:[0x12345678]//A進程的0x12345678內存
mov Cr3,B.DirectoryTableBase
mov eax,dword ptr ds:[0x12345678]//B進程的0x12345678內存
mov Cr3,C.DirectoryTableBase
mov eax,dword ptr ds:[0x12345678]//C進程的0x12345678內存
將當前Cr3的值改為其它進程,稱為:“進程掛靠”
進程掛靠目的是:當前線程能夠訪問其它進程的內存空間
5.NtReadVirtualMemory函數
進入了兩層call后,
開始讀取進程的內存
讀取進程內存之前做了一些處理:
上圖call這個函數開啟了進程掛靠操作:
真正掛靠的過程就在下圖call內部:
1.只需要關注如下一行(修改Cr3值):
2.再修改Cr3之前還做了一步操作
ebx也就是我們所需要讀取的那個進程,存放在了esi+44h處。
NtReadVirtualMemory ----> KiAttachProcess —>修改養父母---->修改Cr3
可不可以只修改Cr3而不修改養父母?不可以,如果不修改養父母的值,一旦產生線程切換,就變成自己讀自己
進行線程切換時,切換的線程時所給值是“edi+0x44h”(即養父母)內存單元處的值,
如果我們自己來寫這個代碼,在切換Cr3后關閉中斷,并且不調用會導致線程切換的API,就可以不用修改養父母的值
6.總結:
正常情況下,當前線程使用的Cr3是由其所屬進程提供的(ETHREAD 0x44偏移處指定的EPROCESS),正是因為如此,A進程中的線程才能訪問A的內存
如果要讓A進程中的線程能訪問B進程的內存,就必須修改Cr3 的值為B進程的頁目錄表基址(B.DirectoryTableBase),這就是所謂的“進程掛靠”
總結
- 上一篇: 等待链表_调度(准备运行)链表
- 下一篇: 私有句柄表(内核对象,并非用户对象),全