指定PID句柄提权

上一节句柄降权是降权驱动将我们CE中的私有句柄表的DbgVIew成员权限给换了,所以我们的方案就是将这个权限提升回去,但是这样就会出现一闪一闪的样子,因为降权驱动一遍在降权提权驱动一遍在提权,所以这时候的思路是让降权驱动失效。根据上节我们可以看到降权驱动是在判断CE中的私有句柄表中是否有DbgView的句柄,那么办法就是换掉这个CE私有句柄表中的DbgView句柄,但是新的DbgView句柄中内容和原来保存的是一致的,代码如下

这里有几点需要注意:
1.因为原先私有句柄表由系统维护,在目标进程关闭的时候别人内存中的私有句柄表也会跟着取消,但是由于我们修改了私有句柄表的值,这个地方就得由我们来维护
2.程序在运行时应该先卸载掉提权驱动将CE的私有句柄表恢复,然后再进行关闭,否则会蓝屏
3.在驱动中抹除CR3、PID、名称只是为了防止更深层检测,并不影响提权

驱动代码:

#include 
#include 
#define My_Code CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define PROCESS_VM_READ           (0x0010)  // winnt
#define PROCESS_VM_WRITE          (0x0020)  // winnt

BOOLEAN isThreadWork = TRUE;

typedef struct _DEVICE_EXTENSION {
	UNICODE_STRING SymLinkName;
} DEVICE_EXTENSION, * PDEVICE_EXTENSION;

struct _HANDLE_TABLE_ENTRY_INFO
{
	ULONG AuditMask;                                                        //0x0
};

typedef struct _HANDLE_TABLE_ENTRY
{
	union
	{
		VOID* Object;                                                       //0x0
		ULONG ObAttributes;                                                 //0x0
		struct _HANDLE_TABLE_ENTRY_INFO* InfoTable;                         //0x0
		ULONG Value;                                                        //0x0
	};
	union
	{
		ULONG GrantedAccess;                                                //0x4
		struct
		{
			USHORT GrantedAccessIndex;                                      //0x4
			USHORT CreatorBackTraceIndex;                                   //0x6
		};
		ULONG NextFreeTableEntry;                                           //0x4
	};
}HANDLE_TABLE_ENTRY, * PHANDLE_TABLE_ENTRY;

typedef struct Hread {
	ULONG Flage;
	ULONG Addr;
	ULONG WriteBufferAddr;
	ULONG Size;
	ULONG Pid;
}_Hread, * PtrHread;

typedef BOOLEAN(NTAPI* EX_ENUMERATE_HANDLE_ROUTINE)(
	IN PHANDLE_TABLE_ENTRY HandleTableEntry,
	IN HANDLE Handle,
	IN PVOID EnumParameter
	);

BOOLEAN ExEnumHandleTable(
	__in PVOID HandleTable,
	__in EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
	__in PVOID EnumParameter,
	__out_opt PHANDLE Handle
);

PVOID gObject = NULL;
PHANDLE_TABLE_ENTRY DbgView_HandleTableEntry;
ULONG DbgView_Value;

BOOLEAN NTAPI enumRoutine(
	IN PHANDLE_TABLE_ENTRY HandleTableEntry,
	IN HANDLE Handle,
	IN PVOID EnumParameter
)
{
	if (HandleTableEntry)
	{
		ULONG_PTR object = (HandleTableEntry->Value & ~7) + 0x18;
		if (object == (ULONG_PTR)EnumParameter)
		{
			//保存先前在CE中DbgView句柄,用于后续还原
			DbgView_HandleTableEntry = HandleTableEntry;
			DbgView_Value = HandleTableEntry->Value;

			HandleTableEntry->Value = (ULONG_PTR)gObject | 1;
			HandleTableEntry->GrantedAccess |= PROCESS_ALL_ACCESS;
		}
	}

	return FALSE;
}

PEPROCESS FindProcessByName(PWCH name)
{
	PEPROCESS Process = NULL;
	PEPROCESS findProcess = NULL;
	for (int i = 8; i < 0x1000000; i += 4)
	{
		NTSTATUS status = PsLookupProcessByProcessId((HANDLE)i, &Process);
		if (!NT_SUCCESS(status))
		{
			continue;
		}

		PUNICODE_STRING ProcessName = NULL;
		status = SeLocateProcessImageName(Process, &ProcessName);

		if (!NT_SUCCESS(status))
		{
			ObDereferenceObject(Process);
			continue;
		}

		if (ProcessName->Length)
		{
			_wcsupr(ProcessName->Buffer);
			if (wcsstr(ProcessName->Buffer, name) != 0)
			{
				findProcess = Process;
				ExFreePoolWithTag(ProcessName, 0);
				//排除空私有表项的成员
				ULONG* ObjectTable = (ULONG*)((ULONG)Process + 0xf4);
				if (*ObjectTable == 0)
				{
					continue;
				}
				break;
			}
		}
		ExFreePoolWithTag(ProcessName, 0);
		ObDereferenceObject(Process);
	}

	return findProcess;
}

ULONG GetProcessIdOffset()
{
	UNICODE_STRING unName = { 0 };
	RtlInitUnicodeString(&unName, L"PsGetProcessId");
	PUCHAR startFunc = MmGetSystemRoutineAddress(&unName);

	return *(PULONG)(startFunc + 8);
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	DbgPrint("--------------DRIVER_UNLOAD-----------------");
	PDEVICE_OBJECT pDevObj;
	//还原CE中的DbgView句柄
	DbgView_HandleTableEntry->Value = DbgView_Value;

	ExFreePool(gObject);

	LARGE_INTEGER tin = { 0 };
	tin.QuadPart = -10000 * 15000;
	KeDelayExecutionThread(KernelMode, FALSE, &tin);

	pDevObj = pDriverObject->DeviceObject;
	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
	UNICODE_STRING pLinkName = pDevExt->SymLinkName;
	IoDeleteSymbolicLink(&pLinkName);
	IoDeleteDevice(pDevObj);
}


VOID Limit_Up(ULONG PID)
{
	gObject = ExAllocatePool(NonPagedPool, PAGE_SIZE);
	PEPROCESS srcProcess = (PUCHAR)gObject + 0x18;
	memset(gObject, 0, PAGE_SIZE);

	//复制进程
	PEPROCESS TargetProcess = FindProcessByName(L"DBGVIEW.EXE");
	memcpy(gObject, (PUCHAR)TargetProcess - 0x18, 0x300);

	//干掉PID
	*(PHANDLE)((PUCHAR)srcProcess + GetProcessIdOffset()) = 0;
	
	ULONG cr3 = *(PULONG)((PUCHAR)TargetProcess + 0x18); //获取目标进程的CR3

	PHYSICAL_ADDRESS cr3Phy = { 0 };
	cr3Phy.QuadPart = cr3;
	ULONG msize = 0x20;  // 29912分页

	if ((cr3 % 0x1000) == 0)
	{
		//101012分页
		msize = PAGE_SIZE;
	}

	
	PVOID mem = MmMapIoSpace(cr3Phy, msize, MmNonCached); //拿到我们的目标进程CR3的另一个线性地址

	//复制CR3	
	PVOID srcCr3 = (PVOID)ExAllocatePool(NonPagedPool, PAGE_SIZE);
	memset(srcCr3, 0, PAGE_SIZE);
	memcpy(srcCr3, mem, msize); //拷贝过去CR3页目录表

	
	PHYSICAL_ADDRESS srcphyCr3 = MmGetPhysicalAddress(srcCr3); //获取到拷贝后新的页目录表物理地址
	//给它一个新的CR3
	*(PULONG)((PUCHAR)srcProcess + 0x18) = srcphyCr3.LowPart;
	PEPROCESS ceProcess = NULL;
	NTSTATUS status = PsLookupProcessByProcessId(PID, &ceProcess);   //ce进程PID
	if (NT_SUCCESS(status))
	{
		ExEnumHandleTable(*(PULONG)((PUCHAR)ceProcess + 0xf4), enumRoutine, TargetProcess, NULL);
	}
}

NTSTATUS IoctlDispatchRoutine(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	ULONG_PTR Informaiton = 0;
	PVOID InputData = NULL;
	ULONG InputDataLength = 0;
	PVOID OutputData = NULL;
	ULONG OutputDataLength = 0;
	PIO_STACK_LOCATION  IoStackLocation = IoGetCurrentIrpStackLocation(pIrp);              // Irp堆栈  
	InputData = pIrp->AssociatedIrp.SystemBuffer;
	OutputData = pIrp->AssociatedIrp.SystemBuffer;
	InputDataLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;      // 输入数据大小
	OutputDataLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;    // 输出数据大小
	ULONG Code = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;

	switch (Code)
	{
	case My_Code:
	{
		PtrHread PtrBuff = (PtrHread)InputData;
		ULONG PID = PtrBuff->Pid;

		Limit_Up(PID);

		DbgPrint("要操作进程PID: %d", PID);

		Status = STATUS_SUCCESS;

		break;
	}
	}

	pIrp->IoStatus.Status = Status;                   // 设置IRP完成状态,会设置用户模式下的GetLastError
	pIrp->IoStatus.Information = Informaiton;    // 设置操作的字节
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);         // 完成IRP,不增加优先级
	return Status;
}

NTSTATUS DefDispatchRoutine(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return status;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
	pDriverObject->DriverUnload = DriverUnload;//注册驱动卸载函数
	pDriverObject->MajorFunction[IRP_MJ_CREATE] = DefDispatchRoutine;   // 注册派遣函数
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DefDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = DefDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_READ] = DefDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoctlDispatchRoutine;

	NTSTATUS status;
	PDEVICE_OBJECT pDevObj;
	PDEVICE_EXTENSION pDevExt;

	//创建设备名称的字符串
	UNICODE_STRING devName;
	RtlInitUnicodeString(&devName, L"\\Device\\MyDevice2");
	//创建设备
	status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
	pDevObj->Flags |= DO_BUFFERED_IO;//将设备设置为缓冲I/O设备
	pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;//得到设备扩展

	//创建符号链接
	UNICODE_STRING symLinkName;
	RtlInitUnicodeString(&symLinkName, L"\\??\\MyDevice2");
	pDevExt->SymLinkName = symLinkName;
	status = IoCreateSymbolicLink(&symLinkName, &devName);

	return STATUS_SUCCESS;
}

三环通信程序

//三环与驱动通信的应用程序
#include
#include
#include
// 自定义的控制信号
#define My_Code CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_BUFFERED,FILE_ANY_ACCESS)

typedef struct Hread {
	ULONG Flage;
	ULONG Addr;
	ULONG WriteBufferAddr;
	ULONG Size;
	ULONG Pid;
}_Hread, * PtrHread;

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE handle = CreateFileA("\\\\.\\MyDevice2", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	unsigned char RetBufferData[20] = { 0 };
	DWORD ReturnLength = 4;
	_Hread buf;

	printf_s("请输入你要提权的句柄PID:");
	scanf_s("%d", &buf.Pid);

	DeviceIoControl(handle, My_Code, &buf, 20, (LPVOID)RetBufferData, 4, &ReturnLength, 0);

	system("pause");
	CloseHandle(handle);
	return 0;
}

你可能感兴趣的:(windows内核,系统安全,网络安全,驱动开发)