(70)内核重载 xp sp3 x86 单核
生活随笔
收集整理的這篇文章主要介紹了
(70)内核重载 xp sp3 x86 单核
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、項目說明
這次項目是這樣設計的,首先 inline hook NtTerminateProcess 函數,使其他進程不能關閉受保護的進程,這里選擇記事本。
然后編寫一個普通的程序,調用 TerminateProcess 函數關閉記事本,如無意外是關不掉的。
然后編寫驅動,從文件系統中加載一份新內核到內存,拉伸PE,修復重定位表,IAT表,SSDT表;HOOK KiFastCallEntry 函數,讓我們的程序系統調用走新內核,這樣就可以關掉記事本了。
二、前置任務
首先把保護記事本和關閉記事本的程序給出,這兩個沒什么難度,不想解釋。
效果就是加載保護驅動后,無法 TerminateProcess 關閉記事本。
調用 TerminateProcess 關閉記事本的程序
// KillNotepad.cpp : 定義控制臺應用程序的入口點。 //#include "stdafx.h" #include <Windows.h>// 提權函數:提升為DEBUG權限 BOOL EnableDebugPrivilege() {HANDLE hToken;BOOL fOk=FALSE;if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken)){TOKEN_PRIVILEGES tp;tp.PrivilegeCount=1;LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid);tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);fOk=(GetLastError()==ERROR_SUCCESS);CloseHandle(hToken);}return fOk; }int _tmain(int argc, _TCHAR* argv[]) {EnableDebugPrivilege();HWND hWnd = FindWindowA(NULL, "無標題 - 記事本");DWORD dwPid = -1;GetWindowThreadProcessId(hWnd, &dwPid);HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);TerminateProcess(hProcess,0);return 0; }保護記事本的驅動
//#include <ntddk.h> #include <ntifs.h> #include <ntimage.h>//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------typedef struct _LDR_DATA_TABLE_ENTRY {LIST_ENTRY InLoadOrderLinks;LIST_ENTRY InMemoryOrderLinks;LIST_ENTRY InInitializationOrderLinks;PVOID DllBase;PVOID EntryPoint;ULONG SizeOfImage;UNICODE_STRING FullDllName;UNICODE_STRING BaseDllName;ULONG Flags;UINT16 LoadCount;UINT16 TlsIndex;LIST_ENTRY HashLinks;PVOID SectionPointer;ULONG CheckSum;ULONG TimeDateStamp;PVOID LoadedImports;PVOID EntryPointActivationContext;PVOID PatchInformation; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;typedef NTSTATUS (*NTTERMINATEPROCESS) (HANDLE ProcessHandle, NTSTATUS ExitStatus);// 系統服務表 typedef struct _KSYSTEM_SERVICE_TABLE {PULONG ServiceTableBase; // 函數地址表PULONG ServiceCounterTableBase; // SSDT 函數被調用的次數ULONG NumberOfService; // 函數個數PULONG ParamTableBase; // 函數參數表 } KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;// SSDT表 typedef struct _KSERVICE_TABLE_DESCRIPTOR {KSYSTEM_SERVICE_TABLE ntoskrnl; // 內核函數KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 函數KSYSTEM_SERVICE_TABLE unUsed1;KSYSTEM_SERVICE_TABLE unUsed2; } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path); VOID DriverUnload(PDRIVER_OBJECT driver); VOID PageProtectOff(); VOID PageProtectOn(); VOID GetKernelBase(PDRIVER_OBJECT driver, PVOID *pKrnlBase, PULONG uKrnlImageSize); PVOID MemorySearch(PVOID bytecode, ULONG bytecodeLen, PVOID pBeginAddress, PVOID pEndAddress); VOID HookNtTerminateProcess(); VOID UnhookNtTerminateProcess(); VOID HbgNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus);//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------PDRIVER_OBJECT g_Driver; extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; // 內核導出的全局變量PVOID pNtTerminateProcess; PVOID pNtTerminateProcessHookRet;// NtTerminateProcess 系統調用號 #define NTTERMINATEPROCESS_INDEX 0x101//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) { g_Driver = driver;driver->DriverUnload = DriverUnload;HookNtTerminateProcess();return STATUS_SUCCESS; }// 卸載驅動 VOID DriverUnload(PDRIVER_OBJECT driver) {UnhookNtTerminateProcess();DbgPrint("Kernel Unload Successfully.\n"); }// 關閉頁保護 VOID PageProtectOff() {__asm{cli; // 關閉中斷mov eax, cr0;and eax, not 0x10000; // WP位置0mov cr0, eax;} }// 開啟頁保護 VOID PageProtectOn() {__asm{mov eax, cr0;or eax, 0x10000; // WP位置1mov cr0, eax;sti; // 恢復中斷} }// 獲取內核基址,大小 VOID GetKernelBase(PDRIVER_OBJECT driver, PVOID *pKrnlBase, PULONG uKrnlImageSize) {PLDR_DATA_TABLE_ENTRY pLdteHead; // 內核模塊鏈表頭PLDR_DATA_TABLE_ENTRY pLdteCur; // 遍歷指針UNICODE_STRING usKrnlBaseDllName; // 內核模塊名RtlInitUnicodeString(&usKrnlBaseDllName,L"ntoskrnl.exe");pLdteHead = (PLDR_DATA_TABLE_ENTRY)driver->DriverSection;pLdteCur = pLdteHead;do {PLDR_DATA_TABLE_ENTRY pLdte = CONTAINING_RECORD(pLdteCur, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);//DbgPrint("DllBase: %p, SizeOfImage: %08X %wZ\n", pLdteCur->DllBase, pLdteCur->SizeOfImage, &(pLdteCur->FullDllName));if (RtlCompareUnicodeString(&pLdteCur->BaseDllName, &usKrnlBaseDllName, TRUE) == 0){*pKrnlBase = pLdteCur->DllBase;*uKrnlImageSize = pLdteCur->SizeOfImage;return;}pLdteCur = (PLDR_DATA_TABLE_ENTRY)pLdteCur->InLoadOrderLinks.Flink;} while (pLdteHead != pLdteCur);return; }// 特征碼搜索 PVOID MemorySearch(PVOID bytecode, ULONG bytecodeLen, PVOID pBeginAddress, PVOID pEndAddress) {PVOID pCur = pBeginAddress;while (pCur != pEndAddress){if (RtlCompareMemory(bytecode,pCur,bytecodeLen) == bytecodeLen){return pCur;}((ULONG)pCur)++;}return 0; }// hook NtTerminateProcess VOID HookNtTerminateProcess() { pNtTerminateProcess = (PVOID)KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[NTTERMINATEPROCESS_INDEX];PageProtectOff();// hook NtTerminateProcess ,采取短跳+長跳的方式*(PUCHAR)((ULONG)pNtTerminateProcess - 5) = 0xE9;*(PULONG)((ULONG)pNtTerminateProcess - 4) = (ULONG)HbgNtTerminateProcess - (ULONG)pNtTerminateProcess;*(PUSHORT)pNtTerminateProcess = (USHORT)0xF9EB;PageProtectOn(); }// unhook NtTerminateProcess VOID UnhookNtTerminateProcess() {*(PUSHORT)pNtTerminateProcess = (USHORT)0xFF8B;*(PUCHAR)((ULONG)pNtTerminateProcess - 5) = 0xCC;*(PULONG)((ULONG)pNtTerminateProcess - 4) = 0xCCCCCCCC; }// 被修改的 NtTerminateProcess 函數,簡單打印參數 __declspec(naked) VOID HbgNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus) {PEPROCESS pEprocess;NTSTATUS status;PCHAR ImageFileName;__asm{mov edi,edi;push ebp;mov ebp,esp;pushad;pushfd;sub esp,0x20;}status = ObReferenceObjectByHandle(ProcessHandle,FILE_ANY_ACCESS,*PsProcessType,KernelMode,&pEprocess,NULL);if (!NT_SUCCESS(status)){goto ReturnToNtTerminateProcess;}// 根據鏡像文件名判斷是不是要保護的進程,字符串最大長度是16,超過就會截斷,所以不用擔心越界ImageFileName = (PCHAR)pEprocess + 0x174;if (strcmp(ImageFileName, "notepad.exe") == 0){if (ProcessHandle == (HANDLE)0xFFFFFFFF){// 通過關閉按鈕關閉goto ReturnToNtTerminateProcess; }else{// 通過任務管理器或其他進程調用TerminateProcess關閉//DbgPrint("Terminate denied. %s: NtTerminateProcess(%x, %x)\n", ImageFileName, ProcessHandle, ExitStatus);goto ReturnAccessDenied;}} ReturnToNtTerminateProcess:pNtTerminateProcessHookRet = (PVOID)((ULONG)pNtTerminateProcess + 5);__asm{add esp,0x20;popfd;popad;jmp pNtTerminateProcessHookRet;} ReturnAccessDenied:__asm{ add esp,0x20;popfd;popad;leave;mov eax,0xC0000022; // STATUS_ACCESS_DENIEDretn 0x08;} }三、內核重載
寫不出來,一是能力不足,二是動機不足。
動機方面,后面會學自建調用框架,完美替代內核重載。
能力方面,目前主要存在以下疑問:
- MDL 是什么,不清楚,ExAllocatePool 申請出來的內存似乎還不能執行?
- 修復 IAT 的方式?是否從當前內核內存鏡像中復制過來?
- 修復重定位的方式?用老辦法修復,還是從當前內核鏡像中拷貝?是否必須共用一份全局變量?
- 修復SSDT表,是否是拷貝現有的SSDT表,然后減去新舊內核鏡像的地址差?
下面給出目前唯一的成果,0環讀寫文件的API。
// 讀取文件到內存中,返回讀取的字節數;讀取失敗返回0 ULONG FileToMemory(LPCWSTR lpszFile, PVOID *pFileBuffer) {OBJECT_ATTRIBUTES objectAttributes;IO_STATUS_BLOCK iostatus;HANDLE hfile;UNICODE_STRING KernelFileUnicodeString;NTSTATUS ntStatus;FILE_STANDARD_INFORMATION fsi;PUCHAR pBuffer;//初始化UNICODE_STRING字符串//RtlInitUnicodeString( &KernelFileUnicodeString, L"\\??\\C:\\Windows\\System32\\ntkrnlpa.exe");RtlInitUnicodeString( &KernelFileUnicodeString, lpszFile);//初始化objectAttributesInitializeObjectAttributes(&objectAttributes, &KernelFileUnicodeString,OBJ_CASE_INSENSITIVE, NULL, NULL );//創建文件ntStatus = ZwOpenFile( &hfile, GENERIC_ALL,&objectAttributes, &iostatus, FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_SYNCHRONOUS_IO_NONALERT);if (!NT_SUCCESS(ntStatus)){KdPrint(("The file is not exist!\n"));return 0;}//讀取文件長度ntStatus = ZwQueryInformationFile(hfile,&iostatus,&fsi,sizeof(FILE_STANDARD_INFORMATION),FileStandardInformation);//KdPrint(("The program want to read %d bytes\n",fsi.EndOfFile.QuadPart));//為讀取的文件分配緩沖區pBuffer = (PUCHAR)ExAllocatePool(PagedPool,(LONG)fsi.EndOfFile.QuadPart);//讀取文件ZwReadFile(hfile,NULL,NULL,NULL,&iostatus,pBuffer,(LONG)fsi.EndOfFile.QuadPart,NULL,NULL);//KdPrint(("The program really read %d bytes\n",iostatus.Information));//釋放緩沖區//ExFreePool(pBuffer);*pFileBuffer = pBuffer;//關閉文件句柄ZwClose(hfile);return (ULONG)fsi.EndOfFile.QuadPart; }// 內存數據寫入文件 VOID MemoryToFile(PVOID pMemBuffer, ULONG ulSize, LPCWSTR lpszFile) {OBJECT_ATTRIBUTES objectAttributes;IO_STATUS_BLOCK iostatus;HANDLE hfile;UNICODE_STRING logFileUnicodeString;NTSTATUS ntStatus;//初始化UNICODE_STRING字符串RtlInitUnicodeString( &logFileUnicodeString, lpszFile);//初始化objectAttributesInitializeObjectAttributes(&objectAttributes,&logFileUnicodeString,OBJ_CASE_INSENSITIVE,//對大小寫敏感 NULL, NULL );//創建文件ntStatus = ZwCreateFile( &hfile, GENERIC_WRITE,&objectAttributes, &iostatus, NULL,FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE,FILE_OPEN_IF,//即使存在該文件,也創建 FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );ZwWriteFile(hfile,NULL,NULL,NULL,&iostatus,pMemBuffer,ulSize,NULL,NULL);KdPrint(("The program really wrote %d bytes\n",iostatus.Information));//關閉文件句柄ZwClose(hfile);}總結
以上是生活随笔為你收集整理的(70)内核重载 xp sp3 x86 单核的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (69)番外 —— 编写一个简易的反调试
- 下一篇: (71)APC队列,KAPC结构,分析