mirror of
https://github.com/ChengChengCC/Ark-tools.git
synced 2026-10-23 17:58:29 +08:00
425 lines
10 KiB
C
425 lines
10 KiB
C
|
|
|
|
#ifndef CXX_KEINJECTAPC_H
|
|
# include "KeInjectApc.h"
|
|
#endif
|
|
|
|
|
|
ULONG ApcStateOffset;
|
|
PLDR_LOAD_DLL LdrLoadDll;
|
|
|
|
|
|
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING pRegistryPath)
|
|
{
|
|
NTSTATUS Status;
|
|
PDEVICE_OBJECT DeviceObject;
|
|
PEPROCESS Process;
|
|
PETHREAD Thread;
|
|
PKAPC_STATE ApcState;
|
|
|
|
PVOID KdVersionBlock,NtdllBase;
|
|
PULONG ptr,Functions,Names;
|
|
PUSHORT Ordinals;
|
|
|
|
PLDR_DATA_TABLE_ENTRY MmLoadedUserImageList,ModuleEntry;
|
|
ULONG i;
|
|
|
|
PIMAGE_DOS_HEADER pIDH;
|
|
PIMAGE_NT_HEADERS pINH;
|
|
PIMAGE_EXPORT_DIRECTORY pIED;
|
|
|
|
UNICODE_STRING uniDeviceName;
|
|
UNICODE_STRING uniLinkName;
|
|
|
|
RtlInitUnicodeString(&uniDeviceName,DEVICE_NAME);
|
|
|
|
RtlInitUnicodeString(&uniLinkName,LINK_NAME);
|
|
|
|
for (i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
|
|
{
|
|
DriverObject->MajorFunction[i] = DefaultPassThrough;
|
|
}
|
|
DriverObject->DriverUnload = UnloadDriver;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverDispatch;
|
|
|
|
//创建设备对象
|
|
Status = IoCreateDevice(DriverObject,0,&uniDeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&DeviceObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
|
|
return Status;
|
|
}
|
|
|
|
Status = IoCreateSymbolicLink(&uniLinkName,&uniDeviceName);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
IoDeleteDevice(DeviceObject);
|
|
|
|
return Status;
|
|
}
|
|
|
|
//使当前线程运行在第一个处理器上
|
|
KeSetSystemAffinityThread(1);
|
|
KdVersionBlock=(PVOID)__readfsdword(0x34); //得到KdVersionBlock
|
|
KeRevertToUserAffinityThread();//恢复线程运行的处理器
|
|
MmLoadedUserImageList=*(PLDR_DATA_TABLE_ENTRY*)((PUCHAR)KdVersionBlock+0x228); // Get the MmLoadUserImageList
|
|
|
|
/*
|
|
kd> !pcr
|
|
KPCR for Processor 0 at 83f3ec00:
|
|
|
|
|
|
kd> dt _kpcr 83f3ec00
|
|
+0x034 KdVersionBlock : 0x83f3dc00 Void
|
|
|
|
kd> dd 0x83f3dc00+0x228
|
|
83f3de28 83f5de38 00000000 83e5dfa8 00000000
|
|
83f3de38 00000000 00000000 83f7d8c0 00000000
|
|
83f3de48 83f7d560 00000000 83f5d84c 00000000
|
|
|
|
|
|
kd> dd 83f5de38
|
|
83f5de38 8706b1e8 877cb660 00000000 00000000
|
|
83f5de48 00000000 00000000 00040107 00000000
|
|
83f5de58 865d0690 865d0690 c0403188 0007ff7e
|
|
|
|
kd> dt _LDR_DATA_TABLE_ENTRY 8706b1e8
|
|
nt!_LDR_DATA_TABLE_ENTRY
|
|
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x8713b4e0 - 0x83f5de38 ]
|
|
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
|
|
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
|
|
+0x018 DllBase : 0x77ce0000 Void
|
|
+0x01c EntryPoint : (null)
|
|
+0x020 SizeOfImage : 0x13c000
|
|
+0x024 FullDllName : _UNICODE_STRING "\Windows\System32\ntdll.dll"
|
|
+0x02c BaseDllName : _UNICODE_STRING ""
|
|
+0x034 Flags : 0
|
|
+0x038 LoadCount : 1
|
|
+0x03a TlsIndex : 0
|
|
+0x03c HashLinks : _LIST_ENTRY [ 0x0 - 0x1490d9 ]
|
|
+0x03c SectionPointer : (null)
|
|
+0x040 CheckSum : 0x1490d9
|
|
+0x044 TimeDateStamp : 0
|
|
+0x044 LoadedImports : (null)
|
|
+0x048 EntryPointActivationContext : (null)
|
|
+0x04c PatchInformation : (null)
|
|
+0x050 ForwarderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
|
|
+0x058 ServiceTagLinks : _LIST_ENTRY [ 0x0 - 0x57005c ]
|
|
+0x060 StaticLinks : _LIST_ENTRY [ 0x6e0069 - 0x6f0064 ]
|
|
+0x068 ContextInformation : 0x00730077 Void
|
|
+0x06c OriginalBase : 0x53005c
|
|
+0x070 LoadTime : _LARGE_INTEGER 0x650074`00730079
|
|
|
|
*/
|
|
DbgPrint("KdVersionBlock address: %#x",KdVersionBlock);
|
|
DbgPrint("MmLoadedUserImageList address: %#x",MmLoadedUserImageList);
|
|
|
|
ModuleEntry=(PLDR_DATA_TABLE_ENTRY)MmLoadedUserImageList->InLoadOrderLinks.Flink; //第一模块
|
|
NtdllBase=ModuleEntry->DllBase; //ntdll基地址
|
|
|
|
DbgPrint("ntdll base address: %#x",NtdllBase);
|
|
|
|
pIDH=(PIMAGE_DOS_HEADER)NtdllBase;
|
|
pINH=(PIMAGE_NT_HEADERS)((PUCHAR)NtdllBase+pIDH->e_lfanew);
|
|
pIED=(PIMAGE_EXPORT_DIRECTORY)((PUCHAR)NtdllBase+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
|
|
|
Functions=(PULONG)((PUCHAR)NtdllBase+pIED->AddressOfFunctions);
|
|
Names=(PULONG)((PUCHAR)NtdllBase+pIED->AddressOfNames);
|
|
|
|
Ordinals=(PUSHORT)((PUCHAR)NtdllBase+pIED->AddressOfNameOrdinals);
|
|
|
|
//搜索LdrLoadDll
|
|
for(i=0;i<pIED->NumberOfNames;i++)
|
|
{
|
|
if(!strcmp((char*)NtdllBase+Names[i],"LdrLoadDll"))
|
|
{
|
|
LdrLoadDll=(PLDR_LOAD_DLL)((PUCHAR)NtdllBase+Functions[Ordinals[i]]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
DbgPrint("LdrLoadDll address: %#x",LdrLoadDll);
|
|
|
|
Process=PsGetCurrentProcess();
|
|
Thread=PsGetCurrentThread();
|
|
|
|
ptr=(PULONG)Thread;
|
|
|
|
//确定ApcState在EThread中的偏移
|
|
for(i=0;i<512;i++)
|
|
{
|
|
if(ptr[i]==(ULONG)Process)
|
|
{
|
|
ApcState=CONTAINING_RECORD(&ptr[i],KAPC_STATE,Process);
|
|
ApcStateOffset=(ULONG)ApcState-(ULONG)Thread;
|
|
break;
|
|
}
|
|
}
|
|
|
|
DbgPrint("ApcState offset: %#x",ApcStateOffset);
|
|
DbgPrint("DLL injection driver loaded.");
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS DefaultPassThrough(PDEVICE_OBJECT DeviceObject,PIRP Irp)
|
|
{
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
void UnloadDriver(PDRIVER_OBJECT DriverObject)
|
|
{
|
|
UNICODE_STRING uniLinkName;
|
|
PDEVICE_OBJECT CurrentDeviceObject;
|
|
PDEVICE_OBJECT NextDeviceObject;
|
|
|
|
RtlInitUnicodeString(&uniLinkName,LINK_NAME);
|
|
|
|
IoDeleteSymbolicLink(&uniLinkName);
|
|
|
|
if (DriverObject->DeviceObject!=NULL)
|
|
{
|
|
CurrentDeviceObject = DriverObject->DeviceObject;
|
|
|
|
while(CurrentDeviceObject!=NULL)
|
|
{
|
|
NextDeviceObject = CurrentDeviceObject->NextDevice;
|
|
IoDeleteDevice(CurrentDeviceObject);
|
|
|
|
CurrentDeviceObject = NextDeviceObject;
|
|
}
|
|
}
|
|
DbgPrint("UnloadDriver\r\n");
|
|
}
|
|
|
|
|
|
void NTAPI InjectDllApc(PVOID NormalContext,PVOID SystemArgument1,PVOID SystemArgument2)
|
|
{
|
|
PKINJECT inject=(PKINJECT)NormalContext;
|
|
|
|
inject->LdrLoadDll(NULL,NULL,&inject->DllName,&inject->DllBase);
|
|
inject->Executed=TRUE;
|
|
}
|
|
|
|
|
|
void NTAPI KernelRoutine(PKAPC apc,PKNORMAL_ROUTINE* NormalRoutine,PVOID* NormalContext,\
|
|
PVOID* SystemArgument1,PVOID* SystemArgument2)
|
|
{
|
|
ExFreePool(apc);
|
|
}
|
|
|
|
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 DriverDispatch(PDEVICE_OBJECT DeviceObject,PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION io;
|
|
PINJECT_INFO InjectInfo;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
PVOID InputBuffer = NULL;
|
|
PVOID OutputBuffer = NULL;
|
|
ULONG_PTR InputSize = 0;
|
|
ULONG_PTR OutputSize = 0;
|
|
ULONG_PTR IoControlCode = 0;
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
InputBuffer = OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
|
InputSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
|
OutputSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
|
IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
|
|
|
|
switch(IoControlCode)
|
|
{
|
|
case CTL_KEINJECTAPC:
|
|
|
|
InjectInfo=(PINJECT_INFO)InputBuffer;
|
|
|
|
if(!InjectInfo)
|
|
{
|
|
Status=STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
if(!InjectDll(InjectInfo))
|
|
{
|
|
Status=STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
Status=STATUS_SUCCESS;
|
|
Irp->IoStatus.Information=0;
|
|
|
|
break;
|
|
|
|
default:
|
|
Status=STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
|
|
Irp->IoStatus.Status=Status;
|
|
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
return Status;
|
|
}
|