青草久久影院-青草久久伊人-青草久久久-青草久久精品亚洲综合专区-SM双性精跪趴灌憋尿调教H-SM脚奴调教丨踩踏贱奴

17站長網

17站長網 首頁 安全 安全教程 查看內容

Rootkit技術之內核鉤子原理

2022-9-24 10:15| 查看: 2368 |來源: 互聯網

我們知道,應用程序總是離不開系統內核所提供的服務,比如它要使用內存的時候,只要跟操作系統申請就行了,而不用自己操心哪里有空閑的內存空間等問題,實際上, ...

我們知道,應用程序總是離不開系統內核所提供的服務,比如它要使用內存的時候,只要跟操作系統申請就行了,而不用自己操心哪里有空閑的內存空間等問題,實際上,這些問題是由操作系統的內核來代勞的。站在黑客的角度講,如果能夠控制內核,實際上就是控制了內核之上的各種應用程序。本文將向您介紹如何建立內核級鉤子來控制操作系統向上提供的各種低級功能。有了內核級鉤子,我們不但能夠控制、監視其他程序并過濾有關數據,還能用其實現Rootkit本身及其它程序的隱形。
本文首先回顧系統調用表和內存保護方面的知識,然后講解如何實現內核鉤子,最后對一些重要的內核函數進行了簡要的說明。

一、系統調用表

系統調用表又稱系統服務表或者服務描述符表,是Windows 內核在進行各種系統操作時所需的一個函數指針表。也就是說,這個表中存放的是提供系統服務的各種函數的地址。當然,該表所指向的都是系統自身的一些函數,但是,如果我們對它做了手腳后,就可以讓它指向我們自己的函數。這正是本文要講解的重點。
讀者一定要注意,修改系統調用表及替換內核函數時,會對系統全局產生影響,稍有不慎就會導致系統崩潰。所以,下手之前,最好對表中的各個函數要有足夠的認識,然后才好用我們自己的函數替換這些內核函數的方法。你對它們了解得越多越深,在實現內核鉤子的時候就越順手。但話又說回來,這個系統調用表中的表項實在是太多了,有的指向字符串操作,有的指向客戶機/服務器操作,等等。所以要在短時間內了解所有表項是不可能的,所以下文中對它們只做有選擇的、概括的介紹。

二、內存保護

現代的Windows操作系統通常將系統調用表所在內存頁設為只讀來提供保護。如果不能克服這個問題,實施內核鉤子技術就是癡人說夢。因為試圖向只讀內存寫入數據也即修改只讀內存區時,立刻就會藍屏。為此,先讓我們來了解一下內存保護方面的有關知識。
內存描述符表是內存保護的一大關鍵,具體定義詳見微軟DDK中的ntddk.h頭文件,我們這里僅做簡要介紹:
typedef struct _MDL {
struct _MDL *Next;
CSHORT Size;
CSHORT MdlFlags;
struct _EPROCESS *Process;
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;
#define MDL_MAPPED_TO_SYSTEM_VA 0x0001
#define MDL_PAGES_LOCKED 0x0002
#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004
#define MDL_ALLOCATED_FIXED_SIZE 0x0008
#define MDL_PARTIAL 0x0010
#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020
#define MDL_IO_PAGE_READ 0x0040
#define MDL_WRITE_OPERATION 0x0080
#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100
#define MDL_FREE_EXTRA_PTES 0x0200
#define MDL_IO_SPACE 0x0800
#define MDL_NETWORK_HEADER 0x1000
#define MDL_MAPPING_CAN_FAIL 0x2000
#define MDL_ALLOCATED_MUST_SUCCEED 0x4000
#define MDL_MAPPING_FLAGS (MDL_MAPPED_TO_SYSTEM_VA | \
MDL_PAGES_LOCKED | \
MDL_SOURCE_IS_NONPAGED_POOL | \
MDL_PARTIAL_HAS_BEEN_MAPPED | \
MDL_PARENT_MAPPED_SYSTEM_VA | \
MDL_SYSTEM_VA | \
MDL_IO_SPACE )


內存描述符表(MDL)的作用是將虛擬內存映射成物理頁。如果將系統調用表所在內存頁的MDL的MDLFlags成員設為MDL_MAPPED_TO_SYSTEM_VA 并且該頁面被鎖定的話,那么就可以使用內核鉤子技術了。以下代碼將可以達此目的:
#pragma pack(1)
typedef struct ServiceDescriptorEntry
{
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase;
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
PVOID* NewSystemCallTable;
PMDL pMyMDL = MmCreateMdl( NULL,
KeServiceDescriptorTable.ServiceTableBase,
KeServiceDescriptorTable.NumberOfServices * 4 );
MmBuildMdlForNonPagedPool( pMyMDL );
pMyMDL->MdlFlags = pMyMDL->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
NewSystemCallTable = MmMapLockedPages( pMyMDL, KernelMode );
好了,我們現在可以通過NewSystemCallTable來新建系統調用表了。系統調用表如下圖所示。


圖1  系統調用表示意圖

進行掛鉤時,可以使用以下宏:
#define HOOK_INDEX(function2hook) *(PULONG)((PUCHAR)function2hook 1)
#define HOOK(functionName, newPointer2Function, oldPointer2Function )  \
oldPointer2Function = (PVOID) InterlockedExchange( (PLONG)
&NewSystemCallTable[HOOK_INDEX(functionName)], (LONG) newPointer2Function)
#define UNHOOK(functionName, oldPointer2Function)  \
InterlockedExchange( (PLONG) &NewSystemCallTable[HOOK_INDEX(functionName)]
, (LONG)
oldPointer2Function)

使這些宏后,鉤子技術會變得更簡單,也更安全。因為InterlockedExchange 是原子函數,不會要求中止中斷,所以交換指針的方式是安全的;另外,它也不需要用一個宏掛鉤之后用另一個宏卸載鉤子,所以也更方便。下圖向我們展示了攔截系統調用表的過程。


圖2  系統調用表攔截技術示意圖

系統調用表數據結構KeServiceDescriptorTable不僅含有ntdll.dll 的全部函數指針,還存有系統調用表的基地址和表的大小,當建立我們自己的內存描述符表的時候,這些信息是不可或缺的。利用MDL_MAPPED_TO_SYSTEM_VA 標志,我們可以建立一個不可頁出(即不會被換到內存之外)的MDL ,這樣我們就可以將其鎖定,并把返回的地址用于我們自己的系統調用表,重要的是,這個系統調用表是可寫的。

三、定義鉤子函數

內核鉤子主要有三部分組成:要鉤取的函數(在下文中稱為目標函數)、替代要鉤取的函數的函數(在下文中成為鉤子函數)和系統調用表。前面部分介紹了系統調用表的問題,下面開始介紹鉤子函數。一般說來,當定義自己的鉤子函數時,可以先到DDK 的頭文件中找到所想要的函數的原型,然后,稍加修改就能把目標函數變成鉤子函數了。

例如,ZwMapViewOfSection 是一個內核函數,允許應用程序把從動態鏈接庫導出的函數映射至內存。如果我們想要鉤住這個內核函數,那么可以到ntddk.h頭文件中查看其函數原型,如下所示:

NTSYSAPI
NTSTATUS
NTAPI
ZwMapViewOfSection(
IN HANDLE SectionHandle,
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN ULONG CommitSize,
IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
IN OUT PSIZE_T ViewSize,
IN SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType,
IN ULONG Protect );

有了函數原型,我們就可以確定指向目標函數的指針了,如下所示:

typedef NTSTATUS (*ZWMAPVIEWOFSECTION)(
IN HANDLE SectionHandle,
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN ULONG CommitSize,
IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
IN OUT PSIZE_T ViewSize,
IN SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType,
IN ULONG Protect );
ZWMAPVIEWOFSECTION OldZwMapViewOfSection;

鉤子函數如下所示:

NTSTATUS NewZwMapViewOfSection(
IN HANDLE SectionHandle,
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN ULONG CommitSize,
IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
IN OUT PSIZE_T ViewSize,
IN SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType,
IN ULONG Protect )
{
NTSTATUS status;
DbgPrint("comint32: NewZwMapViewOfSection called.");
//我們可以對輸入為所欲為,既可以馬上返回,也可以繼續執行原函數
status = OldZwMapViewOfSection(SectionHandle,
 ProcessHandle,
 BaseAddress,
 ZeroBits,
 CommitSize,
 SectionOffset OPTIONAL,
 ViewSize,
 InheritDisposition,
 AllocationType,
 Protect );
// 我們可以在此對輸出為所欲為,想返回什么,就返回什么
return status;
}

好了,鉤子技術的三大件已經準備好了。現在,我們就可以像下面這樣使用它們:
HOOK( ZwMapViewOfSection, NewZwMapViewOfSection, OldZwMapViewOfSection );

如果你打算使用DriverUnload ()的話,可千萬不要忘了卸載鉤子。

四、內核函數系列

經過上面的介紹,我們已經了解了系統調用表有關知識,也已知道如何攔截系統調用表中的函數,下面,我們再來了解一下我們要鉤取的函數:目標函數。這方面,如果我們不僅了解系統調用表中有哪些函數,還知道這些函數的工作機制就最好了。但實際上,ntdll.dll 中的導出函數有好幾百個,別說一個一個的探究,就是把它們都列出來,看著看著頭都大了。幸運的是,我們不必了解每個函數,只要了解其所在的系列就行了。為什么這么說?因為微軟已經按照函數的功能對Ntdll.dll的導出函數進行了分組,并冠以意義明確的前綴,所以根據函數系列的前綴就能明白它們的大體功能了。下面對這些函數系列進行簡單的介紹:

1.KiEtw系列:本系列內核函數用于系統內核,這些函數只能從內核的內部進行調用,常用的有:KiUserCallbackDispatcher、KiRaiseUserExceptionDispatcher、KiUserApcDispatcher、KiUserExceptionDispatcher等。

2.Csr系列:此系列函數用于客戶機和服務器運行時,如果您想攔截客戶機/服務器方面的操作,那么就需要對Csr系列內核函數做進一步的了解。常見的有:CsrClientCallServer、CsrCaptureMessageBuffer、CsrConnectClientToServer和CrsNewThread等。

3.Ldr系列:本系列內核函數用于加載程序管理器,如果你打算攔截加載程序的話,那么請進一步考察這組以Ldr為前綴的函數,常用的有:LdrInitializeThunk、LdrLockLoaderLock、LdrUnlockLoaderLock、LdrGetDllHandle、LdrGetProcedureAddress等。

4.Dbg系列:本系列內核函數用于調試管理,如果打算攔截調試操作的話,那么請進一步考察這組以Dbg為前綴的函數,常用的函數包括:、DbgBreakPoint、DbgUserBreakPoint、DbgPrint和DbgUiConnectToDbg等。

5.Etw系列:本系列內核函數用于追蹤窗口事件,如果你打算攔截追蹤之類的操作的話,那么請進一步考察這組以Etw為前綴的函數。常用的函數包括:EtwTraceEvent、EtwEnableTrace、EtwGetTraceEnableLevel和EtwGetTraceEnableFlags等。

6.Rtl系列:本系列內核函數用于運行時庫,以Rtl為前綴的函數可以完成多種操作,例如字符串、線程、資源、臨界區、安全對象的初始化和使用,內存、進程異常和數據類型的處理,還用于完成定時器、堆、IPv4和IPv6方面的操作,以及壓縮和解壓縮等。

7.Pfx系列:本系列內核函數用于ANSI字符串操作,如果你打算攔截ASNI串表方面的操作的話,就需要進一步了解這些函數。常用的包括:PfxInitialize、PfxRemovePrefix、PfxInsertPrefix、PfxFindPrefix等。

8.Zw系列:本系列內核函數用于文件和注冊表方面的操作,比如文件操作、注冊表操作、訪問進程、事件操作、令牌操作、進程操作和端口操作等。

這里介紹的只是內核函數中的一部分,限于篇幅其他部分在此不作介紹。

六、結束語

本文深入介紹了系統調用表和內存保護方面的知識,并介紹了實現鉤子函數的方法,最后對一些重要的內核函數進行了簡要的說明。有了內核級鉤子,我們不但能夠控制、監視其他程序并過濾有關數據,還能達到隱藏Rootkit本身及其它程序的目的。需要說明的是,盡管可以通過內核鉤子技術來實現rootkit所需的一些功能,但是,現實中的rootkit通常組合使用多種其它技術,如進程注射、分層驅動過濾等。

本文最后更新于 2022-9-24 10:15,某些文章具有時效性,若有錯誤或已失效,請在網站留言或聯系站長:[email protected]
·END·
站長網微信號:w17tui,關注站長、創業、關注互聯網人 - 互聯網創業者營銷服務中心

免責聲明:本站部分文章和圖片均來自用戶投稿和網絡收集,旨在傳播知識,文章和圖片版權歸原作者及原出處所有,僅供學習與參考,請勿用于商業用途,如果損害了您的權利,請聯系我們及時修正或刪除。謝謝!

17站長網微信二維碼

始終以前瞻性的眼光聚焦站長、創業、互聯網等領域,為您提供最新最全的互聯網資訊,幫助站長轉型升級,為互聯網創業者提供更加優質的創業信息和品牌營銷服務,與站長一起進步!讓互聯網創業者不再孤獨!

掃一掃,關注站長網微信

大家都在看

    熱門排行

      最近更新

        返回頂部
        主站蜘蛛池模板: 青草国产在线视频免费 | 55夜色66夜亚洲精品播放 | vivoe另类| 亚洲AV成人无码网天堂 | 日韩欧美中文字幕在线 | 免费一级特黄欧美大片久久网 | 伊人久99久女女视频精品免 | 色一欲一性一乱一区二区三区 | 嫩草影院未满十八岁禁止入内 | 高H黄暴NP辣H一女多男 | 在线播放一区二区精品产 | 久久精品黄AA片一区二区三区 | 97人妻碰视频在线观看 | 欧美男女爱爱 | 国产精品久久久久久影院 | 久久99影院| 白丝女仆被强扒内裤 | 朝鲜女人性猛交 | 亚洲精品在线不卡 | 孕妇bbwbbwbbwbbw超清 | 日欧一片内射VA在线影院 | 双性将军粗壮H灌满怀孕 | 老师湿乎乎两半嫩 | 久拍国产在线观看 | jyzzjyzzz视频国产在线观看 | 色欲AV人妻精品麻豆AV | 99久久国产宗和精品1上映 | 色拍拍噜噜噜久久蜜桃 | 护士WC女子撒尿 | 在线观看免费av网 | 日本特黄网站 | 超h高h肉h文教室生理课 | 一个人免费完整在线观看影院 | 青青视频国产色偷偷 | 91嫩草国产在线观看免费 | 无套内射CHINESEHD熟女 | 很黄很色60分钟在线观看 | 年轻的母亲4线在线观看完整 | 日韩插啊免费视频在线观看 | 亚洲AV国产精品无码精 | 快播电影网站大全 |