드디어 기본적인 틀은 다짰다.
이걸 어떻게 x64로 적용할지가 문제긴 한데 일단 x86을 먼저 시도해놨으니까 괜찮지 않을까 싶다.
아닐 때만 판별해낸다.
아래는 결과적으로 만든 드라이버 소스다.
접기
#include <ntifs.h>
#pragma warning(disable: 4201)
typedef unsigned short WORD;
typedef unsigned char BYTE;
#define WP_MASK 0x0FFFEFFFF //WP bit mask
#define SYSCALL_INDEX(_Func) *(PULONG) ((PUCHAR)_Func+1)
#define SYSTEM_SERVICE(_Func) KeServiceDescriptorTable.ServiceTableBase[SYSCALL_INDEX(_Func)]
#define SYSTEM_SERVICE_INDEX(Index) KeServiceDescriptorTable.ServiceTableBase[Index]
#define HOOK_SYSCALL(CurrentFunc, ChangeFunc) InterlockedExchange((PLONG)&SYSTEM_SERVICE(CurrentFunc), (LONG)ChangeFunc)
#define HOOK_SYSCALL_INDEX(Index, ChangeFunc) InterlockedExchange((PLONG)&SYSTEM_SERVICE_INDEX(Index), (LONG)ChangeFunc)
void writeCR0();
void readCR0();
NTSTATUS SetHookProc();
NTSTATUS SetUnHookProc();
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
void UnloadRoutine(
IN PDRIVER_OBJECT DriverObject
);
typedef unsigned int DWORD;
typedef unsigned int* LPDWORD;
typedef void* LPVOID;
typedef int BOOL;
#pragma pack(1)
typedef struct ServiceDescriptorEntry
{
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase;
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} SSDT_ENTRY;
#pragma pack()
typedef struct _SYSTEM_THREADS_INFORMATION
{
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientIs;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
ULONG ThreadState;
KWAIT_REASON WaitReason;
}SYSTEM_THREADS_INFORMATION, *PSYSTEM_THREADS_INFORMATION;
typedef struct _SYSTEM_PROCESS_INFORMATION
{
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters; //windows 2000 only
SYSTEM_THREADS_INFORMATION Threads[1];
}SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESSES_INFORMATION;
EXTERN_C __declspec(dllimport) SSDT_ENTRY KeServiceDescriptorTable;
typedef NTSTATUS(*ZWCREATETHREADEX) (
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,
IN HANDLE ProcessHandle,
IN PVOID StartRoutine,
IN OPTIONAL PVOID Argument,
IN ULONG CreateFlags,
IN OPTIONAL ULONG_PTR ZeroBits,
IN OPTIONAL SIZE_T StackSize,
IN OPTIONAL SIZE_T MaximumStackSize,
IN OPTIONAL PVOID AttributeList
);
NTSTATUS ZwCreateThreadEx(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,
IN HANDLE ProcessHandle,
IN PVOID StartRoutine,
IN OPTIONAL PVOID Argument,
IN ULONG CreateFlags,
IN OPTIONAL ULONG_PTR ZeroBits,
IN OPTIONAL SIZE_T StackSize,
IN OPTIONAL SIZE_T MaximumStackSize,
IN OPTIONAL PVOID AttributeList
);
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemPathInformation,
SystemProcessInformation,
SystemCallCountInformation,
SystemDeviceInformation,
SystemProcessorPerformanceInformation,
SystemFlagsInformation,
SystemCallTimeInformation,
SystemModuleInformation,
SystemLocksInformation,
SystemStackTraceInformation,
SystemPagedPoolInformation,
SystemNonPagedPoolInformation,
SystemHandleInformation,
SystemObjectInformation,
SystemPageFileInformation,
SystemVdmInstemulInformation,
SystemVdmBopInformation,
SystemFileCacheInformation,
SystemPoolTagInformation,
SystemInterruptInformation,
SystemDpcBehaviorInformation,
SystemFullMemoryInformation,
SystemLoadGdiDriverInformation,
SystemUnloadGdiDriverInformation,
SystemTimeAdjustmentInformation,
SystemSummaryMemoryInformation,
SystemNextEventIdInformation,
SystemEventIdsInformation,
SystemCrashDumpInformation,
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation,
SystemExtendServiceTableInformation,
SystemPrioritySeperation,
SystemPlugPlayBusInformation,
SystemDockInformation,
SystemPowerInformation_,
SystemProcessorSpeedInformation,
SystemCurrentTimeZoneInformation,
SystemLookasideInformation
} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
EXTERN_C NTKERNELAPI NTSTATUS NTAPI ZwQuerySystemInformation(
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
_Inout_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);
EXTERN_C NTKERNELAPI NTSTATUS NTAPI ZwOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN OPTIONAL PCLIENT_ID ClientId
);
typedef struct _SYSTEM_HANDLE
{
ULONG ProcessId;
BYTE ObjectTypeNumber;
BYTE Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG HandleCount; /* Or NumberOfHandles if you prefer. */
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
접기 접기
#include "Hook.h"
#pragma warning(disable:4054) // casting-warning disable
#pragma warning(disable:4305) // casting-warning disable - high to low
void writeCR0(){
__asm
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh
mov CR0, eax
pop eax
};
}
void readCR0(){
__asm
{
push eax
mov eax, CR0
or eax, NOT 0FFFEFFFFh
mov CR0, eax
pop eax
};
}
ZWCREATETHREADEX OrgZwCreateThreadEx;
#define ZWCREATETHREADEX_INDEX 0x58
NTSTATUS ZwCreateThreadEx(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,
IN HANDLE ProcessHandle,
IN PVOID StartRoutine,
IN OPTIONAL PVOID Argument,
IN ULONG CreateFlags,
IN OPTIONAL ULONG_PTR ZeroBits,
IN OPTIONAL SIZE_T StackSize,
IN OPTIONAL SIZE_T MaximumStackSize,
IN OPTIONAL PVOID AttributeList
){
DbgPrint("ZwCreateThreadEx(Hooked)");
DbgPrint("Routine Address : %p", StartRoutine);
if ((DWORD)ProcessHandle == 0xffffffff || (DWORD)ProcessHandle >= 0x80000000){
DbgPrint("Call Original ZwCreateThreadEx");
return OrgZwCreateThreadEx(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle,
StartRoutine, Argument, CreateFlags, ZeroBits, StackSize, MaximumStackSize, AttributeList);
}
else{
ULONG dum, dum2;
SYSTEM_HANDLE_INFORMATION dummy = { 0, };
NTSTATUS result = ZwQuerySystemInformation(SystemHandleInformation, &dummy, sizeof(SYSTEM_HANDLE_INFORMATION), &dum);
PVOID *proc = NULL;
DWORD pid = 0xffffffff;
if (result == STATUS_INFO_LENGTH_MISMATCH){
proc = ExAllocatePoolWithTag(NonPagedPool, dum, 'GETK');
if (proc){
result = ZwQuerySystemInformation(SystemHandleInformation, proc, dum, &dum2);
SYSTEM_HANDLE_INFORMATION *ptr = (SYSTEM_HANDLE_INFORMATION *)proc;
for (ULONG idx = 0; idx < ptr->HandleCount; idx++){
if (ptr->Handles[idx].Handle == (USHORT)ProcessHandle &&
ptr->Handles[idx].ObjectTypeNumber == 7){ // 7 : process
pid = ptr->Handles[idx].ProcessId;
break;
}
}
ExFreePool(proc);
}
else{
result = STATUS_UNSUCCESSFUL;
return result;
}
}
else if (NT_SUCCESS(result)){
proc = &dummy;
DbgPrint("ZwQuerySystemInformation Success!");
SYSTEM_HANDLE_INFORMATION *ptr = (SYSTEM_HANDLE_INFORMATION *)proc;
DbgPrint("Find pid from handle..");
for (ULONG idx = 0; idx < ptr->HandleCount; idx++){
DbgPrint("PID : %p", ptr->Handles[idx].Handle);
if ((HANDLE)ptr->Handles[idx].Handle == ProcessHandle){
DbgPrint("Successfully done.");
pid = ptr->Handles[idx].ProcessId;
break;
}
}
}
SYSTEM_PROCESS_INFORMATION dummy2 = { 0, };
result = ZwQuerySystemInformation(SystemProcessInformation, &dummy2, sizeof(SYSTEM_PROCESS_INFORMATION), &dum);
if (result == STATUS_INFO_LENGTH_MISMATCH){
proc = ExAllocatePoolWithTag(NonPagedPool, dum, 'GETK');
result = ZwQuerySystemInformation(SystemProcessInformation, proc, dum, &dum2);
if (NT_SUCCESS(result)){
SYSTEM_PROCESS_INFORMATION *ptr = (SYSTEM_PROCESS_INFORMATION *)proc;
for (; ptr; ptr = (SYSTEM_PROCESS_INFORMATION *)((char *)ptr + (ULONG)ptr->NextEntryDelta)){
if (pid == ptr->ProcessId){
PEPROCESS eProcess;
result = PsLookupProcessByProcessId((HANDLE)pid, &eProcess);
if (NT_SUCCESS(result)){
PVOID argu = NULL;
KAPC_STATE apc_state;
KeStackAttachProcess(eProcess, &apc_state);
argu = ExAllocatePoolWithTag(NonPagedPool,strlen(Argument) + 1, 'GETK');
if (argu == NULL)
return STATUS_UNSUCCESSFUL;
RtlCopyMemory(argu, Argument, strlen(Argument));
KeUnstackDetachProcess(&apc_state);
if (strstr((const char *)tolower((int)argu), ".dll") != NULL){ // DLL 파일이면
ExFreePool(argu);
return OrgZwCreateThreadEx(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle,
StartRoutine, NULL, CreateFlags, ZeroBits, StackSize, MaximumStackSize, AttributeList);
}
ExFreePool(argu);
return OrgZwCreateThreadEx(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle,
StartRoutine, Argument, CreateFlags, ZeroBits, StackSize, MaximumStackSize, AttributeList);
}
}
}
}
if (proc)
ExFreePool(proc);
return STATUS_SUCCESS;
}
else if (NT_SUCCESS(result)){
SYSTEM_PROCESS_INFORMATION *ptr = (SYSTEM_PROCESS_INFORMATION *)&dummy2;
for (; ptr; ptr = (SYSTEM_PROCESS_INFORMATION *)((char *)ptr + (ULONG)ptr->NextEntryDelta)){
if (pid == ptr->ProcessId){
PEPROCESS eProcess;
result = PsLookupProcessByProcessId((HANDLE)pid, &eProcess);
if (NT_SUCCESS(result)){
PVOID argu = NULL;
KAPC_STATE apc_state;
KeStackAttachProcess(eProcess, &apc_state);
argu = ExAllocatePoolWithTag(NonPagedPool, strlen(Argument) + 1, 'GETK');
if (argu == NULL)
return STATUS_UNSUCCESSFUL;
RtlCopyMemory(argu, Argument, strlen(Argument));
KeUnstackDetachProcess(&apc_state);
if (strstr((const char *)tolower((int)argu), ".dll") != NULL){ // DLL 파일이면
ExFreePool(argu);
return OrgZwCreateThreadEx(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle,
StartRoutine, NULL, CreateFlags, ZeroBits, StackSize, MaximumStackSize, AttributeList);
}
ExFreePool(argu);
return OrgZwCreateThreadEx(ThreadHandle, DesiredAccess, ObjectAttributes, ProcessHandle,
StartRoutine, Argument, CreateFlags, ZeroBits, StackSize, MaximumStackSize, AttributeList);
}
}
}
}
return STATUS_UNSUCCESSFUL;
}
}
NTSTATUS SetHookProc(){
DbgPrint("SetHookProc() Routine");
writeCR0();
OrgZwCreateThreadEx = (ZWCREATETHREADEX)SYSTEM_SERVICE_INDEX(ZWCREATETHREADEX_INDEX);
HOOK_SYSCALL_INDEX(ZWCREATETHREADEX_INDEX, ZwCreateThreadEx);
readCR0();
return STATUS_SUCCESS;
}
NTSTATUS SetUnHookProc(){
writeCR0();
HOOK_SYSCALL_INDEX(ZWCREATETHREADEX_INDEX, OrgZwCreateThreadEx);
readCR0();
return STATUS_SUCCESS;
}
void UnloadRoutine(IN PDRIVER_OBJECT DriverObject){
UNREFERENCED_PARAMETER(DriverObject);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Unloaded\n");
SetUnHookProc();
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath){
UNREFERENCED_PARAMETER(RegistryPath);
DbgPrint("DriverEntry!");
DbgPrint("DriverObject Unload Function Setting");
DriverObject->DriverUnload = UnloadRoutine;
SetHookProc();
return STATUS_SUCCESS;
}
접기