VOID InjectDllIntoProcess(PWCHAR ProcessName) { HANDLE ThreadId; HANDLE ProcessId = GetPidAndTidByName(ProcessName, &ThreadId); if (ProcessId) { PETHREAD Thread; NTSTATUS St = PsLookupThreadByThreadId(ThreadId, &Thread); if (NT_SUCCESS(St)) { PKAPC pkaApc = (PKAPC)ExAllocatePool(NonPagedPool, sizeof(KAPC)); if(pkaApc) { KeInitializeApc(pkaApc, (PKTHREAD)Thread, 0, APCInjectRoutine, 0, 0, KernelMode, 0); KeInsertQueueApc(pkaApc, 0, 0, IO_NO_INCREMENT); } ObDereferenceObject(Thread); } } else { DbgPrint("GetPidAndTidByName error\n"); } }
/* 获取ShadowSSDT表地址偏移 */ ULONG GetSSDTShadowTableAddr() { ULONG ktrdCid; NTSTATUS status; ULONG ethread; ULONG shadowTableAddr=0; ULONG i=0; /* 尝试枚举系统线程获取 KTHREAD */ for( ktrdCid = 8; ktrdCid < 32768; ktrdCid += 4) { status = PsLookupThreadByThreadId( (HANDLE)ktrdCid, &(PETHREAD)ethread ); if( NT_SUCCESS(status) ) { // if( *(PULONG)( ethread + 0x0e0 ) != (ULONG)KeServiceDescriptorTable ) { /* 获取 KTHREAD.ServiceTable 指针值 */ shadowTableAddr = *(PULONG)( ethread + 0x0e0 ); break; } } } return shadowTableAddr; }
/* * UserGetKeyboardLayout * * Returns hkl of given thread keyboard layout */ HKL FASTCALL UserGetKeyboardLayout( DWORD dwThreadId) { NTSTATUS Status; PETHREAD pThread; PTHREADINFO pti; PKL pKl; HKL hKl; if (!dwThreadId) { pti = PsGetCurrentThreadWin32Thread(); pKl = pti->KeyboardLayout; return pKl ? pKl->hkl : NULL; } Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)dwThreadId, &pThread); if (!NT_SUCCESS(Status)) { EngSetLastError(ERROR_INVALID_PARAMETER); return NULL; } pti = PsGetThreadWin32Thread(pThread); pKl = pti->KeyboardLayout; hKl = pKl ? pKl->hkl : NULL;; ObDereferenceObject(pThread); return hKl; }
ULONG GetSwapContextAddr() { PETHREAD pEThread = NULL; NTSTATUS Status = STATUS_SUCCESS; Status = PsLookupThreadByThreadId( 8, &pEThread ); if( !NT_SUCCESS(Status) ) return 0; if( MmIsAddressValid( (PULONG)((ULONG)pEThread+0x28) ) ) { ULONG pCurrentStack = *(PULONG)((ULONG)pEThread + 0x28); return *(PULONG)(pCurrentStack+0x8) - 5; } else return 0; }
NTSTATUS HwlTerminateProcess64(PEPROCESS Process) { //get pspterminatethreadbypointer ULONG32 callcode=0; ULONG64 AddressOfPspTTBP=0, AddressOfPsTST=0, i=0; PETHREAD Thread=NULL; PEPROCESS tProcess=NULL; NTSTATUS status=0; if(PspTerminateThreadByPointer==NULL) { AddressOfPsTST=(ULONG64)GetFunctionAddr(L"PsTerminateSystemThread"); if(AddressOfPsTST==0) return STATUS_UNSUCCESSFUL; for(i=1;i<0xff;i++) { if(MmIsAddressValid((PVOID)(AddressOfPsTST+i))!=FALSE) { if(*(BYTE *)(AddressOfPsTST+i)==0x01 && *(BYTE *)(AddressOfPsTST+i+1)==0xe8) //目标地址-原始地址-5=机器码 ==> 目标地址=机器码+5+原始地址 { RtlMoveMemory(&callcode,(PVOID)(AddressOfPsTST+i+2),4); AddressOfPspTTBP=(ULONG64)callcode + 5 + AddressOfPsTST+i+1; } } } PspTerminateThreadByPointer=(PSPTERMINATETHREADBYPOINTER)AddressOfPspTTBP; } //loop call pspterminatethreadbypointer for(i=4;i<0x40000;i+=4) { status=PsLookupThreadByThreadId((HANDLE)i, &Thread); if(NT_SUCCESS(status)) { tProcess=IoThreadToProcess(Thread); if(tProcess==Process) PspTerminateThreadByPointer(Thread,0,1); ObDereferenceObject(Thread); } } //return status return STATUS_SUCCESS; }
__checkReturn bool Initialize() { if (!m_stack.Begin()) { if (!Id && NT_SUCCESS(PsLookupThreadByThreadId(m_threadId, &Id))) { m_vadScanner.Init(Id); CPassiveLvl irql; void* teb; if (teb = GetWow64Teb(Id)) ResolveThreadLimits<NT_TIB32>(reinterpret_cast<NT_TIB32*>(teb)); else if (teb = PsGetThreadTeb(Id)) ResolveThreadLimits<NT_TIB>(reinterpret_cast<NT_TIB*>(teb)); //DbgPrint("\nstack boundaries : %p %p\n", m_stack.Begin(), m_stack.End()); return true; } } return false; }
/* * Test the Thread to verify and validate it. Hard to the core tests are required. */ PTHREADINFO FASTCALL IntTID2PTI(HANDLE id) { NTSTATUS Status; PETHREAD Thread; PTHREADINFO pti; Status = PsLookupThreadByThreadId(id, &Thread); if (!NT_SUCCESS(Status)) { return NULL; } if (PsIsThreadTerminating(Thread)) { ObDereferenceObject(Thread); return NULL; } pti = PsGetThreadWin32Thread(Thread); if (!pti) { ObDereferenceObject(Thread); return NULL; } // Validate and verify! _SEH2_TRY { if (pti->TIF_flags & TIF_INCLEANUP) pti = NULL; if (pti && !(pti->TIF_flags & TIF_GUITHREADINITIALIZED)) pti = NULL; if (PsGetThreadId(Thread) != id) pti = NULL; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { pti = NULL; } _SEH2_END ObDereferenceObject(Thread); return pti; }
static VOID JpkfagsOnCreateThread( __in HANDLE ProcessId, __in HANDLE ThreadId, __in BOOLEAN Create ) { PETHREAD ThreadObject; UNREFERENCED_PARAMETER( ProcessId ); if ( ! Create ) { // // We are obly interested in thread terminations. // // Obtain ETHREAD from ThreadId. // if ( NT_SUCCESS( PsLookupThreadByThreadId( ThreadId, &ThreadObject ) ) ) { JpkfagpCleanupThread( ThreadObject ); ObDereferenceObject( ThreadObject ); } } }
BOOL APIENTRY NtUserGetGUIThreadInfo( DWORD idThread, /* If NULL use foreground thread */ LPGUITHREADINFO lpgui) { NTSTATUS Status; PTHRDCARETINFO CaretInfo; GUITHREADINFO SafeGui; PDESKTOP Desktop; PUSER_MESSAGE_QUEUE MsgQueue; PTHREADINFO W32Thread; PETHREAD Thread = NULL; DECLARE_RETURN(BOOLEAN); TRACE("Enter NtUserGetGUIThreadInfo\n"); UserEnterShared(); Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); } if(SafeGui.cbSize != sizeof(GUITHREADINFO)) { EngSetLastError(ERROR_INVALID_PARAMETER); RETURN( FALSE); } if (idThread) { Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)idThread, &Thread); if(!NT_SUCCESS(Status)) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread; Desktop = W32Thread->rpdesk; if (!Thread || !Desktop ) { if(Thread) ObDereferenceObject(Thread); EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } if ( W32Thread->MessageQueue ) MsgQueue = W32Thread->MessageQueue; else { if ( Desktop ) MsgQueue = Desktop->ActiveMessageQueue; } } else { /* Get the foreground thread */ /* FIXME: Handle NULL queue properly? */ MsgQueue = IntGetFocusMessageQueue(); if(!MsgQueue) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } } CaretInfo = &MsgQueue->CaretInfo; SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0); /* if (W32Thread->pMenuState->pGlobalPopupMenu) { SafeGui.flags |= GUI_INMENUMODE; if (W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify) SafeGui.hwndMenuOwner = UserHMGetHandle(W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify); if (W32Thread->pMenuState->pGlobalPopupMenu->fHasMenuBar) { if (W32Thread->pMenuState->pGlobalPopupMenu->fIsSysMenu) { SafeGui.flags |= GUI_SYSTEMMENUMODE; } } else { SafeGui.flags |= GUI_POPUPMENUMODE; } } */ SafeGui.hwndMenuOwner = MsgQueue->MenuOwner; if (MsgQueue->MenuOwner) SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState; if (MsgQueue->MoveSize) SafeGui.flags |= GUI_INMOVESIZE; /* FIXME: Add flag GUI_16BITTASK */ SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0; SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0; SafeGui.hwndCapture = MsgQueue->spwndCapture ? UserHMGetHandle(MsgQueue->spwndCapture) : 0; SafeGui.hwndMoveSize = MsgQueue->MoveSize; SafeGui.hwndCaret = CaretInfo->hWnd; SafeGui.rcCaret.left = CaretInfo->Pos.x; SafeGui.rcCaret.top = CaretInfo->Pos.y; SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx; SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy; if (idThread) ObDereferenceObject(Thread); Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); } RETURN( TRUE); CLEANUP: TRACE("Leave NtUserGetGUIThreadInfo, ret=%u\n",_ret_); UserLeave(); END_CLEANUP; }
/// <summary> /// Find first thread of the target process /// </summary> /// <param name="pid">Target PID.</param> /// <param name="ppThread">Found thread. Thread object reference count is increased by 1</param> /// <returns>Status code</returns> NTSTATUS BBLookupProcessThread( IN HANDLE pid, OUT PETHREAD* ppThread ) { NTSTATUS status = STATUS_SUCCESS; PVOID pBuf = ExAllocatePoolWithTag( NonPagedPool, 1024 * 1024, BB_POOL_TAG ); PSYSTEM_PROCESS_INFO pInfo = (PSYSTEM_PROCESS_INFO)pBuf; ASSERT( ppThread != NULL ); if (ppThread == NULL) return STATUS_INVALID_PARAMETER; if (!pInfo) { DPRINT( "BlackBone: %s: Failed to allocate memory for process list\n", __FUNCTION__ ); return STATUS_NO_MEMORY; } // Get the process thread list status = ZwQuerySystemInformation( SystemProcessInformation, pInfo, 1024 * 1024, NULL ); if (!NT_SUCCESS( status )) { ExFreePoolWithTag( pBuf, BB_POOL_TAG ); return status; } // Find target thread if (NT_SUCCESS( status )) { status = STATUS_NOT_FOUND; for (;;) { if (pInfo->UniqueProcessId == pid) { status = STATUS_SUCCESS; break; } else if (pInfo->NextEntryOffset) pInfo = (PSYSTEM_PROCESS_INFO)((PUCHAR)pInfo + pInfo->NextEntryOffset); else break; } } // Reference target thread if (NT_SUCCESS( status )) { status = STATUS_NOT_FOUND; // Get first thread for (ULONG i = 0; i < pInfo->NumberOfThreads; i++) { // Skip current thread if (/*pInfo->Threads[i].WaitReason == Suspended || pInfo->Threads[i].ThreadState == 5 ||*/ pInfo->Threads[i].ClientId.UniqueThread == PsGetCurrentThread()) { continue; } status = PsLookupThreadByThreadId( pInfo->Threads[i].ClientId.UniqueThread, ppThread ); break; } } else DPRINT( "BlackBone: %s: Failed to locate process\n", __FUNCTION__ ); if (pBuf) ExFreePoolWithTag( pBuf, BB_POOL_TAG ); return status; }
NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION extension = DeviceObject->DeviceExtension; switch(irpStack->Parameters.DeviceIoControl.IoControlCode){ case IOCTL_GET_HOOKS: { unsigned int i,j; PETHREAD pethread; PTHREADINFO ptiCurrent; PDESKTOPINFO pdesktopinfo; PPROCESSINFO ppi; PARAMS_GET_HOOKS *params; DATA_GET_HOOKS *data; PHOOK* aphkStart; if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DATA_GET_HOOKS)) { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARAMS_GET_HOOKS)) { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } params = ExAllocatePoolWithTag(PagedPool, sizeof(PARAMS_GET_HOOKS), 'tdkh'); if (!params) { break; } memcpy(params, Irp->AssociatedIrp.SystemBuffer, sizeof(PARAMS_GET_HOOKS)); pethread = PsGetCurrentThread(); ptiCurrent = PsGetThreadWin32Thread(pethread); if (g_win7) { pdesktopinfo = (PDESKTOPINFO)((unsigned int*)ptiCurrent)[0xCC/4]; ppi = (PPROCESSINFO)&((char*)ptiCurrent)[0xB8]; aphkStart = (PHOOK*)&((char*)pdesktopinfo)[0x10]; } else { pdesktopinfo = ptiCurrent->pDeskInfo; ppi = ptiCurrent->ppi; aphkStart = pdesktopinfo->aphkStart; } data = (DATA_GET_HOOKS*)Irp->AssociatedIrp.SystemBuffer; memset(data, 0, sizeof(DATA_GET_HOOKS)); retrieve_hooks(aphkStart, ppi, data->global_hook); data->threads=0; j=0; for (i=0;i<params->threads;i++) { if (PsLookupThreadByThreadId((HANDLE)params->thread_id[i], &pethread) != STATUS_SUCCESS) { continue; } if (g_win7) { if (PsGetThreadSessionId(pethread) != PsGetCurrentProcessSessionId()) { ObDereferenceObject(pethread); continue; } } ptiCurrent = PsGetThreadWin32Thread(pethread); if (ptiCurrent) { if (g_win7) { aphkStart = (PHOOK*)&((char*)ptiCurrent)[0x198]; ppi = (PPROCESSINFO)&((char*)ptiCurrent)[0xB8]; } else { aphkStart = (PHOOK*)&((char*)ptiCurrent)[0xf4]; ppi = ptiCurrent->ppi; } if (has_hooks(aphkStart)) { data->threads++; if (j<MAX_OUT_THREADS) { retrieve_hooks(aphkStart, ppi, data->thread[j].hook); data->thread[j].thread_id = params->thread_id[i]; j++; } } } ObDereferenceObject(pethread); } ExFreePool(params); ntStatus = STATUS_SUCCESS; break; } case IOCTL_HMOD_TBL_INX_TO_MOD_NAME: { DATA_HMOD_TBL_INX_TO_MOD_NAME *data; PARAMS_HMOD_TBL_INX_TO_MOD_NAME *params; WCHAR tmp; int hmod_table_index; if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DATA_HMOD_TBL_INX_TO_MOD_NAME)) { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARAMS_HMOD_TBL_INX_TO_MOD_NAME)) { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } params = Irp->AssociatedIrp.SystemBuffer; UserGetAtomName = (UserGetAtomName_ptr)params->UserGetAtomName_address; aatomSysLoaded = (ATOM*)params->aatomSysLoaded_address; hmod_table_index = params->hmod_table_index; if (UserGetAtomName && aatomSysLoaded) { __try { (*UserGetAtomName)(aatomSysLoaded[0], &tmp, 1); } __except (EXCEPTION_EXECUTE_HANDLER) { UserGetAtomName = 0; } } data = Irp->AssociatedIrp.SystemBuffer; if (UserGetAtomName) { (*UserGetAtomName)(aatomSysLoaded[hmod_table_index], data->module_name, MAX_PATH); } else { data->module_name[0] = 0; } ntStatus = STATUS_SUCCESS; break; } }
BOOLEAN InjectDll(PINJECT_INFO InjectInfo) { PEPROCESS Process; PETHREAD Thread; PKINJECT mem; ULONG size; PKAPC_STATE ApcState; PKAPC apc; PVOID buffer; PSYSTEM_PROCESS_INFO pSpi; LARGE_INTEGER delay; buffer=ExAllocatePool(NonPagedPool,1024*1024); // Allocate memory for the system information if(!buffer) { DbgPrint("Error: Unable to allocate memory for the process thread list."); return FALSE; } // Get the process thread list if(!NT_SUCCESS(ZwQuerySystemInformation(5,buffer,1024*1024,NULL))) { DbgPrint("Error: Unable to query process thread list."); ExFreePool(buffer); return FALSE; } pSpi=(PSYSTEM_PROCESS_INFO)buffer; // Find a target thread while(pSpi->NextEntryOffset) { if(pSpi->UniqueProcessId==InjectInfo->ProcessId) { DbgPrint("Target thread found. TID: %d",pSpi->Threads[0].ClientId.UniqueThread); break; } pSpi=(PSYSTEM_PROCESS_INFO)((PUCHAR)pSpi+pSpi->NextEntryOffset); } // Reference the target process if(!NT_SUCCESS(PsLookupProcessByProcessId(InjectInfo->ProcessId,&Process))) { DbgPrint("Error: Unable to reference the target process."); ExFreePool(buffer); return FALSE; } DbgPrint("Process name: %s",PsGetProcessImageFileName(Process)); DbgPrint("EPROCESS address: %#x",Process); // Reference the target thread if(!NT_SUCCESS(PsLookupThreadByThreadId(pSpi->Threads[0].ClientId.UniqueThread,&Thread))) { DbgPrint("Error: Unable to reference the target thread."); ObDereferenceObject(Process); // Dereference the target process ExFreePool(buffer); // Free the allocated memory return FALSE; } DbgPrint("ETHREAD address: %#x",Thread); ExFreePool(buffer); // Free the allocated memory KeAttachProcess(Process); // Attach to target process's address space mem=NULL; size=4096; // Allocate memory in the target process if(!NT_SUCCESS(ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,0,&size,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE))) { DbgPrint("Error: Unable to allocate memory in the target process."); KeDetachProcess(); // Detach from target process's address space ObDereferenceObject(Process); // Dereference the target process ObDereferenceObject(Thread); // Dereference the target thread return FALSE; } DbgPrint("Memory allocated at %#x",mem); mem->LdrLoadDll=LdrLoadDll; // Write the address of LdrLoadDll to target process wcscpy(mem->Buffer,InjectInfo->DllName); // Write the DLL name to target process RtlInitUnicodeString(&mem->DllName,mem->Buffer); // Initialize the UNICODE_STRING structure ApcState=(PKAPC_STATE)((PUCHAR)Thread+ApcStateOffset); // Calculate the address of the ApcState structure ApcState->UserApcPending=TRUE; // Force the target thread to execute APC memcpy((PKINJECT)(mem+1),InjectDllApc,(ULONG)KernelRoutine-(ULONG)InjectDllApc); // Copy the APC code to target process DbgPrint("APC code address: %#x",(PKINJECT)(mem+1)); apc=(PKAPC)ExAllocatePool(NonPagedPool,sizeof(KAPC)); // Allocate the APC object if(!apc) { DbgPrint("Error: Unable to allocate the APC object."); size=0; ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); // Free the allocated memory KeDetachProcess(); // Detach from target process's address space ObDereferenceObject(Process); // Dereference the target process ObDereferenceObject(Thread); // Dereference the target thread return FALSE; } KeInitializeApc(apc,Thread,OriginalApcEnvironment,KernelRoutine,NULL,(PKNORMAL_ROUTINE)((PKINJECT)mem+1),UserMode,mem); // Initialize the APC DbgPrint("Inserting APC to target thread"); // Insert the APC to the target thread if(!KeInsertQueueApc(apc,NULL,NULL,IO_NO_INCREMENT)) { DbgPrint("Error: Unable to insert APC to target thread."); size=0; ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); // Free the allocated memory KeDetachProcess(); // Detach from target process's address space ObDereferenceObject(Process); // Dereference the target process ObDereferenceObject(Thread); // Dereference the target thread ExFreePool(apc); // Free the APC object return FALSE; } delay.QuadPart=-100*10000; while(!mem->Executed) { KeDelayExecutionThread(KernelMode,FALSE,&delay); // Wait for the injection to complete } if(!mem->DllBase) { DbgPrint("Error: Unable to inject DLL into target process."); size=0; ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); KeDetachProcess(); ObDereferenceObject(Process); ObDereferenceObject(Thread); return FALSE; } DbgPrint("DLL injected at %#x",mem->DllBase); size=0; ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); // Free the allocated memory KeDetachProcess(); // Detach from target process's address space ObDereferenceObject(Process); // Dereference the target process ObDereferenceObject(Thread); // Dereference the target thread return TRUE; }
BOOLEAN InjectDll(PINJECT_INFO InjectInfo) { PEPROCESS Process; PETHREAD Thread; PKINJECT mem; ULONG size; PKAPC_STATE ApcState; PKAPC apc; PVOID buffer; PSYSTEM_PROCESS_INFO pSpi; LARGE_INTEGER delay; buffer=ExAllocatePool(NonPagedPool,1024*1024); if(!buffer) { DbgPrint("Error: Unable to allocate memory for the process thread list."); return FALSE; } //5 SystemProcessInformation, if(!NT_SUCCESS(ZwQuerySystemInformation(5,buffer,1024*1024,NULL))) { DbgPrint("Error: Unable to query process thread list."); ExFreePool(buffer); return FALSE; } pSpi=(PSYSTEM_PROCESS_INFO)buffer; //找到目标进程 while(pSpi->NextEntryOffset) { if(pSpi->UniqueProcessId==InjectInfo->ProcessId) { DbgPrint("Target thread found. TID: %d",pSpi->Threads[0].ClientId.UniqueThread); break; } pSpi=(PSYSTEM_PROCESS_INFO)((PUCHAR)pSpi+pSpi->NextEntryOffset); } // 引用目标进程EProcess, if(!NT_SUCCESS(PsLookupProcessByProcessId(InjectInfo->ProcessId,&Process))) { DbgPrint("Error: Unable to reference the target process."); ExFreePool(buffer); return FALSE; } DbgPrint("Process name: %s",PsGetProcessImageFileName(Process)); DbgPrint("EPROCESS address: %#x",Process); //目标进程主线程 if(!NT_SUCCESS(PsLookupThreadByThreadId(pSpi->Threads[0].ClientId.UniqueThread,&Thread))) { DbgPrint("Error: Unable to reference the target thread."); ObDereferenceObject(Process); ExFreePool(buffer); return FALSE; } DbgPrint("ETHREAD address: %#x",Thread); ExFreePool(buffer); //切入到目标进程 KeAttachProcess(Process); mem=NULL; size=4096; //在目标进程申请内存 if(!NT_SUCCESS(ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,0,&size,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE))) { DbgPrint("Error: Unable to allocate memory in the target process."); KeDetachProcess(); ObDereferenceObject(Process); ObDereferenceObject(Thread); return FALSE; } DbgPrint("Memory allocated at %#x",mem); mem->LdrLoadDll=LdrLoadDll; wcscpy(mem->Buffer,InjectInfo->DllName); RtlInitUnicodeString(&mem->DllName,mem->Buffer); ApcState=(PKAPC_STATE)((PUCHAR)Thread+ApcStateOffset); ApcState->UserApcPending=TRUE; memcpy((PKINJECT)(mem+1),InjectDllApc,(ULONG)KernelRoutine-(ULONG)InjectDllApc); DbgPrint("APC code address: %#x",(PKINJECT)(mem+1)); //申请apc对象 apc=(PKAPC)ExAllocatePool(NonPagedPool,sizeof(KAPC)); if(!apc) { DbgPrint("Error: Unable to allocate the APC object."); size=0; ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); KeDetachProcess(); ObDereferenceObject(Process); ObDereferenceObject(Thread); return FALSE; } KeInitializeApc(apc, Thread, //目标进程主线程 OriginalApcEnvironment, //目标apcz状态 KernelRoutine, //内核apc总入口 NULL, //Rundown Rounine=NULL (PKNORMAL_ROUTINE)((PKINJECT)mem+1), //用户空间的总apc UserMode, //插入到用户apc队列 mem); // 自己的apc队列 DbgPrint("Inserting APC to target thread"); // 插入apc队列 if(!KeInsertQueueApc(apc,NULL,NULL,IO_NO_INCREMENT)) { DbgPrint("Error: Unable to insert APC to target thread."); size=0; ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); KeDetachProcess(); ObDereferenceObject(Process); ObDereferenceObject(Thread); ExFreePool(apc); return FALSE; } delay.QuadPart=-100*10000; while(!mem->Executed) { KeDelayExecutionThread(KernelMode,FALSE,&delay); //等待apc执行 } if(!mem->DllBase) { DbgPrint("Error: Unable to inject DLL into target process."); size=0; ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); KeDetachProcess(); ObDereferenceObject(Process); ObDereferenceObject(Thread); return FALSE; } DbgPrint("DLL injected at %#x",mem->DllBase); size=0; ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); ObDereferenceObject(Process); ObDereferenceObject(Thread); return TRUE; }
NTSTATUS RequestApc( HANDLE ProcessId, PVOID ShellcodeBase, PVOID ContextData ) { NTSTATUS Status; PKAPC UserApc = NULL; PKAPC KernelApc = NULL; HANDLE ThreadId = NULL; PKTHREAD ThreadObject = NULL; ThreadId = GetThreadForProcess ( ProcessId ); if ( ! ThreadId ) { DPF(("%s!%s GetThreadForProcess() FAIL\n", __MODULE__, __FUNCTION__ )); Status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } // get the ETHREAD/KTHREAD for ThreadId Status = PsLookupThreadByThreadId ( ThreadId, &ThreadObject ); if ( ! NT_SUCCESS( Status ) ) { DPF(("%s!%s PsLookupThreadByThreadId(%p) FAIL=%08x\n", __MODULE__, __FUNCTION__, ThreadId, Status )); goto Exit; } // allocate memory for the user mode APC object UserApc = ExAllocatePoolWithTag ( NonPagedPool, sizeof (KAPC), 'auMC' ); if ( ! UserApc ) { DPF(("%s!%s ExAllocatePoolWithTag(UserApc) FAIL=%08x\n", __MODULE__, __FUNCTION__ )); Status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } // allocate memory for the kernel mode APC KernelApc = ExAllocatePoolWithTag ( NonPagedPool, sizeof (KAPC), 'akMC' ); if ( ! KernelApc ) { DPF(("%s!%s ExAllocatePoolWithTag(KernelApc) FAIL=%08x\n", __MODULE__, __FUNCTION__ )); Status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } // initialize the user mode APC obect with the // APC routines UserApcKernelRoutine and UserApcNormalRoutine KeInitializeApc ( UserApc, ThreadObject, OriginalApcEnvironment, (PKKERNEL_ROUTINE)UserApcKernelRoutine, (PKRUNDOWN_ROUTINE)NULL, (PKNORMAL_ROUTINE)ShellcodeBase, // user routine UserApcNormalRoutine() UserMode, ContextData ); // queue the user mode APC // note that this APC will not be delivered until the thread is alerted // when the kernel mode APC calls KeTestAlertThread() KeInsertQueueApc( UserApc, NULL, NULL, IO_NO_INCREMENT ); // initialize the kernel mode APC obect with the // APC routines KernelApcKernelRoutine and KernelApcNormalRoutine KeInitializeApc ( KernelApc, ThreadObject, OriginalApcEnvironment, (PKKERNEL_ROUTINE)KernelApcKernelRoutine, (PKRUNDOWN_ROUTINE)NULL, (PKNORMAL_ROUTINE)KernelApcNormalRoutine, KernelMode, NULL ); // queue the kernel mode APC which will alert the target thread KeInsertQueueApc( KernelApc, NULL, NULL, IO_NO_INCREMENT ); Exit : if ( ThreadObject ) { ObDereferenceObject ( ThreadObject ); } if ( ! NT_SUCCESS ( Status ) ) { if ( UserApc ) { ExFreePool ( UserApc ); } if ( KernelApc ) { ExFreePool ( KernelApc ); } } return Status; } // RequestApc()
PETHREAD GetThreadObjectByThreadId(HANDLE ThreadID) { PETHREAD Thread; return NT_SUCCESS(PsLookupThreadByThreadId(ThreadID, &Thread)) ? Thread : NULL; }
HWINEVENTHOOK APIENTRY NtUserSetWinEventHook( UINT eventMin, UINT eventMax, HMODULE hmodWinEventProc, PUNICODE_STRING puString, WINEVENTPROC lpfnWinEventProc, DWORD idProcess, DWORD idThread, UINT dwflags) { PEVENTHOOK pEH; HWINEVENTHOOK Ret = NULL; NTSTATUS Status; HANDLE Handle; PETHREAD Thread = NULL; TRACE("NtUserSetWinEventHook hmod 0x%x, pfn 0x%x\n",hmodWinEventProc, lpfnWinEventProc); UserEnterExclusive(); if ( !GlobalEvents ) { GlobalEvents = ExAllocatePoolWithTag(PagedPool, sizeof(EVENTTABLE), TAG_HOOK); if (GlobalEvents == NULL) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); goto SetEventExit; } GlobalEvents->Counts = 0; InitializeListHead(&GlobalEvents->Events); } if (eventMin > eventMax) { EngSetLastError(ERROR_INVALID_HOOK_FILTER); goto SetEventExit; } if (!lpfnWinEventProc) { EngSetLastError(ERROR_INVALID_FILTER_PROC); goto SetEventExit; } if ((dwflags & WINEVENT_INCONTEXT) && !hmodWinEventProc) { EngSetLastError(ERROR_HOOK_NEEDS_HMOD); goto SetEventExit; } if (idThread) { Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)idThread, &Thread); if (!NT_SUCCESS(Status)) { EngSetLastError(ERROR_INVALID_THREAD_ID); goto SetEventExit; } } // Creator, pti is set here. pEH = UserCreateObject(gHandleTable, NULL, &Handle, otEvent, sizeof(EVENTHOOK)); if (pEH) { InsertTailList(&GlobalEvents->Events, &pEH->Chain); GlobalEvents->Counts++; UserHMGetHandle(pEH) = Handle; pEH->eventMin = eventMin; pEH->eventMax = eventMax; pEH->idProcess = idProcess; // These are cmp'ed pEH->idThread = idThread; // " pEH->Flags = dwflags; /* If WINEVENT_INCONTEXT, set offset from hmod and proc. Save ihmod from the atom index table where the hmod data is saved to be recalled later if fSync set by WINEVENT_INCONTEXT. If WINEVENT_OUTOFCONTEXT just use proc.. Do this instead.... */ if (NULL != hmodWinEventProc) { pEH->offPfn = (ULONG_PTR)((char *)lpfnWinEventProc - (char *)hmodWinEventProc); pEH->ihmod = (INT)hmodWinEventProc; pEH->Proc = lpfnWinEventProc; } else pEH->Proc = lpfnWinEventProc; UserDereferenceObject(pEH); Ret = Handle; IntSetSrvEventMask( eventMin, eventMax); } SetEventExit: if (Thread) ObDereferenceObject(Thread); UserLeave(); return Ret; }