上一节句柄降权是降权驱动将我们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;
}