大家都知道我们在应用层使用系统api除了gdi相关的都会走中断门或者systementer进0环然后在走ssdt表去执行0环的函数
这也就导致了ssdthook可以挡下大部分的api调用,那如果我们进0环走另外一条路线的话不通过ssdt就可以做到规避掉hook而且也很难被人找到
下面我们用readprocessMemory来简单写个样例代码
思路如下:
驱动层
1.定义code
2.读取3环传来的pid
3.根据pid获取eprocess
4.获取目标进程的cr3
5.提升到dpcl防止被缺页中断导致线程切换,关闭中断,防止被时钟中断导致线程切换
6.修改当前进程的cr3和apcstat结构中的eprocess指针
7.恢复到原始的irql,防止后面读取目标进程内存时缺页无法换页上来,此时我们已经挂靠到了目标进程所以即便被线程切换也不会导致cr3被更新回去
8.读取目标进程的内存将要读取的内容放到0环空间暂存
9.跟之前的流程一样恢复cr3和挂靠
返回内容给三环、
应用层:
1.定义读取目标内存的函数
2.函数内通过deviceiocontrol和code向设备发3.送irp
4.获取目标进程内存内容
5.函数返回
驱动的样例代码如下,这里我直接用我前几个博客里用的那个架子来改了代码里也能会有一些用不到的全局变量大家不用管就行
#include
//#include
#define NTSTRSAFE_LIB
#include
#include
extern NTSTATUS PsLookupProcessByProcessId(
HANDLE ProcessId,
PEPROCESS* Process
);
PDEVICE_OBJECT g_pDev = NULL;
UNICODE_STRING devName = { 0 };
UNICODE_STRING symName = { 0 };
DWORD32 g_idtNum = 0;
PVOID sharedMem;
BOOLEAN g_LoopDelDebugportRun = FALSE;
HANDLE g_LoopDelProcessThreadHandle = 0;
VOID Unload(PDRIVER_OBJECT pDriver) {
KdPrint(("unload"));
if (g_LoopDelDebugportRun) {
LARGE_INTEGER time = { 0 };
time.QuadPart = -100 * 10 * 1000 * 10;//10秒
g_LoopDelDebugportRun = FALSE;
KeWaitForSingleObject(&g_LoopDelProcessThreadHandle, Executive, KernelMode,
FALSE, &time);
ZwClose(g_LoopDelProcessThreadHandle);
}
IoDeleteSymbolicLink(&symName);
IoDeleteDevice(g_pDev);
}
typedef struct _IDTR {
UINT16 limit;
UINT16 base_low;
UINT16 base_hight;
}IDTR, *PIDTR;
#define DEVICE_OBJECT_NAME L"\\Device\\systest"
#define DEVICE_LINK_NAME L"\\??\\systest"
#define MAKE_WORD(a,b) ((a) + (b << 16))
#define MAKE_BASE(a) (DWORD32)(((a >> 32) & 0x00000000ffff0000) + ((a & 0x000000000000ffff)))
#define IOCTL_SYS_INJECTIDT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, \
METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_MAKE_SHAREDPAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, \
METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_HIDEPROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, \
METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_DELDEBUGPORT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, \
METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_READPROCESSSMEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, \
METHOD_BUFFERED, FILE_ANY_ACCESS)
NTSTATUS ReadProcessMemory(UINT32 pid, PVOID addr, PVOID buf, UINT32 len)
{
NTSTATUS status = STATUS_SUCCESS;
PETHREAD pEthread = NULL;
PEPROCESS pEprocess = NULL;
PEPROCESS attachEprocess = NULL;
DWORD32 oldCr3 = 0;
DWORD32 attachCr3 = 0;
_asm {
mov eax, fs: [0x124] //fs:[0]是kpcr + 124是ethread
mov pEthread, eax
mov eax, [eax + 0x220] //eprocess
mov pEprocess, eax
}
__try {
status = PsLookupProcessByProcessId((HANDLE)pid, &attachEprocess);
if (!NT_SUCCESS(status)) {
KdPrint(("failed search target eprocess!\r\n"));
return status;
}
oldCr3 = __readcr3();
attachCr3 = *(PDWORD32)((PUCHAR)attachEprocess + 0x18);
KIRQL irql = KeRaiseIrqlToDpcLevel();
_asm cli; //这里关闭中断是因为时钟中断比dpcl要高,此时还没有挂靠所以要避免线程切换
*(DWORD32*)((PUCHAR)pEthread + 0x44) = attachEprocess;
__writecr3(attachCr3);
_asm sti;
KeLowerIrql(irql);
RtlCopyMemory(buf, addr, len);
return status;
}
__except (1) {
KdPrint(("failed ReadProcessMemory exception happened!\r\n"));
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS DeviceControl(PDEVICE_OBJECT pDev, PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG_PTR Informaiton = 0;
ULONG ioControlCode = 0;
PVOID input = NULL;
ULONG inputLen = 0;
PVOID output = NULL;
ULONG outputLen = 0;
PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation(pIrp);
ioControlCode = pIoStackLocation->Parameters.DeviceIoControl.IoControlCode;
input = pIrp->AssociatedIrp.SystemBuffer;
output = pIrp->AssociatedIrp.SystemBuffer;
inputLen = pIoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
outputLen = pIoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
switch (ioControlCode)
{
case IOCTL_SYS_READPROCESSSMEMORY:
{
DWORD32* data = (PDWORD32)input;
UINT32 pid = data[0];
DWORD32 addr = data[1];
status = ReadProcessMemory(pid, (PVOID)addr, output, outputLen);
if (!NT_SUCCESS(status)) {
KdPrint(("failed del process debugport!\n"));
}
Informaiton = outputLen;
break;
}
default:
break;
}
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = Informaiton;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;
}
NTSTATUS PassFunc(PDEVICE_OBJECT pDev, PIRP pIrp)
{
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRegPath) {
NTSTATUS status = STATUS_SUCCESS;
pDriver->DriverUnload = Unload;
for (size_t i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriver->MajorFunction[i] = PassFunc;
}
pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
do
{
KdPrint(("begin\r\n"));
//创建设备对象
RtlInitUnicodeString(&devName, DEVICE_OBJECT_NAME);
status = IoCreateDevice(pDriver, 0, &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_pDev);
if (!NT_SUCCESS(status)) {
KdPrint(("Create Dev Object Failed!\r\n"));
break;
}
RtlInitUnicodeString(&symName, DEVICE_LINK_NAME);
status = IoCreateSymbolicLink(&symName, &devName);
if (!NT_SUCCESS(status)) {
KdPrint(("Create Sym Link Failed!\r\n"));
IoDeleteDevice(g_pDev);
break;
}
g_pDev->Flags |= DO_BUFFERED_IO;
} while (FALSE);
return status;
}
三环代码就比较简单了写这个博客时候环境已经关掉了,这里就不贴了