1 #include "stdafx.h" 2 #include <iostream> 3 #include <Windows.h> 4 #include <WinIoCtl.h> 5 using namespace std; 6 7 #define CTL_KEINJECTAPC \ 8 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x830, METHOD_BUFFERED, FILE_ANY_ACCESS) 9 10 typedef struct _INJECT_INFO 11 { 12 ULONG ProcessId; 13 wchar_t DllName[1024]; 14 }INJECT_INFO, *PINJECT_INFO; 15 16 int _tmain(int argc, _TCHAR* argv[]) 17 { 18 HANDLE hFile; 19 INJECT_INFO InjectInfo; 20 hFile = CreateFile(L"\\\\.\\DriverLink", 21 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 22 NULL, OPEN_EXISTING, 0, NULL); 23 24 if (hFile == INVALID_HANDLE_VALUE) 25 { 26 printf("\nError: Unable to connect to the driver (%d)\n", GetLastError()); 27 return -1; 28 } 29 memset(&InjectInfo, 0, sizeof(INJECT_INFO)); 30 scanf("%d", &(InjectInfo.ProcessId)); 31 wscanf(L"%s", InjectInfo.DllName); 32 DWORD dwReturnSize = 0; 33 DWORD dwRet = 0; 34 dwRet = DeviceIoControl(hFile, CTL_KEINJECTAPC, // 35 &InjectInfo, 36 sizeof(INJECT_INFO), 37 NULL, 38 NULL, 39 &dwReturnSize, 40 NULL); 41 42 CloseHandle(hFile); 43 return 0; 44 } 45 46 #include <ntifs.h> 47 #include <devioctl.h> 48 #include <ntimage.h> 49 50 #endif 51 52 #define DEVICE_NAME L"\\Device\\DriverDevice" 53 #define LINK_NAME L"\\DosDevices\\DriverLink" 54 55 #define CTL_KEINJECTAPC \ 56 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x830, METHOD_BUFFERED, FILE_ANY_ACCESS) 57 58 typedef struct _SYSTEM_THREAD_INFORMATION 59 { 60 LARGE_INTEGER KernelTime; 61 LARGE_INTEGER UserTime; 62 LARGE_INTEGER CreateTime; 63 ULONG WaitTime; 64 PVOID StartAddress; 65 CLIENT_ID ClientId; 66 KPRIORITY Priority; 67 LONG BasePriority; 68 ULONG ContextSwitches; 69 ULONG ThreadState; 70 KWAIT_REASON WaitReason; 71 }SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; 72 73 typedef struct _SYSTEM_PROCESS_INFO 74 { 75 ULONG NextEntryOffset; 76 ULONG NumberOfThreads; 77 LARGE_INTEGER WorkingSetPrivateSize; 78 ULONG HardFaultCount; 79 ULONG NumberOfThreadsHighWatermark; 80 ULONGLONG CycleTime; 81 LARGE_INTEGER CreateTime; 82 LARGE_INTEGER UserTime; 83 LARGE_INTEGER KernelTime; 84 UNICODE_STRING ImageName; 85 KPRIORITY BasePriority; 86 HANDLE UniqueProcessId; 87 HANDLE InheritedFromUniqueProcessId; 88 ULONG HandleCount; 89 ULONG SessionId; 90 ULONG_PTR UniqueProcessKey; 91 SIZE_T PeakVirtualSize; 92 SIZE_T VirtualSize; 93 ULONG PageFaultCount; 94 SIZE_T PeakWorkingSetSize; 95 SIZE_T WorkingSetSize; 96 SIZE_T QuotaPeakPagedPoolUsage; 97 SIZE_T QuotaPagedPoolUsage; 98 SIZE_T QuotaPeakNonPagedPoolUsage; 99 SIZE_T QuotaNonPagedPoolUsage; 100 SIZE_T PagefileUsage; 101 SIZE_T PeakPagefileUsage; 102 SIZE_T PrivatePageCount; 103 LARGE_INTEGER ReadOperationCount; 104 LARGE_INTEGER WriteOperationCount; 105 LARGE_INTEGER OtherOperationCount; 106 LARGE_INTEGER ReadTransferCount; 107 LARGE_INTEGER WriteTransferCount; 108 LARGE_INTEGER OtherTransferCount; 109 SYSTEM_THREAD_INFORMATION Threads[1]; 110 }SYSTEM_PROCESS_INFO, *PSYSTEM_PROCESS_INFO; 111 112 typedef struct _LDR_DATA_TABLE_ENTRY 113 { 114 LIST_ENTRY InLoadOrderLinks; 115 LIST_ENTRY InMemoryOrderLinks; 116 LIST_ENTRY InInitializationOrderLinks; 117 PVOID DllBase; 118 PVOID EntryPoint; 119 ULONG SizeOfImage; 120 UNICODE_STRING FullDllName; 121 UNICODE_STRING BaseDllName; 122 ULONG Flags; 123 USHORT LoadCount; 124 USHORT TlsIndex; 125 126 union 127 { 128 LIST_ENTRY HashLinks; 129 struct 130 { 131 PVOID SectionPointer; 132 ULONG CheckSum; 133 }; 134 }; 135 136 union 137 { 138 ULONG TimeDateStamp; 139 PVOID LoadedImports; 140 }; 141 142 struct _ACTIVATION_CONTEXT * EntryPointActivationContext; 143 PVOID PatchInformation; 144 LIST_ENTRY ForwarderLinks; 145 LIST_ENTRY ServiceTagLinks; 146 LIST_ENTRY StaticLinks; 147 }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 148 149 typedef struct _INJECT_INFO 150 { 151 ULONG ProcessId; 152 wchar_t DllName[1024]; 153 }INJECT_INFO, *PINJECT_INFO; 154 155 typedef NTSTATUS(*PLDR_LOAD_DLL)(PWSTR, PULONG, PUNICODE_STRING, PVOID*); 156 157 typedef struct _KINJECT 158 { 159 UNICODE_STRING DllName; 160 wchar_t Buffer[1024]; 161 PLDR_LOAD_DLL LdrLoadDll; 162 PVOID DllBase; 163 ULONG Executed; 164 }KINJECT, *PKINJECT; 165 166 typedef enum _KAPC_ENVIRONMENT 167 { 168 OriginalApcEnvironment, 169 AttachedApcEnvironment, 170 CurrentApcEnvironment, 171 InsertApcEnvironment 172 }KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT; 173 174 typedef VOID(NTAPI *PKNORMAL_ROUTINE)( 175 PVOID NormalContext, 176 PVOID SystemArgument1, 177 PVOID SystemArgument2 178 ); 179 180 typedef VOID KKERNEL_ROUTINE( 181 PRKAPC Apc, 182 PKNORMAL_ROUTINE *NormalRoutine, 183 PVOID *NormalContext, 184 PVOID *SystemArgument1, 185 PVOID *SystemArgument2 186 ); 187 188 typedef KKERNEL_ROUTINE(NTAPI *PKKERNEL_ROUTINE); 189 190 typedef VOID(NTAPI *PKRUNDOWN_ROUTINE)( 191 PRKAPC Apc 192 ); 193 194 void KeInitializeApc( 195 PRKAPC Apc, 196 PRKTHREAD Thread, 197 KAPC_ENVIRONMENT Environment, 198 PKKERNEL_ROUTINE KernelRoutine, 199 PKRUNDOWN_ROUTINE RundownRoutine, 200 PKNORMAL_ROUTINE NormalRoutine, 201 KPROCESSOR_MODE ProcessorMode, 202 PVOID NormalContext 203 ); 204 205 BOOLEAN KeInsertQueueApc( 206 PRKAPC Apc, 207 PVOID SystemArgument1, 208 PVOID SystemArgument2, 209 KPRIORITY Increment 210 ); 211 212 213 NTSTATUS ZwQuerySystemInformation(ULONG InfoClass, PVOID Buffer, ULONG Length, PULONG ReturnLength); 214 LPSTR PsGetProcessImageFileName(PEPROCESS Process); 215 216 NTSTATUS DefaultPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp); 217 void UnloadDriver(PDRIVER_OBJECT DriverObject); 218 NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp); 219 220 ULONG ApcStateOffset; 221 PLDR_LOAD_DLL LdrLoadDll; 222 223 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING pRegistryPath) 224 { 225 NTSTATUS Status; 226 PDEVICE_OBJECT DeviceObject; 227 PEPROCESS Process; 228 PETHREAD Thread; 229 PKAPC_STATE ApcState; 230 PVOID KdVersionBlock, NtdllBase; 231 PULONG ptr, Functions, Names; 232 PUSHORT Ordinals; 233 PLDR_DATA_TABLE_ENTRY MmLoadedUserImageList, ModuleEntry; 234 ULONG i; 235 PIMAGE_DOS_HEADER pIDH; 236 PIMAGE_NT_HEADERS pINH; 237 PIMAGE_EXPORT_DIRECTORY pIED; 238 UNICODE_STRING uniDeviceName; 239 UNICODE_STRING uniLinkName; 240 RtlInitUnicodeString(&uniDeviceName, DEVICE_NAME); 241 RtlInitUnicodeString(&uniLinkName, LINK_NAME); 242 for (i = 0; i<IRP_MJ_MAXIMUM_FUNCTION; i++) 243 { 244 DriverObject->MajorFunction[i] = DefaultPassThrough; 245 } 246 DriverObject->DriverUnload = UnloadDriver; 247 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverDispatch; 248 //创建设备对象 249 Status = IoCreateDevice(DriverObject, 0, &uniDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); 250 if (!NT_SUCCESS(Status)) 251 { 252 return Status; 253 } 254 Status = IoCreateSymbolicLink(&uniLinkName, &uniDeviceName); 255 if (!NT_SUCCESS(Status)) 256 { 257 IoDeleteDevice(DeviceObject); 258 return Status; 259 } 260 261 //使当前线程运行在第一个处理器上 262 KeSetSystemAffinityThread(1); 263 KdVersionBlock = (PVOID)__readfsdword(0x34); //得到KdVersionBlock 264 KeRevertToUserAffinityThread();//恢复线程运行的处理器 265 MmLoadedUserImageList = *(PLDR_DATA_TABLE_ENTRY*)((PUCHAR)KdVersionBlock + 0x228); // Get the MmLoadUserImageList 266 267 /* 268 kd> !pcr 269 KPCR for Processor 0 at 83f3ec00: 270 271 kd> dt _kpcr 83f3ec00 272 +0x034 KdVersionBlock : 0x83f3dc00 Void 273 274 kd> dd 0x83f3dc00+0x228 275 83f3de28 83f5de38 00000000 83e5dfa8 00000000 276 83f3de38 00000000 00000000 83f7d8c0 00000000 277 83f3de48 83f7d560 00000000 83f5d84c 00000000 278 279 kd> dd 83f5de38 280 83f5de38 8706b1e8 877cb660 00000000 00000000 281 83f5de48 00000000 00000000 00040107 00000000 282 83f5de58 865d0690 865d0690 c0403188 0007ff7e 283 284 kd> dt _LDR_DATA_TABLE_ENTRY 8706b1e8 285 nt!_LDR_DATA_TABLE_ENTRY 286 +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x8713b4e0 - 0x83f5de38 ] 287 +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ] 288 +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ] 289 +0x018 DllBase : 0x77ce0000 Void 290 +0x01c EntryPoint : (null) 291 +0x020 SizeOfImage : 0x13c000 292 +0x024 FullDllName : _UNICODE_STRING "\Windows\System32\ntdll.dll" 293 +0x02c BaseDllName : _UNICODE_STRING "" 294 +0x034 Flags : 0 295 +0x038 LoadCount : 1 296 +0x03a TlsIndex : 0 297 +0x03c HashLinks : _LIST_ENTRY [ 0x0 - 0x1490d9 ] 298 +0x03c SectionPointer : (null) 299 +0x040 CheckSum : 0x1490d9 300 +0x044 TimeDateStamp : 0 301 +0x044 LoadedImports : (null) 302 +0x048 EntryPointActivationContext : (null) 303 +0x04c PatchInformation : (null) 304 +0x050 ForwarderLinks : _LIST_ENTRY [ 0x0 - 0x0 ] 305 +0x058 ServiceTagLinks : _LIST_ENTRY [ 0x0 - 0x57005c ] 306 +0x060 StaticLinks : _LIST_ENTRY [ 0x6e0069 - 0x6f0064 ] 307 +0x068 ContextInformation : 0x00730077 Void 308 +0x06c OriginalBase : 0x53005c 309 +0x070 LoadTime : _LARGE_INTEGER 0x650074`00730079 310 */ 311 DbgPrint("KdVersionBlock address: %#x", KdVersionBlock); 312 DbgPrint("MmLoadedUserImageList address: %#x", MmLoadedUserImageList); 313 314 ModuleEntry = (PLDR_DATA_TABLE_ENTRY)MmLoadedUserImageList->InLoadOrderLinks.Flink; //第一模块 315 NtdllBase = ModuleEntry->DllBase; //ntdll基地址 316 317 DbgPrint("ntdll base address: %#x", NtdllBase); 318 319 pIDH = (PIMAGE_DOS_HEADER)NtdllBase; 320 pINH = (PIMAGE_NT_HEADERS)((PUCHAR)NtdllBase + pIDH->e_lfanew); 321 pIED = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)NtdllBase + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 322 323 Functions = (PULONG)((PUCHAR)NtdllBase + pIED->AddressOfFunctions); 324 Names = (PULONG)((PUCHAR)NtdllBase + pIED->AddressOfNames); 325 326 Ordinals = (PUSHORT)((PUCHAR)NtdllBase + pIED->AddressOfNameOrdinals); 327 328 //搜索LdrLoadDll 329 for (i = 0; i<pIED->NumberOfNames; i++) 330 { 331 if (!strcmp((char*)NtdllBase + Names[i], "LdrLoadDll")) 332 { 333 LdrLoadDll = (PLDR_LOAD_DLL)((PUCHAR)NtdllBase + Functions[Ordinals[i]]); 334 break; 335 } 336 } 337 338 DbgPrint("LdrLoadDll address: %#x", LdrLoadDll); 339 Process = PsGetCurrentProcess(); 340 Thread = PsGetCurrentThread(); 341 ptr = (PULONG)Thread; 342 //确定ApcState在EThread中的偏移 343 for (i = 0; i<512; i++) 344 { 345 if (ptr[i] == (ULONG)Process) 346 { 347 ApcState = CONTAINING_RECORD(&ptr[i], KAPC_STATE, Process); 348 ApcStateOffset = (ULONG)ApcState - (ULONG)Thread; 349 break; 350 } 351 } 352 DbgPrint("ApcState offset: %#x", ApcStateOffset); 353 DbgPrint("DLL injection driver loaded."); 354 return STATUS_SUCCESS; 355 } 356 357 NTSTATUS DefaultPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp) 358 { 359 Irp->IoStatus.Information = 0; 360 Irp->IoStatus.Status = STATUS_SUCCESS; 361 IoCompleteRequest(Irp, IO_NO_INCREMENT); 362 return STATUS_SUCCESS; 363 } 364 365 void UnloadDriver(PDRIVER_OBJECT DriverObject) 366 { 367 UNICODE_STRING uniLinkName; 368 PDEVICE_OBJECT CurrentDeviceObject; 369 PDEVICE_OBJECT NextDeviceObject; 370 RtlInitUnicodeString(&uniLinkName, LINK_NAME); 371 IoDeleteSymbolicLink(&uniLinkName); 372 if (DriverObject->DeviceObject != NULL) 373 { 374 CurrentDeviceObject = DriverObject->DeviceObject; 375 while (CurrentDeviceObject != NULL) 376 { 377 NextDeviceObject = CurrentDeviceObject->NextDevice; 378 IoDeleteDevice(CurrentDeviceObject); 379 CurrentDeviceObject = NextDeviceObject; 380 } 381 } 382 DbgPrint("UnloadDriver\r\n"); 383 } 384 385 void NTAPI InjectDllApc(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2) 386 { 387 PKINJECT inject = (PKINJECT)NormalContext; 388 inject->LdrLoadDll(NULL, NULL, &inject->DllName, &inject->DllBase); 389 inject->Executed = TRUE; 390 } 391 392 void NTAPI KernelRoutine(PKAPC apc, PKNORMAL_ROUTINE* NormalRoutine, PVOID* NormalContext, \ 393 PVOID* SystemArgument1, PVOID* SystemArgument2) 394 { 395 ExFreePool(apc); 396 } 397 398 BOOLEAN InjectDll(PINJECT_INFO InjectInfo) 399 { 400 PEPROCESS Process; 401 PETHREAD Thread; 402 PKINJECT mem; 403 ULONG size; 404 PKAPC_STATE ApcState; 405 PKAPC apc; 406 PVOID buffer; 407 PSYSTEM_PROCESS_INFO pSpi; 408 LARGE_INTEGER delay; 409 buffer = ExAllocatePool(NonPagedPool, 1024 * 1024); 410 if (!buffer) 411 { 412 DbgPrint("Error: Unable to allocate memory for the process thread list."); 413 return FALSE; 414 } 415 416 //5 SystemProcessInformation, 417 if (!NT_SUCCESS(ZwQuerySystemInformation(5, buffer, 1024 * 1024, NULL))) 418 { 419 DbgPrint("Error: Unable to query process thread list."); 420 ExFreePool(buffer); 421 return FALSE; 422 } 423 424 pSpi = (PSYSTEM_PROCESS_INFO)buffer; 425 426 //找到目标进程 427 while (pSpi->NextEntryOffset) 428 { 429 if (pSpi->UniqueProcessId == InjectInfo->ProcessId) 430 { 431 DbgPrint("Target thread found. TID: %d", pSpi->Threads[0].ClientId.UniqueThread); 432 break; 433 } 434 pSpi = (PSYSTEM_PROCESS_INFO)((PUCHAR)pSpi + pSpi->NextEntryOffset); 435 } 436 437 // 引用目标进程EProcess, 438 if (!NT_SUCCESS(PsLookupProcessByProcessId(InjectInfo->ProcessId, &Process))) 439 { 440 DbgPrint("Error: Unable to reference the target process."); 441 ExFreePool(buffer); 442 return FALSE; 443 } 444 445 DbgPrint("Process name: %s", PsGetProcessImageFileName(Process)); 446 DbgPrint("EPROCESS address: %#x", Process); 447 448 //目标进程主线程 449 if (!NT_SUCCESS(PsLookupThreadByThreadId(pSpi->Threads[0].ClientId.UniqueThread, &Thread))) 450 { 451 DbgPrint("Error: Unable to reference the target thread."); 452 ObDereferenceObject(Process); 453 ExFreePool(buffer); 454 return FALSE; 455 } 456 457 DbgPrint("ETHREAD address: %#x", Thread); 458 459 ExFreePool(buffer); 460 //切入到目标进程 461 KeAttachProcess(Process); 462 463 mem = NULL; 464 size = 4096; 465 466 //在目标进程申请内存 467 if (!NT_SUCCESS(ZwAllocateVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE))) 468 { 469 DbgPrint("Error: Unable to allocate memory in the target process."); 470 KeDetachProcess(); 471 ObDereferenceObject(Process); 472 ObDereferenceObject(Thread); 473 return FALSE; 474 } 475 476 DbgPrint("Memory allocated at %#x", mem); 477 mem->LdrLoadDll = LdrLoadDll; 478 wcscpy(mem->Buffer, InjectInfo->DllName); 479 RtlInitUnicodeString(&mem->DllName, mem->Buffer); 480 ApcState = (PKAPC_STATE)((PUCHAR)Thread + ApcStateOffset); 481 ApcState->UserApcPending = TRUE; 482 memcpy((PKINJECT)(mem + 1), InjectDllApc, (ULONG)KernelRoutine - (ULONG)InjectDllApc); 483 DbgPrint("APC code address: %#x", (PKINJECT)(mem + 1)); 484 485 //申请apc对象 486 apc = (PKAPC)ExAllocatePool(NonPagedPool, sizeof(KAPC)); 487 488 if (!apc) 489 { 490 DbgPrint("Error: Unable to allocate the APC object."); 491 size = 0; 492 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, &size, MEM_RELEASE); 493 KeDetachProcess(); 494 ObDereferenceObject(Process); 495 ObDereferenceObject(Thread); 496 return FALSE; 497 } 498 499 KeInitializeApc(apc, 500 Thread, //目标进程主线程 501 OriginalApcEnvironment, //目标apcz状态 502 KernelRoutine, //内核apc总入口 503 NULL, //Rundown Rounine=NULL 504 (PKNORMAL_ROUTINE)((PKINJECT)mem + 1), //用户空间的总apc 505 UserMode, //插入到用户apc队列 506 mem); // 自己的apc队列 507 508 DbgPrint("Inserting APC to target thread"); 509 510 // 插入apc队列 511 if (!KeInsertQueueApc(apc, NULL, NULL, IO_NO_INCREMENT)) 512 { 513 DbgPrint("Error: Unable to insert APC to target thread."); 514 size = 0; 515 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, &size, MEM_RELEASE); 516 KeDetachProcess(); 517 ObDereferenceObject(Process); 518 ObDereferenceObject(Thread); 519 ExFreePool(apc); 520 return FALSE; 521 } 522 523 delay.QuadPart = -100 * 10000; 524 while (!mem->Executed) 525 { 526 KeDelayExecutionThread(KernelMode, FALSE, &delay); //等待apc执行 527 } 528 if (!mem->DllBase) 529 { 530 DbgPrint("Error: Unable to inject DLL into target process."); 531 size = 0; 532 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, &size, MEM_RELEASE); 533 KeDetachProcess(); 534 ObDereferenceObject(Process); 535 ObDereferenceObject(Thread); 536 return FALSE; 537 } 538 539 DbgPrint("DLL injected at %#x", mem->DllBase); 540 size = 0; 541 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, &size, MEM_RELEASE); 542 ObDereferenceObject(Process); 543 ObDereferenceObject(Thread); 544 return TRUE; 545 } 546 547 NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) 548 { 549 PIO_STACK_LOCATION io; 550 PINJECT_INFO InjectInfo; 551 NTSTATUS Status = STATUS_SUCCESS; 552 PIO_STACK_LOCATION IrpSp; 553 PVOID InputBuffer = NULL; 554 PVOID OutputBuffer = NULL; 555 ULONG_PTR InputSize = 0; 556 ULONG_PTR OutputSize = 0; 557 ULONG_PTR IoControlCode = 0; 558 559 IrpSp = IoGetCurrentIrpStackLocation(Irp); 560 InputBuffer = OutputBuffer = Irp->AssociatedIrp.SystemBuffer; 561 InputSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; 562 OutputSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; 563 IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode; 564 565 switch (IoControlCode) 566 { 567 case CTL_KEINJECTAPC: 568 569 InjectInfo = (PINJECT_INFO)InputBuffer; 570 571 if (!InjectInfo) 572 { 573 Status = STATUS_INSUFFICIENT_RESOURCES; 574 break; 575 } 576 577 if (!InjectDll(InjectInfo)) 578 { 579 Status = STATUS_UNSUCCESSFUL; 580 break; 581 } 582 Status = STATUS_SUCCESS; 583 Irp->IoStatus.Information = 0; 584 break; 585 default: 586 Status = STATUS_INVALID_DEVICE_REQUEST; 587 break; 588 } 589 Irp->IoStatus.Status = Status; 590 IoCompleteRequest(Irp, IO_NO_INCREMENT); 591 return Status; 592 }