#include ntddk.h #define ThreadLength 0x190 //要保存的 NtOpenThread 原代码的长度 #define ProcessLength 0x184 //要保存的 NtOpenProcess 原代码的长度 #define DeviceLink L\\Device\\DNFCracker #define SymbolicLink L\\DosDevices\\DNFCracker #def
#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 { 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 { 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 { 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 { 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!"); }