最近有在作一個東西,須要在ring0下攔截進程啓動並注入DLL(dll用於hook ring3下的API),不少種實現方法,此處採用sudami大神提供的思路,另外一位大俠提供的參考代碼。雖然這個東西沒什麼技術含量,但對於我這種剛入門內核的人仍是搞了好久才作出來,藍屏不少,要注意不少細節.多線程
思路:進程建立完時是一個空水壺,裏面沒有沸騰的熱水(threads),因而系統調用NtCreateThread建立其主線程(給空水壺注水 – 涼水),在這個暫停的線程裏面折騰了一陣後完事了也厭倦了,因而系統跳了出來,回到進程空間中,調用Kernel32.dll去通知CSRSS.EXE,對它說:「這裏有一個新進程出生了,你在你的表裏標記一下」。而後就開始加載DLL啦,把系統KnownDLLs中的本身須要的DLL都Map一份到這個大水壺中。接着KiThreadStartup加熱水壺中的涼水,因而水就開始沸騰了,此時主線程開始工做。。。
攔截NtCreateThread,取得當前線程上下文,保存它要返回的地址(會回到空水壺中去),劫持爲咱們本身分配的地址,在其中填充ShellCode來加載目的DLL。至於選擇Buffer,思路不少。這裏可簡單的Attach到當前進程,在充足的虛擬2GB進程地址空間中分配屬於你本身的一塊小內存,夠放ShellCode足矣。示意圖以下:spa
代碼:寫的很醜線程
NTSTATUS MyNtCreateThread ( OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle, OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, IN PHANDLE InitialTeb, IN BOOLEAN CreateSuspended ) { pfnNtCreateThread oldNtCreateThread = (pfnNtCreateThread)SystemServiceAddr[ServiceCreateThreadID]; if(IsHandleExist(ProcessHandle)){ CHAR ProcessName[16]; NTSTATUS ObjectStatus; PRKPROCESS pProcess; POBJECT_TYPE PsProcessType; NTSTATUS ResultStatus; DbgPrint( "CreateThread(%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x)\n", ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle, ClientId, ThreadContext, InitialTeb, CreateSuspended); PsProcessType = NULL; ///得到EPROCESS對象 ObjectStatus = ObReferenceObjectByHandle( ProcessHandle, PROCESS_ALL_ACCESS, PsProcessType, UserMode, (PVOID *)&pProcess, NULL); if (ObjectStatus ==STATUS_SUCCESS) { //ProcessName = (CHAR*)pProcess+0x174; RtlStringCbCopyA(ProcessName,16,(CHAR*)pProcess+0x174); _strlwr(ProcessName);//進程名轉換爲小寫 if(strstr(ProcessName,Iexplore)) { NTSTATUS AllocStatus; UCHAR * BaseAddr; SIZE_T RegionSize; ULONG Win32StartAddr; ULONG LoadLibraryAddr; RegionSize = 100; BaseAddr = NULL; PsProcessType = NULL; KAPC_STATE apcstate; LoadLibraryAddr = g_addrinfo.LoadLibraryAddr; if(ThreadContext) { Win32StartAddr = ThreadContext->Eax; if (!Win32StartAddr) { DbgPrint("Win32StartAddr not set\n"); } else { //切換上下文 KeDetachProcess(); KeAttachProcess(pProcess); //allocating memory with PAGE_EXECUTE_READWRITE access rights // KeUnstackDetachProcess(&apcstate); // KeStackAttachProcess(pProcess,&apcstate); AllocStatus = ZwAllocateVirtualMemory( NtCurrentProcess(), (PVOID*)&BaseAddr, 0, &RegionSize, MEM_COMMIT , PAGE_EXECUTE_READWRITE); if (AllocStatus!=STATUS_SUCCESS) { DbgPrint("Fail to Allocate memory! AllocStatus = 0x%x\n",AllocStatus); } else { ULONG Offset = 0; ULONG OffsetStrAddr = 0; DbgPrint("Memory allocation OK! BaseAddr = 0x%x\n",BaseAddr); BaseAddr[Offset] = 0x68; //push 0xXXXXXXXX ++Offset; OffsetStrAddr = Offset; Offset += 4; BaseAddr[Offset] = 0xbb; //mov ebx,LoadLibraryAddr ++Offset; *(ULONG *)(BaseAddr+Offset) = LoadLibraryAddr; Offset += 4; BaseAddr[Offset] = 0xff; //call ebx ++Offset; BaseAddr[Offset] = 0xd3; ++Offset; BaseAddr[Offset] = 0xb8; //mov eax,Win32StartAddr ++Offset; *(ULONG *)(BaseAddr+Offset) = Win32StartAddr; Offset += 4; BaseAddr[Offset] = 0x50; //push eax ++Offset; BaseAddr[Offset] = 0xc3; //ret ++Offset; *(ULONG *)(BaseAddr+OffsetStrAddr) = (ULONG)(BaseAddr + Offset); // parameter for LoadLibrary //tSetKey.dll //memcpy(BaseAddr+Offset,"tSetKey.dll",strlen("tSetKey.dll")+1); memcpy(BaseAddr+Offset,g_addrinfo.DllPath,sizeof(g_addrinfo.DllPath)); DbgPrint("<EAX:0x%08x>\n",Win32StartAddr); Win32StartAddr = (ULONG)BaseAddr; }//end ZwAllocateVirtualMemory //切換上下文 KeDetachProcess(); ///設置Win32StartAddr ThreadContext->Eax = Win32StartAddr; } }//end ThreadConext ObDereferenceObject(pProcess); }//end strstr RemoveHandle(ProcessHandle); }//end obj else { DbgPrint(("Fail to RefernceObject. Stopping Injecting Technique.\n")); } }//end Ishandleexist; return oldNtCreateThread(ThreadHandle,DesiredAccess,ObjectAttributes,ProcessHandle,ClientId,ThreadContext,InitialTeb,CreateSuspended); }
對於一個進程的多線程環境 ,這裏用一個鏈表來維護進程句柄,同時hook zwcreateprocessex,在裏面添加句柄,在createthread裏刪除.code