• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉,開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理
            掃盲貼,HOOK SSDT 短文一篇(通過MDL修改內存保護機制)
            2009-09-05 23:25

            http://hi.baidu.com/csh0w/blog/item/f44412e8cbf12936b90e2d2b.html

            標 題: 【原創】掃盲貼,HOOK SSDT 短文一篇。
            作 者: 梧桐
            時 間: 2008-12-06,23:01
            鏈 接: http://bbs.pediy.com/showthread.php?t=78218

            //author:梧桐
            //轉載請注明出處

            ------------------------很不華麗的分割線------------------------------------------------------

            本文章僅供那些在驅動開發門外徘徊的程序愛好者參考和學習,大牛就繞過吧,
            如有錯誤的地方,還請多多指出,不勝感激。

            ------------------------很不華麗的分割線------------------------------------------------------

            ?????? 對于Driver 一詞兒,我想大家都不陌生,它是工作在ring0下的,正是因為如此,它不不能夠快速上手的,更多的時候你要熟悉它的技術資料和接口,還要熟悉底層工作的原理,一不小心搞個BSOD,那是會非常郁悶的。

            ???? 好了,現在讓我們步入正題,首先確認你已經安裝好了DDK(學習驅動開發,推薦WINXP DDK 2600、 Windows XP,?? VS2003),配置好了你的開發環境(DDK Wizard),在VS20003里添加WINDDK路徑。

            ???? 打開VS2003,Tools選項,選取 Options(如下圖):

            然后,我們找到 Projects(工程),選取VC++ Directories,添加WINDDK路徑:

            配置好這些環境以后,我們開始與驅動的親密接觸吧。

            ???? 先來建立一個驅動的工程:

            那些默認的選項,全部取消掉:

            接著點 Finish ,刪除 Header Files、Resource Files,此時,DDK Wizard 已經為我們建立了一套Driver模板了,但細看,是不是感覺非常非常的亂?

            ???? OK,我們把它K掉,現在我們自己來打造一個簡單的入口點。

            ????

            代碼:
            #include "ntddk.h"
            
            //Unload
            VOID UnLoad(IN PDRIVER_OBJECT DriverObject)
            {
            ???  DbgPrint("UnLoad Driver.\n");
            }
            
            //EntryPoint.
            NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, 
            ???????????  IN PUNICODE_STRING RegistryPath)
            {
            ??  DriverObject->DriverUnload = UnLoad;
            ??  //TODO
            ??  return STATUS_SUCCESS;
            }
            ???? 在 DriverName.WXP上點Build,看看objchk\i386目錄下產生的Sys文件,OK,Cool吧,當然,我們這個驅動連任何功能都沒有的,Cool是很Cool,就是Cool得沒內涵了,那么我們來實現點什么功能呢,好吧,讓我們來對SSDT掛鉤一下吧。

            ???? 要掛鉤SSDT,就必須先要由內核到處一個KeServiceDescriptorTable,那么我們還要先定義一個KeServiceDescriptorTable類型的的結構體:

            代碼:
            typedef struct ServiceDescriptorEntry
            {
            ????????  unsigned int *ServiceTableBase;
            ????????  unsigned int *ServiceCounterTableBase; //Used only in checked build
            ????????  unsigned int NumberOfServices;
            ????????  unsigned char *ParamTableBase;
            } SSDTEntry;
            ???? 定義了KSDT的結構,那么我們想想要HOOK那個函數呢,好吧,就以ZwTerminateProcess為例,我們開動,首先定義一個ZwTerminateProcess函數結構,函數原型:

            代碼:
            ZwTerminateProcess(
            ????????  IN HANDLE ProcessHandle OPTIONAL, 
            ????????  IN NTSTATUS ExitStatus
            ????????  );
            結構定義:

            代碼:
            typedef NTSTATUS(*_ZwTerminateProcess)(
            ????????????????  IN HANDLE ProcessHandle OPTIONAL,
            ????????????????  IN NTSTATUS ExitStatus
            ????????????????  );
            ???? 我們要HOOK ZwTerminateProcess,那么我們是不是要先找出它在KSDT中的位置呢,沒錯,那么我們來定義一個通過SSDT服務號得到函數地址的宏以達到我們的目的:

            代碼:
            #define??  GetSystemFunc(FuncName) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)FuncName+1)];
            ???? 想要達到改寫SSDT的目的,那么首先要解決的是內存保護機制的問題,眾所周知,Windows的某些版本對內存區域啟用了寫保護的功能,在XP和2003中更為常見,SSDT是只讀的,那怎么辦呢?

            ???? 有的網友此刻估計已經明白了。

            ???? 沒錯,就是 Memory Descriptor List,簡稱 MDL。有的同學可能會問了,MDL究竟是個什么東西呢?從字面意思看,不難理解,內存描述符列表。MDL包含了內存區域的起始、擁有者proc、字節數、標記等。OK,我們需要先定義一個MDL的指針。

            代碼:
            PMDL MDLSystemCall;

            ???? 定義了MDL的指針以后,我們要通過MAPPED系列的參數來使內存擁有可寫性,然后鎖定內存中的MDL,那么我們就要定義一個PVOID的指針,來供MmMap操作。

            ????
            代碼:
            PVOID *MappedSCT;
            ???? 代碼片段:
            代碼:
            MDLSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
            if(!MDLSystemCall)
            ??  return STATUS_UNSUCCESSFUL;
            ???? 那么,建立了MDL,是不是該填充一下頁數組啊?

            ???? 對的,沒錯。

            ????
            代碼:
            MmBuildMdlForNonPagedPool(MDLSystemCall);
            MDLSystemCall->MdlFlags = MDLSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; //可寫
            MappedSCT = MmMapLockedPages(MDLSystemCall, KernelMode);
            ???? 我們轉入HOOK話題,繼續。

            ???? 剛才我們已經定義了 ZwTerminateProcess 的結構。

            ????
            代碼:
            Old_ZwTerminateProcess = (_ZwTerminateProcess)(GetSystemFunc(ZwTerminateProcess));
            ???? 獲取沒被HOOK之前的ZwTerminateProcess在KSDT中的索引,保存。

            ???? 那么下一步呢,就是干掉他了,替換為我們的函數,那么我們是不是要構造一個自己的函數過程呢,恩,沒錯。

            ????
            代碼:
            NTSTATUS NewZwTerminateProcess(
            ????????????????  IN HANDLE ProcessHandle OPTIONAL, 
            ????????????????  IN NTSTATUS ExitStatus
            ????????????????  )
            {
            ??  //TODO
            ??  return STATUS_SUCCESS;
            }
            ???? 在過程里要怎么玩,全看你自己了。

            ???? 下面就是替換函數了,修改SSDT中函數地址指向的位置,下面是宏定義:

            代碼:
            #define GetIndex(_foo) *(PULONG)((PUCHAR)_foo+1)
            #define HookOn(_Old,_New) InterlockedExchange((PLONG)&MappedSCT[GetIndex(_Old)] ,(LONG)_New)
            ????
            代碼:
            MDLSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
            if(!MDLSystemCall)
            ??  return STATUS_UNSUCCESSFUL;
            MmBuildMdlForNonPagedPool(MDLSystemCall);
            MDLSystemCall->MdlFlags = MDLSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; //可寫
            MappedSCT = MmMapLockedPages(MDLSystemCall, KernelMode);
            HookOn(ZwTerminateProcess, NewZwTerminateProcess);
            return STATUS_SUCCESS;
            完整代碼:

            代碼:
            ///////////////////////////////////////////////////////////////////////////////
            ///
            /// Copyright (c) 2008 - <company name here>
            ///
            /// Original filename: NtHook.c
            /// Project??????????  : NtHook
            /// Date of creation : 2008-11-20
            /// Author(s)????????  : 梧桐
            ///
            /// Purpose??????????  : <description>
            ///
            /// Revisions:
            ///??  0000 [2008-11-20] Initial revision.
            ///
            ///////////////////////////////////////////////////////////////////////////////
            #include "ntddk.h"
            
            #pragma pack(1)
            typedef struct ServiceDescriptorEntry
            {
            ????????  unsigned int *ServiceTableBase;
            ????????  unsigned int *ServiceCounterTableBase; //Used only in checked build
            ????????  unsigned int NumberOfServices;
            ????????  unsigned char *ParamTableBase;
            } SSDTEntry;
            __declspec(dllimport)??  SSDTEntry KeServiceDescriptorTable;
            
            #pragma pack()
            
            NTKERNELAPI NTSTATUS ZwTerminateProcess(
            ????????????????  IN HANDLE ProcessHandle OPTIONAL, 
            ????????????????  IN NTSTATUS ExitStatus
            ????????????????  ); 
            
            typedef NTSTATUS(*_ZwTerminateProcess)(
            ????????????????  IN HANDLE ProcessHandle OPTIONAL,
            ????????????????  IN NTSTATUS ExitStatus
            ????????????????  );
            _ZwTerminateProcess Old_ZwTerminateProcess;
            
            #define GetSystemFunc(FuncName) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)FuncName+1)]
            PMDL??  MDSystemCall;
            PVOID *MappedSCT;
            
            #define GetIndex(_Function) *(PULONG)((PUCHAR)_Function+1)
            
            #define HookOn(_Old, _New)??  \
            ???????  (PVOID) InterlockedExchange( (PLONG) &MappedSCT[GetIndex(_Old)], (LONG) _New)
            
            #define UnHook(_Old, _New)??  \
            ???????  InterlockedExchange( (PLONG) &MappedSCT[GetIndex(_Old)], (LONG) _New)
            
            NTSTATUS NewZwTerminateProcess(
            ????????????????  IN HANDLE ProcessHandle OPTIONAL, 
            ????????????????  IN NTSTATUS ExitStatus
            ????????????????  )
            {
            ??  return STATUS_SUCCESS;
            }
            
            //Unload
            VOID UnLoad(IN PDRIVER_OBJECT DriverObject)
            {
            ???  DbgPrint("UnLoad Driver.\n");
            ???  //卸載Hook
            ???  UnHook( ZwTerminateProcess, Old_ZwTerminateProcess);
            
            ???  //解鎖、釋放MDL
            ???  if(MDSystemCall)
            ???  {
            ??????  MmUnmapLockedPages(MappedSCT, MDSystemCall);
            ??????  IoFreeMdl(MDSystemCall);
            ???  }
            }
            
            //EntryPoint.
            NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, 
            ???????????  IN PUNICODE_STRING RegistryPath)
            {
            ??  DriverObject->DriverUnload = UnLoad;
            ??  
            ??  //找出舊函數地址并保存
            ??  Old_ZwTerminateProcess =(_ZwTerminateProcess)(GetSystemFunc(ZwTerminateProcess));
            
            ??  MDSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
            ??  if(!MDSystemCall)
            ????  return STATUS_UNSUCCESSFUL;
            ??  MmBuildMdlForNonPagedPool(MDSystemCall);
            ??  MDSystemCall->MdlFlags = MDSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
            ??  MappedSCT = MmMapLockedPages(MDSystemCall, KernelMode);
            
            ??  //安裝HOOK
            ??  HookOn( ZwTerminateProcess, NewZwTerminateProcess);
            ??  return STATUS_SUCCESS;
            }

            工程附件:http://xlick.3video.cn/1.zip

            一段類似的代碼

            #include "ntddk.h"


            ULONG pid=1548;

            #pragma pack(1) //SSDT表的結構
            typedef struct ServiceDescriptorEntry {
            unsigned int *ServiceTableBase;
            unsigned int *ServiceCounterTableBase; //Used only in checked build
            unsigned int NumberOfServices;
            unsigned char *ParamTableBase;
            } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
            #pragma pack()


            __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; //變量名是不能變的,因為是從外部導入

            //取函數在SSDT中的位置
            #define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]
            //取函數的索引
            #define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
            //修改函數的地址
            #define HOOK_SYSCALL(_Function, _Hook, _Orig ) _Orig = (PVOID) InterlockedExchange( (PLONG) &m_Mapped[SYSCALL_INDEX(_Function)], (LONG) _Hook)
            PMDL m_MDL;
            PVOID *m_Mapped;


            NTSYSAPI NTSTATUS NTAPI ZwOpenProcess(OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId OPTIONAL);
            NTSYSAPI NTSTATUS NTAPI ZwTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,IN NTSTATUS ExitStatus);

            typedef NTSTATUS (*ZWOPENPROCESS)(OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId OPTIONAL);
            typedef NTSTATUS (*ZWTERMINATEPROCESS)(IN HANDLE ProcessHandle OPTIONAL,IN NTSTATUS ExitStatus);

            NTSTATUS NewZwOpenProcess(OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId OPTIONAL);
            NTSTATUS NewZwTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,IN NTSTATUS ExitStatus);

            NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId, OUT PEPROCESS *pEProcess);

            ZWOPENPROCESS OldZwOpenProcess = NULL;
            ZWTERMINATEPROCESS OldZwTerminateProcess = NULL;

            VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
            {
            //卸載時會調用
            PVOID Oldfun = NULL;

            HOOK_SYSCALL(ZwOpenProcess,OldZwOpenProcess,Oldfun);
            HOOK_SYSCALL(ZwTerminateProcess,OldZwTerminateProcess,Oldfun);

            if(m_MDL){
            ?? MmUnmapLockedPages(m_Mapped,m_MDL);
            ?? IoFreeMdl(m_MDL);
            }

            KdPrint(("驅動卸載完畢.\n"));
            }

            NTSTATUS NewZwOpenProcess(OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId OPTIONAL)
            {
            if((long)ClientId->UniqueProcess == pid)
            {
            ?? KdPrint(("保護進程,打開操作 PID:%ld\n",pid));
            ?? return STATUS_ACCESS_DENIED;
            }
            //剩下的交給我們的原函數
            return OldZwOpenProcess(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
            }

            NTSTATUS NewZwTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,IN NTSTATUS ExitStatus)
            {
            NTSTATUS nStatus = STATUS_SUCCESS;
            PEPROCESS EPROCESSPROTECT = NULL;
            PEPROCESS EPROCESSKILL = NULL;

            //我們要保護的進程的PID存在變量pid里,使用PsLookupProcessByProcessId可以通過PID獲得EPROCESS
            PsLookupProcessByProcessId((ULONG)pid,&EPROCESSPROTECT);

            //通過ProcessHandle來獲得當前要結束的進程的EPROCESS
            if (ObReferenceObjectByHandle(ProcessHandle,GENERIC_READ,NULL,KernelMode,&EPROCESSKILL,0) == STATUS_SUCCESS)
            {
            ?? //如果要結束的是我們需要保護的進程,這里分兩種情況
            ?? if (EPROCESSPROTECT== EPROCESSKILL)
            ?? {
            ??? if (EPROCESSPROTECT != PsGetCurrentProcess())
            ??? {//情況一:當前進程不是我們所保護的進程
            ???? //換句話說也就是其他進程試圖結束我們所保護的進程,當然不能讓他結束
            ???? KdPrint(("[-]進程保護,外部程序試圖關閉保護進程\n"));
            ???? nStatus = STATUS_ACCESS_DENIED;
            ??? }else{
            ???? //當我們程序點擊關閉也是使用的TermianteProcess,
            ???? //所以這種情況下當前進程是我們所保護的進程,則正常退出
            ???? KdPrint(("[-]進程保護,程序自身退出請求!\n"));
            ??? }
            ???
            ?? }
            }

            //剩下的交給我們的原函數
            if (nStatus != STATUS_SUCCESS)
            ?? return nStatus;
            else
            ?? return OldZwTerminateProcess(ProcessHandle,ExitStatus);
            }

            NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING theRegistryPath)
            {
            NTSTATUS??????? ntStatus = STATUS_SUCCESS;
            PDEVICE_OBJECT deviceObject = NULL;

            DriverObject->DriverUnload = OnUnload;

            m_MDL = MmCreateMdl(NULL,KeServiceDescriptorTable.ServiceTableBase,KeServiceDescriptorTable.NumberOfServices*4);
            if(!m_MDL)
            {
            ?? return STATUS_UNSUCCESSFUL;
            }

            //非分頁內存
            MmBuildMdlForNonPagedPool(m_MDL);

            m_MDL->MdlFlags = m_MDL->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;

            //鎖定
            m_Mapped = MmMapLockedPages(m_MDL, KernelMode);

            HOOK_SYSCALL(ZwOpenProcess,NewZwOpenProcess,OldZwOpenProcess);
            HOOK_SYSCALL(ZwTerminateProcess,NewZwTerminateProcess,OldZwTerminateProcess);

            return STATUS_SUCCESS;
            }

            热久久国产精品| 久久婷婷国产麻豆91天堂| 99久久精品国产一区二区蜜芽| 日韩精品久久久久久久电影蜜臀| 久久久久久久综合狠狠综合| 久久99精品国产麻豆蜜芽| 久久精品国产亚洲AV不卡| 久久99国产精品成人欧美| 精品无码久久久久久久久久| 国内精品久久久久久久coent | 久久精品一区二区三区不卡| 久久人人爽人人爽人人AV东京热 | A狠狠久久蜜臀婷色中文网| 囯产极品美女高潮无套久久久| 久久亚洲国产成人影院| 久久夜色精品国产亚洲| 99精品国产免费久久久久久下载| 亚洲午夜无码久久久久小说| 亚洲精品无码久久久久| 麻豆精品久久精品色综合| 久久电影网| 久久久久亚洲av无码专区| 91精品久久久久久无码| 日本久久中文字幕| 久久亚洲春色中文字幕久久久| 美女写真久久影院| 色播久久人人爽人人爽人人片AV| 久久er99热精品一区二区| 久久精品无码专区免费| 亚洲精品tv久久久久久久久| 人人狠狠综合久久亚洲婷婷| 久久久久久曰本AV免费免费| 亚洲国产精品久久66| 日本WV一本一道久久香蕉| 亚洲国产精品久久久久| 97久久婷婷五月综合色d啪蜜芽| 国产精品美女久久久| 精品久久久久久无码不卡| 精品国产乱码久久久久久1区2区| 久久久久亚洲AV无码去区首| 久久本道伊人久久|