ring0下注入DLL

最近有在作一個東西,須要在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

相關文章
相關標籤/搜索