Inject DLL from kernel mode

超、凢脫俗 2022-08-04 13:34 276阅读 0赞

How kernel mode injection works?

1) Get the address of KdVersionBlock from KPCR. (__readfsdword)

2) Get the address of MmLoadedUserImageList from KdVersionBlock.

3) Get the base address of ntdll from MmLoadedUserImageList.

4) Parse the export table of ntdll to locate LdrLoadDll.

5) Find a thread to hijack. (ZwQuerySystemInformation)

6) Open the target process. (PsLookupProcessByProcessId)

7) Open the target thread. (PsLookupThreadByThreadId)

8) Attach to target process’s address space. (KeAttachProcess)

8) Allocate memory in target process’s address space. (ZwAllocateVirtualMemory)

9) Copy the DLL name and APC routine into target process’s address space. (memcpy,RtlInitUnicodeString)

10) Set ApcState.UserApcPending to TRUE to force the target thread to execute the APC routine.

11) Allocate an APC object from nonpaged pool. (ExAllocatePool)

12) Initialize the APC and insert it to the target thread. (KeInitializeApc,KeInsertQueueApc)

13) The target thread executes the APC routine in target process’s address space. The APC routine calls LdrLoadDll to load the DLL.

14) Wait for the APC routine to complete.

15) Free the allocated memory. (ZwFreeVirtualMemory,ExFreePool)

16) Detach from target process’s address space. (KeDetachProcess)

17) Dereference the target process and target thread. (ObDereferenceObject)

Usage:

To use the injector, run install.bat to install the driver, and then run kinject.exe from command prompt.

kinject [PID] [DLL name]

Source code (driver)

  1. #include <ntifs.h>
  2. #include <ntddk.h>
  3. typedef struct _SYSTEM_THREAD_INFORMATION
  4. {
  5. LARGE_INTEGER KernelTime;
  6. LARGE_INTEGER UserTime;
  7. LARGE_INTEGER CreateTime;
  8. ULONG WaitTime;
  9. PVOID StartAddress;
  10. CLIENT_ID ClientId;
  11. KPRIORITY Priority;
  12. LONG BasePriority;
  13. ULONG ContextSwitches;
  14. ULONG ThreadState;
  15. KWAIT_REASON WaitReason;
  16. }SYSTEM_THREAD_INFORMATION,*PSYSTEM_THREAD_INFORMATION;
  17. typedef struct _SYSTEM_PROCESS_INFO
  18. {
  19. ULONG NextEntryOffset;
  20. ULONG NumberOfThreads;
  21. LARGE_INTEGER WorkingSetPrivateSize;
  22. ULONG HardFaultCount;
  23. ULONG NumberOfThreadsHighWatermark;
  24. ULONGLONG CycleTime;
  25. LARGE_INTEGER CreateTime;
  26. LARGE_INTEGER UserTime;
  27. LARGE_INTEGER KernelTime;
  28. UNICODE_STRING ImageName;
  29. KPRIORITY BasePriority;
  30. HANDLE UniqueProcessId;
  31. HANDLE InheritedFromUniqueProcessId;
  32. ULONG HandleCount;
  33. ULONG SessionId;
  34. ULONG_PTR UniqueProcessKey;
  35. SIZE_T PeakVirtualSize;
  36. SIZE_T VirtualSize;
  37. ULONG PageFaultCount;
  38. SIZE_T PeakWorkingSetSize;
  39. SIZE_T WorkingSetSize;
  40. SIZE_T QuotaPeakPagedPoolUsage;
  41. SIZE_T QuotaPagedPoolUsage;
  42. SIZE_T QuotaPeakNonPagedPoolUsage;
  43. SIZE_T QuotaNonPagedPoolUsage;
  44. SIZE_T PagefileUsage;
  45. SIZE_T PeakPagefileUsage;
  46. SIZE_T PrivatePageCount;
  47. LARGE_INTEGER ReadOperationCount;
  48. LARGE_INTEGER WriteOperationCount;
  49. LARGE_INTEGER OtherOperationCount;
  50. LARGE_INTEGER ReadTransferCount;
  51. LARGE_INTEGER WriteTransferCount;
  52. LARGE_INTEGER OtherTransferCount;
  53. SYSTEM_THREAD_INFORMATION Threads[1];
  54. }SYSTEM_PROCESS_INFO,*PSYSTEM_PROCESS_INFO;
  55. typedef struct _LDR_DATA_TABLE_ENTRY
  56. {
  57. LIST_ENTRY InLoadOrderLinks;
  58. LIST_ENTRY InMemoryOrderLinks;
  59. LIST_ENTRY InInitializationOrderLinks;
  60. PVOID DllBase;
  61. PVOID EntryPoint;
  62. ULONG SizeOfImage;
  63. UNICODE_STRING FullDllName;
  64. UNICODE_STRING BaseDllName;
  65. ULONG Flags;
  66. USHORT LoadCount;
  67. USHORT TlsIndex;
  68. union
  69. {
  70. LIST_ENTRY HashLinks;
  71. struct
  72. {
  73. PVOID SectionPointer;
  74. ULONG CheckSum;
  75. };
  76. };
  77. union
  78. {
  79. ULONG TimeDateStamp;
  80. PVOID LoadedImports;
  81. };
  82. struct _ACTIVATION_CONTEXT * EntryPointActivationContext;
  83. PVOID PatchInformation;
  84. LIST_ENTRY ForwarderLinks;
  85. LIST_ENTRY ServiceTagLinks;
  86. LIST_ENTRY StaticLinks;
  87. }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;
  88. typedef struct _IMAGE_DOS_HEADER
  89. {
  90. USHORT e_magic;
  91. USHORT e_cblp;
  92. USHORT e_cp;
  93. USHORT e_crlc;
  94. USHORT e_cparhdr;
  95. USHORT e_minalloc;
  96. USHORT e_maxalloc;
  97. USHORT e_ss;
  98. USHORT e_sp;
  99. USHORT e_csum;
  100. USHORT e_ip;
  101. USHORT e_cs;
  102. USHORT e_lfarlc;
  103. USHORT e_ovno;
  104. USHORT e_res[4];
  105. USHORT e_oemid;
  106. USHORT e_oeminfo;
  107. USHORT e_res2[10];
  108. LONG e_lfanew;
  109. }IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
  110. typedef struct _IMAGE_DATA_DIRECTORY
  111. {
  112. ULONG VirtualAddress;
  113. ULONG Size;
  114. }IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;
  115. typedef struct _IMAGE_FILE_HEADER
  116. {
  117. USHORT Machine;
  118. USHORT NumberOfSections;
  119. ULONG TimeDateStamp;
  120. ULONG PointerToSymbolTable;
  121. ULONG NumberOfSymbols;
  122. USHORT SizeOfOptionalHeader;
  123. USHORT Characteristics;
  124. }IMAGE_FILE_HEADER,*PIMAGE_FILE_HEADER;
  125. typedef struct _IMAGE_OPTIONAL_HEADER
  126. {
  127. USHORT Magic;
  128. UCHAR MajorLinkerVersion;
  129. UCHAR MinorLinkerVersion;
  130. ULONG SizeOfCode;
  131. ULONG SizeOfInitializedData;
  132. ULONG SizeOfUninitializedData;
  133. ULONG AddressOfEntryPoint;
  134. ULONG BaseOfCode;
  135. ULONG BaseOfData;
  136. ULONG ImageBase;
  137. ULONG SectionAlignment;
  138. ULONG FileAlignment;
  139. USHORT MajorOperatingSystemVersion;
  140. USHORT MinorOperatingSystemVersion;
  141. USHORT MajorImageVersion;
  142. USHORT MinorImageVersion;
  143. USHORT MajorSubsystemVersion;
  144. USHORT MinorSubsystemVersion;
  145. ULONG Win32VersionValue;
  146. ULONG SizeOfImage;
  147. ULONG SizeOfHeaders;
  148. ULONG CheckSum;
  149. USHORT Subsystem;
  150. USHORT DllCharacteristics;
  151. ULONG SizeOfStackReserve;
  152. ULONG SizeOfStackCommit;
  153. ULONG SizeOfHeapReserve;
  154. ULONG SizeOfHeapCommit;
  155. ULONG LoaderFlags;
  156. ULONG NumberOfRvaAndSizes;
  157. IMAGE_DATA_DIRECTORY DataDirectory[16];
  158. }IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
  159. typedef struct _IMAGE_NT_HEADERS
  160. {
  161. ULONG Signature;
  162. IMAGE_FILE_HEADER FileHeader;
  163. IMAGE_OPTIONAL_HEADER OptionalHeader;
  164. }IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;
  165. typedef struct _IMAGE_EXPORT_DIRECTORY
  166. {
  167. ULONG Characteristics;
  168. ULONG TimeDateStamp;
  169. USHORT MajorVersion;
  170. USHORT MinorVersion;
  171. ULONG Name;
  172. ULONG Base;
  173. ULONG NumberOfFunctions;
  174. ULONG NumberOfNames;
  175. ULONG AddressOfFunctions;
  176. ULONG AddressOfNames;
  177. ULONG AddressOfNameOrdinals;
  178. }IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
  179. #define IMAGE_DIRECTORY_ENTRY_EXPORT 0
  180. extern "C" NTSTATUS ZwQuerySystemInformation(ULONG InfoClass,PVOID Buffer,ULONG Length,PULONG ReturnLength);
  181. extern "C" LPSTR PsGetProcessImageFileName(PEPROCESS Process);
  182. typedef NTSTATUS (*PLDR_LOAD_DLL)(PWSTR,PULONG,PUNICODE_STRING,PVOID*);
  183. typedef struct _INJECT_INFO
  184. {
  185. HANDLE ProcessId;
  186. wchar_t DllName[1024];
  187. }INJECT_INFO,*PINJECT_INFO;
  188. typedef struct _KINJECT
  189. {
  190. UNICODE_STRING DllName;
  191. wchar_t Buffer[1024];
  192. PLDR_LOAD_DLL LdrLoadDll;
  193. PVOID DllBase;
  194. ULONG Executed;
  195. }KINJECT,*PKINJECT;
  196. typedef enum _KAPC_ENVIRONMENT
  197. {
  198. OriginalApcEnvironment,
  199. AttachedApcEnvironment,
  200. CurrentApcEnvironment,
  201. InsertApcEnvironment
  202. }KAPC_ENVIRONMENT,*PKAPC_ENVIRONMENT;
  203. typedef VOID (NTAPI *PKNORMAL_ROUTINE)(
  204. PVOID NormalContext,
  205. PVOID SystemArgument1,
  206. PVOID SystemArgument2
  207. );
  208. typedef VOID KKERNEL_ROUTINE(
  209. PRKAPC Apc,
  210. PKNORMAL_ROUTINE *NormalRoutine,
  211. PVOID *NormalContext,
  212. PVOID *SystemArgument1,
  213. PVOID *SystemArgument2
  214. );
  215. typedef KKERNEL_ROUTINE (NTAPI *PKKERNEL_ROUTINE);
  216. typedef VOID (NTAPI *PKRUNDOWN_ROUTINE)(
  217. PRKAPC Apc
  218. );
  219. extern "C" void KeInitializeApc(
  220. PRKAPC Apc,
  221. PRKTHREAD Thread,
  222. KAPC_ENVIRONMENT Environment,
  223. PKKERNEL_ROUTINE KernelRoutine,
  224. PKRUNDOWN_ROUTINE RundownRoutine,
  225. PKNORMAL_ROUTINE NormalRoutine,
  226. KPROCESSOR_MODE ProcessorMode,
  227. PVOID NormalContext
  228. );
  229. extern "C" BOOLEAN KeInsertQueueApc(
  230. PRKAPC Apc,
  231. PVOID SystemArgument1,
  232. PVOID SystemArgument2,
  233. KPRIORITY Increment
  234. );
  235. UNICODE_STRING DeviceName=RTL_CONSTANT_STRING(L"\\Device\\KeInject"),SymbolicLink=RTL_CONSTANT_STRING(L"\\DosDevices\\KeInject");
  236. ULONG ApcStateOffset; // Offset to the ApcState structure
  237. PLDR_LOAD_DLL LdrLoadDll; // LdrLoadDll address
  238. void Unload(PDRIVER_OBJECT pDriverObject)
  239. {
  240. DbgPrint("DLL injection driver unloaded.");
  241. IoDeleteSymbolicLink(&SymbolicLink);
  242. IoDeleteDevice(pDriverObject->DeviceObject);
  243. }
  244. void NTAPI KernelRoutine(PKAPC apc,PKNORMAL_ROUTINE* NormalRoutine,PVOID* NormalContext,PVOID* SystemArgument1,PVOID* SystemArgument2)
  245. {
  246. ExFreePool(apc);
  247. }
  248. void NTAPI InjectDllApc(PVOID NormalContext,PVOID SystemArgument1,PVOID SystemArgument2)
  249. {
  250. PKINJECT inject=(PKINJECT)NormalContext;
  251. inject->LdrLoadDll(NULL,NULL,&inject->DllName,&inject->DllBase);
  252. inject->Executed=TRUE;
  253. }
  254. BOOLEAN InjectDll(PINJECT_INFO InjectInfo)
  255. {
  256. PEPROCESS Process;
  257. PETHREAD Thread;
  258. PKINJECT mem;
  259. ULONG size;
  260. PKAPC_STATE ApcState;
  261. PKAPC apc;
  262. PVOID buffer;
  263. PSYSTEM_PROCESS_INFO pSpi;
  264. LARGE_INTEGER delay;
  265. buffer=ExAllocatePool(NonPagedPool,1024*1024); // Allocate memory for the system information
  266. if(!buffer)
  267. {
  268. DbgPrint("Error: Unable to allocate memory for the process thread list.");
  269. return FALSE;
  270. }
  271. // Get the process thread list
  272. if(!NT_SUCCESS(ZwQuerySystemInformation(5,buffer,1024*1024,NULL)))
  273. {
  274. DbgPrint("Error: Unable to query process thread list.");
  275. ExFreePool(buffer);
  276. return FALSE;
  277. }
  278. pSpi=(PSYSTEM_PROCESS_INFO)buffer;
  279. // Find a target thread
  280. while(pSpi->NextEntryOffset)
  281. {
  282. if(pSpi->UniqueProcessId==InjectInfo->ProcessId)
  283. {
  284. DbgPrint("Target thread found. TID: %d",pSpi->Threads[0].ClientId.UniqueThread);
  285. break;
  286. }
  287. pSpi=(PSYSTEM_PROCESS_INFO)((PUCHAR)pSpi+pSpi->NextEntryOffset);
  288. }
  289. // Reference the target process
  290. if(!NT_SUCCESS(PsLookupProcessByProcessId(InjectInfo->ProcessId,&Process)))
  291. {
  292. DbgPrint("Error: Unable to reference the target process.");
  293. ExFreePool(buffer);
  294. return FALSE;
  295. }
  296. DbgPrint("Process name: %s",PsGetProcessImageFileName(Process));
  297. DbgPrint("EPROCESS address: %#x",Process);
  298. // Reference the target thread
  299. if(!NT_SUCCESS(PsLookupThreadByThreadId(pSpi->Threads[0].ClientId.UniqueThread,&Thread)))
  300. {
  301. DbgPrint("Error: Unable to reference the target thread.");
  302. ObDereferenceObject(Process); // Dereference the target process
  303. ExFreePool(buffer); // Free the allocated memory
  304. return FALSE;
  305. }
  306. DbgPrint("ETHREAD address: %#x",Thread);
  307. ExFreePool(buffer); // Free the allocated memory
  308. KeAttachProcess(Process); // Attach to target process's address space
  309. mem=NULL;
  310. size=4096;
  311. // Allocate memory in the target process
  312. if(!NT_SUCCESS(ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,0,&size,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE)))
  313. {
  314. DbgPrint("Error: Unable to allocate memory in the target process.");
  315. KeDetachProcess(); // Detach from target process's address space
  316. ObDereferenceObject(Process); // Dereference the target process
  317. ObDereferenceObject(Thread); // Dereference the target thread
  318. return FALSE;
  319. }
  320. DbgPrint("Memory allocated at %#x",mem);
  321. mem->LdrLoadDll=LdrLoadDll; // Write the address of LdrLoadDll to target process
  322. wcscpy(mem->Buffer,InjectInfo->DllName); // Write the DLL name to target process
  323. RtlInitUnicodeString(&mem->DllName,mem->Buffer); // Initialize the UNICODE_STRING structure
  324. ApcState=(PKAPC_STATE)((PUCHAR)Thread+ApcStateOffset); // Calculate the address of the ApcState structure
  325. ApcState->UserApcPending=TRUE; // Force the target thread to execute APC
  326. memcpy((PKINJECT)(mem+1),InjectDllApc,(ULONG)KernelRoutine-(ULONG)InjectDllApc); // Copy the APC code to target process
  327. DbgPrint("APC code address: %#x",(PKINJECT)(mem+1));
  328. apc=(PKAPC)ExAllocatePool(NonPagedPool,sizeof(KAPC)); // Allocate the APC object
  329. if(!apc)
  330. {
  331. DbgPrint("Error: Unable to allocate the APC object.");
  332. size=0;
  333. ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); // Free the allocated memory
  334. KeDetachProcess(); // Detach from target process's address space
  335. ObDereferenceObject(Process); // Dereference the target process
  336. ObDereferenceObject(Thread); // Dereference the target thread
  337. return FALSE;
  338. }
  339. KeInitializeApc(apc,Thread,OriginalApcEnvironment,KernelRoutine,NULL,(PKNORMAL_ROUTINE)((PKINJECT)mem+1),UserMode,mem); // Initialize the APC
  340. DbgPrint("Inserting APC to target thread");
  341. // Insert the APC to the target thread
  342. if(!KeInsertQueueApc(apc,NULL,NULL,IO_NO_INCREMENT))
  343. {
  344. DbgPrint("Error: Unable to insert APC to target thread.");
  345. size=0;
  346. ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); // Free the allocated memory
  347. KeDetachProcess(); // Detach from target process's address space
  348. ObDereferenceObject(Process); // Dereference the target process
  349. ObDereferenceObject(Thread); // Dereference the target thread
  350. ExFreePool(apc); // Free the APC object
  351. return FALSE;
  352. }
  353. delay.QuadPart=-100*10000;
  354. while(!mem->Executed)
  355. {
  356. KeDelayExecutionThread(KernelMode,FALSE,&delay); // Wait for the injection to complete
  357. }
  358. if(!mem->DllBase)
  359. {
  360. DbgPrint("Error: Unable to inject DLL into target process.");
  361. size=0;
  362. ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE);
  363. KeDetachProcess();
  364. ObDereferenceObject(Process);
  365. ObDereferenceObject(Thread);
  366. return FALSE;
  367. }
  368. DbgPrint("DLL injected at %#x",mem->DllBase);
  369. size=0;
  370. ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); // Free the allocated memory
  371. KeDetachProcess(); // Detach from target process's address space
  372. ObDereferenceObject(Process); // Dereference the target process
  373. ObDereferenceObject(Thread); // Dereference the target thread
  374. return TRUE;
  375. }
  376. NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject,PIRP irp)
  377. {
  378. PIO_STACK_LOCATION io;
  379. PINJECT_INFO InjectInfo;
  380. NTSTATUS status;
  381. io=IoGetCurrentIrpStackLocation(irp);
  382. irp->IoStatus.Information=0;
  383. switch(io->MajorFunction)
  384. {
  385. case IRP_MJ_CREATE:
  386. status=STATUS_SUCCESS;
  387. break;
  388. case IRP_MJ_CLOSE:
  389. status=STATUS_SUCCESS;
  390. break;
  391. case IRP_MJ_READ:
  392. status=STATUS_SUCCESS;
  393. break;
  394. case IRP_MJ_WRITE:
  395. InjectInfo=(PINJECT_INFO)MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
  396. if(!InjectInfo)
  397. {
  398. status=STATUS_INSUFFICIENT_RESOURCES;
  399. break;
  400. }
  401. if(!InjectDll(InjectInfo))
  402. {
  403. status=STATUS_UNSUCCESSFUL;
  404. break;
  405. }
  406. status=STATUS_SUCCESS;
  407. irp->IoStatus.Information=sizeof(INJECT_INFO);
  408. break;
  409. default:
  410. status=STATUS_INVALID_DEVICE_REQUEST;
  411. break;
  412. }
  413. irp->IoStatus.Status=status;
  414. IoCompleteRequest(irp,IO_NO_INCREMENT);
  415. return status;
  416. }
  417. NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
  418. {
  419. PDEVICE_OBJECT DeviceObject;
  420. PEPROCESS Process;
  421. PETHREAD Thread;
  422. PKAPC_STATE ApcState;
  423. PVOID KdVersionBlock,NtdllBase;
  424. PULONG ptr,Functions,Names;
  425. PUSHORT Ordinals;
  426. PLDR_DATA_TABLE_ENTRY MmLoadedUserImageList,ModuleEntry;
  427. ULONG i;
  428. PIMAGE_DOS_HEADER pIDH;
  429. PIMAGE_NT_HEADERS pINH;
  430. PIMAGE_EXPORT_DIRECTORY pIED;
  431. pDriverObject->DriverUnload=Unload;
  432. KdVersionBlock=(PVOID)__readfsdword(0x34); // Get the KdVersionBlock
  433. MmLoadedUserImageList=*(PLDR_DATA_TABLE_ENTRY*)((PUCHAR)KdVersionBlock+0x228); // Get the MmLoadUserImageList
  434. DbgPrint("KdVersionBlock address: %#x",KdVersionBlock);
  435. DbgPrint("MmLoadedUserImageList address: %#x",MmLoadedUserImageList);
  436. ModuleEntry=(PLDR_DATA_TABLE_ENTRY)MmLoadedUserImageList->InLoadOrderLinks.Flink; // Move to first entry
  437. NtdllBase=ModuleEntry->DllBase; // ntdll is always located in first entry
  438. DbgPrint("ntdll base address: %#x",NtdllBase);
  439. pIDH=(PIMAGE_DOS_HEADER)NtdllBase;
  440. pINH=(PIMAGE_NT_HEADERS)((PUCHAR)NtdllBase+pIDH->e_lfanew);
  441. pIED=(PIMAGE_EXPORT_DIRECTORY)((PUCHAR)NtdllBase+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
  442. Functions=(PULONG)((PUCHAR)NtdllBase+pIED->AddressOfFunctions);
  443. Names=(PULONG)((PUCHAR)NtdllBase+pIED->AddressOfNames);
  444. Ordinals=(PUSHORT)((PUCHAR)NtdllBase+pIED->AddressOfNameOrdinals);
  445. // Parse the export table to locate LdrLoadDll
  446. for(i=0;i<pIED->NumberOfNames;i++)
  447. {
  448. if(!strcmp((char*)NtdllBase+Names[i],"LdrLoadDll"))
  449. {
  450. LdrLoadDll=(PLDR_LOAD_DLL)((PUCHAR)NtdllBase+Functions[Ordinals[i]]);
  451. break;
  452. }
  453. }
  454. DbgPrint("LdrLoadDll address: %#x",LdrLoadDll);
  455. Process=PsGetCurrentProcess();
  456. Thread=PsGetCurrentThread();
  457. ptr=(PULONG)Thread;
  458. // Locate the ApcState structure
  459. for(i=0;i<512;i++)
  460. {
  461. if(ptr[i]==(ULONG)Process)
  462. {
  463. ApcState=CONTAINING_RECORD(&ptr[i],KAPC_STATE,Process); // Get the actual address of KAPC_STATE
  464. ApcStateOffset=(ULONG)ApcState-(ULONG)Thread; // Calculate the offset of the ApcState structure
  465. break;
  466. }
  467. }
  468. DbgPrint("ApcState offset: %#x",ApcStateOffset);
  469. IoCreateDevice(pDriverObject,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&DeviceObject);
  470. IoCreateSymbolicLink(&SymbolicLink,&DeviceName);
  471. for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
  472. {
  473. pDriverObject->MajorFunction[i]=DriverDispatch;
  474. }
  475. DeviceObject->Flags&=~DO_DEVICE_INITIALIZING;
  476. DeviceObject->Flags|=DO_DIRECT_IO;
  477. DbgPrint("DLL injection driver loaded.");
  478. return STATUS_SUCCESS;
  479. }

Source code (user mode application)

  1. #include <stdio.h>
  2. #include <Windows.h>
  3. typedef struct _INJECT_INFO
  4. {
  5. HANDLE ProcessId;
  6. wchar_t DllName[1024];
  7. }INJECT_INFO,*PINJECT_INFO;
  8. int wmain(int argc,wchar_t* argv[])
  9. {
  10. HANDLE hFile;
  11. DWORD write;
  12. INJECT_INFO InjectInfo;
  13. if(argc<3)
  14. {
  15. printf("\nUsage: kinject [PID] [DLL name]\n");
  16. return -1;
  17. }
  18. hFile=CreateFile(L"\\\\.\\KeInject",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
  19. if(hFile==INVALID_HANDLE_VALUE)
  20. {
  21. printf("\nError: Unable to connect to the driver (%d)\n",GetLastError());
  22. return -1;
  23. }
  24. memset(&InjectInfo,0,sizeof(INJECT_INFO));
  25. InjectInfo.ProcessId=(HANDLE)wcstoul(argv[1],NULL,0);
  26. wcscpy(InjectInfo.DllName,argv[2]);
  27. if(!WriteFile(hFile,&InjectInfo,sizeof(INJECT_INFO),&write,NULL))
  28. {
  29. printf("\nError: Unable to write data to the driver (%d)\n",GetLastError());
  30. CloseHandle(hFile);
  31. return -1;
  32. }
  33. CloseHandle(hFile);
  34. return 0;
  35. }

Attached Files

  • Attached File KeInject.zip 447.64KB 1528 downloads

发表评论

表情:
评论列表 (有 0 条评论,276人围观)

还没有评论,来说两句吧...

相关阅读

    相关 provide/inject

    概述 `provide/inject`:简单的来说就是在父组件中通过`provide`来提供变量,然后在子组件中通过`inject`来注入变量。 需要注意的是这里不论子