Posts

Showing posts with the label Heap

Windows內核安全之 線程調度

Image
線程一個比較重要的概念是, CPU中永遠調度的是線程, 而不是進程, 而進程的切換完全是源於是否同一個CR3寄存器, 詳見SwapContext的實現 以下先列出KTHREAD對象 內核中對線程優先級(priority) 分別使用0~31表示 實時(Real-time)類別: 16~31 動態(Dynamic)類別: 1~15 系統(System)類別: 0 線程在內核的執行體層(Executable Layer)中 使用以下6種優先級 實時(Realtime) 高(High) 普通之上(Above normal) 普通(normal) 普通之下(Below normal) 低(Low) 執行體層透過一個數組PspPriorityTable 轉換成真正的表示 以下是他們的對應關係 實時(Realtime) 24 高(High) 13 普通之上(Above normal) 10 普通(normal) 8 普通之下(Below normal) 6 低(Low) 4 進程的對象EPROCESS結構中 BasePriority 指定一個進程中所有線程的預設優先級 可以通過KeSetPriorityAndQuantumProcess 或 KeSetBasePriorityThread 函數設置優先級 KTHREAD中的Priority域記錄一個線程當前實際優先級, 他一般是在BasePriority基礎上提升到某個增量 Priority不會超過0~15 內核通過調用KiComputeNewPriority計算並調整非實時的線程優先級 我們可以使用NtSetInformationProcess為進程的基礎優先級進行微調, 所以一條線程在執行體中的值並非數組中指定的值 優先級的提升: ------------- 由於每個線程優先級都有對應的鏈表維護著相同優先級的線程 方便調度 所以優先級的提升, 一定是在加入鏈表之前 內核中不小函數的參數使用KPRIORITY Increment進行提升 如: KeInsertQueueApc KePulseEv...

Windows安全之 應用層(Ring3)的)內存管理(四) 堆(Heap)

Image
4. Windows 最小單位的內存管理 - 堆 進程的默認堆是1MB, 透過修改鏈接器的/HEAP 屬性可以自定義大小 相比之前兩章, 堆是用來管理鏈表和樹的最好內存結構, 堆的優點就是可以不顧分配粒度, 和頁面邊界的事情, 但缺點就是分配及釋放比較慢一點, 而且也沒法再對物理存備器調撥進行直接控制。 4.1 創建額外的堆  HANDLE WINAPI HeapCreate( _In_ DWORD  flOptions, _In_ SIZE_T dwInitialSize, _In_ SIZE_T dwMaximumSize  ); 使用創建 HeapCreate 額外的堆 使用額外的堆 可使線程開銷減低, 而且把儲存對象分類, 不然如果把鏈表及二叉樹的對象放在同一個堆中, 會發現鏈表的節點有可能會令二叉樹的節點被破壞,  如下圖 創建額外的堆的原因 假設NODE1 有代碼會覆蓋它的下8個字節的地方, 這樣就會使NODE1及BRAJNCH2,3 被破壞 所以我們是需要創建額外的堆來保護我們的組件, 不應把所有類別都在放同一個堆中 使用堆, 能夠快速釋放, 例如我們將一個二叉樹的所有節點 進行釋放, 需要遍歷所有節點進行釋放, 但現在 我們使用堆存放著所有節點, 我們只需要把這個堆釋放, 例如Windows的資源管理器使用二叉樹來遍歷系統所有進程, 那如果刷新一次, 他就需要重新遍歷一次系統 看進程是否已經存在, 但使用堆就可以直接清除, 最後重新遍歷, 不用再比對什麼 4.2 從堆中分配內存塊 使用以下函數 LPVOID WINAPI HeapAlloc( _In_ HANDLE hHeap, //指定哪一塊堆中建立內存塊 _In_ DWORD  dwFlags, _In_ SIZE_T dwBytes ); 使用創建HeapAlloc在堆中分配一塊內存,  如果成功返回內存塊地址, 若較大的內存分配應直接使用VirtualAlloc , 而不使用堆函數 LPVOID WINAPI HeapReAlloc( _In_ HANDLE hHeap, ...