#include "ntddk.h"
#define ThreadLength 0x190 //要保存的 NtOpenThread 原代码的长度
#define ProcessLength 0x184 //要保存的 NtOpenProcess 原代码的长度
#define DeviceLink L"\\Device\\DNFCracker"
#define SymbolicLink L"\\DosDevices\\DNFCracker"
#define IOCTL_RESTORE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, 0x886, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef NTSTATUS (* NTOPENTHREAD)(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN OPTIONAL PCLIENT_ID ClientId
);
typedef NTSTATUS (* NTOPENPROCESS)(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId
);
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}
SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
VOID Hook();
VOID Unhook();
NTOPENTHREAD OldThread;
NTOPENPROCESS OldProcess;
ULONG AddrRead, AddrWrite;
//原 NtReadVirtualMemory/NtWriteVirtualMemory 的前 16 字节代码
ULONG OrgRead[2], OrgWrite[2];
//保存 NtOpenThread/NtOpenProcess 代码
UCHAR MyThread[ThreadLength], MyProcess[ProcessLength];
NTSTATUS MyNtOpenThread(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId)
{
ACCESS_MASK oDA;
OBJECT_ATTRIBUTES oOA;
CLIENT_ID oCID;
NTSTATUS statusF, statusT;
oDA = DesiredAccess;
oOA = *ObjectAttributes;
oCID = *ClientId;
statusF = OldThread(ThreadHandle, oDA, &oOA, &oCID);
statusT = ((NTOPENTHREAD)MyThread)(ThreadHandle, DesiredAccess, ObjectAttributes, ClientId);
return statusT;
}
NTSTATUS MyNtOpenProcess(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId)
{
ACCESS_MASK oDA;
OBJECT_ATTRIBUTES oOA;
CLIENT_ID oCID;
NTSTATUS statusF, statusT;
oDA = DesiredAccess;
oOA = *ObjectAttributes;
oCID = *ClientId;
statusF = OldProcess(ProcessHandle, oDA, &oOA, &oCID);
statusT = ((NTOPENPROCESS)MyProcess)(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
return statusT;
}
NTSTATUS DispatchIoCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
ULONG ioControlCode;
ULONG inBufLength, outBufLength;
//PUCHAR InputBuffer, OutputBuffer;
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
case IOCTL_RESTORE:
//InputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
//OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
//恢复 NtReadVirtualMemory/NtWriteVirtualMemory 前 16 字节
*(PULONG)(*(PULONG)AddrRead) = OrgRead[0];
*(PULONG)(*(PULONG)AddrRead + 4) = OrgRead[1];
*(PULONG)(*(PULONG)AddrWrite) = OrgWrite[0];
*(PULONG)(*(PULONG)AddrWrite + 4) = OrgWrite[1];
Irp->IoStatus.Information = outBufLength;
break;
default:
DbgPrint("Unknown IOCTL: 0x%X (%04X)",
ioControlCode, IoGetFunctionCodeFromCtlCode(ioControlCode));
status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
}
//完成 IRP
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING usLink;
/*ULONG i;
for (i = 0; i < ThreadLength; i += 4)
{
DbgPrint("%02x %02x %02x %02x\n", MyThread[i], MyThread[i + 1], MyThread[i + 2], MyThread[i + 3]);
DbgPrint("%02x %02x %02x %02x\n", MyProcess[i], MyProcess[i + 1], MyProcess[i + 2], MyProcess[i + 3]);
}
*/
Unhook();
DbgPrint("DNF Cracker Unloaded!");
RtlInitUnicodeString(&usLink, SymbolicLink);
IoDeleteSymbolicLink(&usLink);
IoDeleteDevice(DriverObject->DeviceObject);
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
PDEVICE_OBJECT DvcObj;
UNICODE_STRING usDevice, usLink;
PLIST_ENTRY pLE = (PLIST_ENTRY)DriverObject->DriverSection;
//隐藏驱动
pLE->Flink->Blink = pLE->Blink;
pLE->Blink->Flink = pLE->Flink;
DriverObject->DriverUnload = OnUnload;
//创建虚拟设备
RtlInitUnicodeString(&usDevice, DeviceLink);
status = IoCreateDevice(DriverObject, 0, &usDevice, FILE_DEVICE_UNKNOWN, 0, TRUE, &DvcObj);
if (!NT_SUCCESS(status))
{
DbgPrint("Failed to create device!\n");
return status;
}
//创建符号链接
RtlInitUnicodeString(&usLink, SymbolicLink);
status = IoCreateSymbolicLink(&usLink, &usDevice);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(DriverObject->DeviceObject);
DbgPrint("Failed to create symbolic link!\n");
return status;
}
//调度函数分配
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] =
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoCtrl;
Hook();
DbgPrint("DNF Cracker Loaded!");
return STATUS_SUCCESS;
}
// OrgRel 原相对跳转地址
// CurAbs 当前代码绝对地址
// MyAbs 替换代码绝对地址
// CodeLen 跳转代码占据的长度
// 返回值 到替换代码的相对地址
LONG GetRelAddr(LONG OrgRel, ULONG CurAbs, ULONG MyAbs) //, ULONG CodeLen)
{
ULONG TrgAbs;
TrgAbs = CurAbs + OrgRel; // + CodeLen; //目的地址
return TrgAbs - MyAbs;
}
// 保存原来整个函数的代码
// pCode 用来保存代码的数组的地址
// TrgAddr 要保存的函数的地址
// BufferLength 整个函数占用的大小
VOID BufferCode(PUCHAR pCode, ULONG TrgAddr, ULONG BufferLength)
{
ULONG cAbs, i;
LONG oRel, cRel;
memset(pCode, 0x90, BufferLength);
for (i = 0; i < BufferLength; i++)
{
cAbs = TrgAddr + i;
pCode[i] = *(PUCHAR)cAbs;
switch (*(PUCHAR)cAbs)
{
case 0x0F: //JXX NEAR X
if ((*(PUCHAR)(cAbs + 1) >= 0x80)&&(*(PUCHAR)(cAbs + 1) <= 0x8F))
{
oRel = *(PLONG)(cAbs + 2);
if ((oRel + cAbs + 6 > TrgAddr + BufferLength)||
(oRel + cAbs + 6 < TrgAddr)) //判断跳转是否在过程范围内
{
pCode[i + 1] = *(PUCHAR)(cAbs + 1);
cRel = GetRelAddr(oRel, cAbs, (ULONG)pCode + i);
memcpy(pCode + i + 2, &cRel, sizeof(LONG));
//DbgPrint("JXX: 0x%08X -> 0x%08X", cAbs, (ULONG)pCode + i);
i += sizeof(LONG) + 1;
}
}
break;
case 0xE8: //CALL
oRel = *(PLONG)(cAbs + 1);
if ((oRel + cAbs + 5 > TrgAddr + BufferLength)||
(oRel + cAbs + 5 < TrgAddr)) //判断跳转是否在过程范围内
{
cRel = GetRelAddr(oRel, cAbs, (ULONG)pCode + i);
memcpy(pCode + i + 1, &cRel, sizeof(LONG));
//DbgPrint("CALL: 0x%08X -> 0x%08X", cAbs, (ULONG)pCode + i);
i += sizeof(LONG);
}
break;
case 0x80: //CMP BYTE PTR X
if (*(PUCHAR)(cAbs + 1) == 0x7D)
{
memcpy(pCode + i + 1, (PVOID)(cAbs + 1), 3);
i += 3; continue;
}
break;
case 0xC2: //RET X
if (*(PUSHORT)(cAbs +1) == 0x10)
{
memcpy(pCode + i + 1, (PVOID)(cAbs + 1), sizeof(USHORT));
i += sizeof(USHORT);
}
break;
/*case 0xE9: //JMP
oRel = *(PLONG)(cAbs + 1);
if (oRel + cAbs > TrgAddr + BufferLength)
{
cRel = GetRelAddr(oRel, cAbs, (ULONG)pCode + i);
memcpy(pCode + i + 1, &cRel, sizeof(LONG));
i += 4;
}*/
}
if ((*(PUCHAR)cAbs == 0x39)||(*(PUCHAR)cAbs == 0x89)||(*(PUCHAR)cAbs == 0x8D))
{
memcpy(pCode + i + 1, (PVOID)(cAbs + 1), sizeof(USHORT));
i += sizeof(USHORT); continue;
}
/*if ((*(PUCHAR)cAbs >= 0x70)&&(*(PUCHAR)cAbs <= 0x7F)&&(*(PUCHAR)(cAbs - 1) != 0xFF))
{
oRel = (LONG)(*(PCHAR)(cAbs + 1));
cRel = GetRelAddr(oRel, cAbs, (ULONG)pCode + i);
memcpy(pCode + i + 1, &cRel, 1);
i++; continue;
}*/
}
}
VOID Hook()
{
ULONG AddrProcess, AddrThread;
AddrRead = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0xBA * 4;
AddrWrite = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x115 * 4;
AddrThread = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x80 * 4;
AddrProcess = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;
OldThread = (NTOPENTHREAD)(*(PULONG)AddrThread);
OldProcess = (NTOPENPROCESS)(*(PULONG)AddrProcess);
DbgPrint("MyThread:0x%08X OldThread:0x%08X", MyThread, OldThread);
DbgPrint("MyProcess:0x%08X OldProcess:0x%08X", MyProcess, OldProcess);
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
//记录 NtReadVirtualMemory/NtWriteVirtualMemory 前 16 字节
OrgRead[0] = *(PULONG)(*(PULONG)AddrRead);
OrgRead[1] = *(PULONG)(*(PULONG)AddrRead + 4);
OrgWrite[0] = *(PULONG)(*(PULONG)AddrWrite);
OrgWrite[1] = *(PULONG)(*(PULONG)AddrWrite + 4);
//保存原代码
BufferCode(MyThread, (ULONG)OldThread, ThreadLength);
BufferCode(MyProcess, (ULONG)OldProcess, ProcessLength);
//SSDT Hook
*(PULONG)AddrThread = (ULONG)MyNtOpenThread;
*(PULONG)AddrProcess = (ULONG)MyNtOpenProcess;
__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
DbgPrint("Hooked!");
}
VOID Unhook()
{
ULONG AddrProcess, AddrThread;
AddrThread = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x80 * 4;
AddrProcess = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
//恢复 SSDT
*(PULONG)AddrThread = (ULONG)OldThread;
*(PULONG)AddrProcess = (ULONG)OldProcess;
__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
DbgPrint("Unhooked!");
}