├── ProcLogger ├── ProcLogger.c ├── ProcLogger.h ├── RegMonitor.c ├── RegMonitor.h ├── SelfProtect.c ├── SelfProtect.h ├── loggers.c ├── loggers.h ├── utils.c └── utils.h └── README.md /ProcLogger/ProcLogger.c: -------------------------------------------------------------------------------- 1 | #include "ProcLogger.h" 2 | 3 | 4 | #pragma alloc_text(INIT, DriverEntry) 5 | 6 | 7 | NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) 8 | { 9 | UNREFERENCED_PARAMETER(RegistryPath); 10 | 11 | NTSTATUS Status = STATUS_SUCCESS; 12 | 13 | DriverObject->DriverUnload = DriverUnload; 14 | 15 | DbgPrint("[ ProcLogger ] Driver Loaded\n"); 16 | 17 | // installing Process Logger 18 | InstallProcLogger(); 19 | 20 | // installing Register Monitor 21 | InstallRegMonitor(DriverObject); 22 | 23 | // installing Self Protection 24 | InstallSelfProtect(); 25 | 26 | return Status; 27 | } 28 | 29 | 30 | VOID DriverUnload(PDRIVER_OBJECT DriverObject) { 31 | 32 | UNREFERENCED_PARAMETER(DriverObject); 33 | 34 | // Uninstalling Process Logger 35 | UnInstallProcLogger(); 36 | 37 | // Uninstalling Register Monitor 38 | UnInstallRegMonitor(); 39 | 40 | // Uninstalling Self Protection 41 | UnInstallSelfProtect(); 42 | 43 | DbgPrint("[ ProcLogger ] Driver Unloaded\n"); 44 | } 45 | -------------------------------------------------------------------------------- /ProcLogger/ProcLogger.h: -------------------------------------------------------------------------------- 1 | #include "loggers.h" 2 | #include "SelfProtect.h" 3 | #include "RegMonitor.h" 4 | 5 | 6 | NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath); 7 | VOID DriverUnload(IN PDRIVER_OBJECT DriverObject); 8 | 9 | -------------------------------------------------------------------------------- /ProcLogger/RegMonitor.c: -------------------------------------------------------------------------------- 1 | #include "RegMonitor.h"" 2 | 3 | 4 | #define REG_TAG 'Reg1' 5 | 6 | 7 | typedef struct _GLOBAL_CONTEXT { 8 | PDRIVER_OBJECT DriverObject; 9 | UNICODE_STRING Altitude; 10 | LARGE_INTEGER Cookie; 11 | } GLOBAL_CONTEXT, *PGLOBAL_CONTEXT; 12 | 13 | GLOBAL_CONTEXT g_GlobalContext = { 0 }; 14 | 15 | UNICODE_STRING g_PolicyKeyArray[] = { 16 | RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\System\\CurrentControlSet\\Services\\ProcLogger"), 17 | RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\System\\ControlSet001\\Services\\ProcLogger"), 18 | RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\System\\ControlSet002\\Services\\ProcLogger"), 19 | RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\System\\ControlSet003\\Services\\ProcLogger") 20 | }; 21 | ULONG g_PolicyKeyCount = sizeof(g_PolicyKeyArray) / sizeof(UNICODE_STRING); 22 | 23 | 24 | BOOLEAN CheckProcess(VOID) { 25 | PEPROCESS Process; 26 | PCHAR ImageFileName; 27 | 28 | Process = PsGetCurrentProcess(); 29 | 30 | ImageFileName = PsGetProcessImageFileName(Process); 31 | 32 | if (_stricmp(ImageFileName, "services.exe") == 0) { 33 | return TRUE; 34 | } 35 | 36 | if (_stricmp(ImageFileName, "svchost.exe") == 0) { 37 | return TRUE; 38 | } 39 | 40 | return FALSE; 41 | } 42 | 43 | 44 | BOOLEAN CheckPolicy(PUNICODE_STRING KeyFullPath) { 45 | 46 | BOOLEAN Matched = FALSE; 47 | ULONG Idx; 48 | 49 | for (Idx = 0; Idx < g_PolicyKeyCount; Idx++) { 50 | if (RtlEqualUnicodeString(KeyFullPath, &g_PolicyKeyArray[Idx], TRUE)) { 51 | Matched = TRUE; 52 | break; 53 | } 54 | } 55 | 56 | if (Matched) { 57 | DbgPrint("[ ProcLogger ] [ RegMonitor ] pid(%x) and tid(%x) Block %wZ\n", 58 | PsGetCurrentProcessId(), PsGetCurrentThreadId(), KeyFullPath); 59 | } 60 | 61 | return Matched; 62 | } 63 | 64 | 65 | NTSTATUS RegPreOpenKey(PVOID RootObject, PUNICODE_STRING CompleteName) 66 | { 67 | PUNICODE_STRING RootObjectName; 68 | ULONG_PTR RootObjectID; 69 | BOOLEAN Matched = FALSE; 70 | NTSTATUS Status; 71 | UNICODE_STRING KeyPath = { 0 }; 72 | 73 | // CompleteName can have a absolute path or relative path. 74 | // That's why we should do more work. 75 | 76 | // If RootObject is not valid, It means CompleteName has full path. 77 | // If RootObject is valid, we should work more. 78 | if (RootObject) { 79 | 80 | // We store path from RootObject to RootObjectName using CmCallbackGetKeyObjectID() 81 | if (!NT_SUCCESS(Status = CmCallbackGetKeyObjectID(&g_GlobalContext.Cookie, RootObject, &RootObjectID, &RootObjectName))) 82 | { 83 | DbgPrint("[ ProcLogger ] [ RegMonitor ] [ ERROR ] CmCallbackGetKeyObjectID : (%x)\n", Status); 84 | goto Exit; 85 | } 86 | 87 | // If there is valid CompleteName, we should concatenate RootObjectName and CompleteName. 88 | // If there isn't, just use RootObjectName. 89 | if (CompleteName->Length && CompleteName->Buffer) { 90 | 91 | KeyPath.MaximumLength = RootObjectName->Length + CompleteName->Length + (sizeof(WCHAR) * 2); 92 | 93 | KeyPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, KeyPath.MaximumLength, REG_TAG); 94 | 95 | if (!KeyPath.Buffer) { 96 | DbgPrint("[ ProcLogger ] [ RegMonitor ] [ Error ] ExAllocatePool() FAIL\n"); 97 | goto Exit; 98 | } 99 | 100 | swprintf(KeyPath.Buffer, L"%wZ\\%wZ", RootObjectName, CompleteName); 101 | KeyPath.Length = RootObjectName->Length + CompleteName->Length + (sizeof(WCHAR)); 102 | 103 | Matched = CheckPolicy(&KeyPath); 104 | } 105 | else { 106 | Matched = CheckPolicy(RootObjectName); 107 | 108 | } 109 | } 110 | else { 111 | Matched = CheckPolicy(CompleteName); 112 | } 113 | 114 | Exit: 115 | // if a buffer was allocated in KeyPath.Buffer then free it 116 | if (KeyPath.Buffer) { 117 | ExFreePoolWithTag(KeyPath.Buffer, REG_TAG); 118 | } 119 | return Matched; 120 | } 121 | 122 | 123 | NTSTATUS RegistryFilterCallback( 124 | IN PVOID CallbackContext, 125 | IN PVOID Argument1, 126 | IN PVOID Argument2 127 | ) { 128 | 129 | UNREFERENCED_PARAMETER(CallbackContext); 130 | NTSTATUS Status = STATUS_SUCCESS; 131 | REG_NOTIFY_CLASS NotifyClass = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1; 132 | 133 | if (CheckProcess()) { 134 | return Status; 135 | } 136 | 137 | if (NotifyClass == RegNtPreCreateKeyEx || NotifyClass == RegNtPreOpenKeyEx) 138 | { 139 | PREG_CREATE_KEY_INFORMATION RegInformation = (PREG_CREATE_KEY_INFORMATION)Argument2; 140 | 141 | if (RegPreOpenKey(RegInformation->RootObject, RegInformation->CompleteName)) 142 | { 143 | DbgPrint("[ ProcLogger ] [ RegMonitor ] Prevent Opening Handle\n"); 144 | Status = STATUS_ACCESS_DENIED; 145 | } 146 | } 147 | 148 | return Status; 149 | } 150 | 151 | 152 | NTSTATUS InstallRegMonitor(IN PDRIVER_OBJECT DriverObject) 153 | { 154 | NTSTATUS Status = STATUS_SUCCESS; 155 | RtlInitUnicodeString(&g_GlobalContext.Altitude, L"370000"); 156 | g_GlobalContext.DriverObject = DriverObject; 157 | 158 | if (!NT_SUCCESS(Status = CmRegisterCallbackEx( 159 | RegistryFilterCallback, 160 | &g_GlobalContext.Altitude, 161 | DriverObject, 162 | &g_GlobalContext, 163 | &g_GlobalContext.Cookie, 164 | NULL 165 | ))) { 166 | DbgPrint("[ ProcLogger ] [ RegMonitor ] [ ERROR ] CmRegisterCallbackEx Failed : (%x)\n", Status); 167 | return Status; 168 | } 169 | else { 170 | DbgPrint("[ ProcLogger ] [ RegMonitor ] [ SUCCESS ] CmRegisterCallbackEx Success\n"); 171 | } 172 | 173 | return STATUS_SUCCESS; 174 | } 175 | 176 | 177 | VOID UnInstallRegMonitor() 178 | { 179 | NTSTATUS Status; 180 | 181 | if (!NT_SUCCESS(Status = CmUnRegisterCallback(g_GlobalContext.Cookie))) { 182 | DbgPrint("[ ProcLogger ] [ RegMonitor ] [ ERROR ] CmUnRegisterCallback Failed (%x)\n", Status); 183 | return Status; 184 | } 185 | else { 186 | DbgPrint("[ ProcLogger ] [ RegMonitor ] [ SUCCESS ] CmUnRegisterCallback Success\n"); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /ProcLogger/RegMonitor.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utils.h" 4 | 5 | 6 | BOOLEAN CheckProcess(VOID); 7 | BOOLEAN CheckPolicy(PUNICODE_STRING KeyFullPath); 8 | NTSTATUS RegPreOpenKey(PVOID RootObject, PUNICODE_STRING CompleteName); 9 | NTSTATUS RegistryFilterCallback( 10 | IN PVOID CallbackContext, 11 | IN PVOID Argument1, 12 | IN PVOID Argument2 13 | ); 14 | NTSTATUS InstallRegMonitor(IN PDRIVER_OBJECT DriverObject); 15 | VOID UnInstallRegMonitor(); 16 | 17 | -------------------------------------------------------------------------------- /ProcLogger/SelfProtect.c: -------------------------------------------------------------------------------- 1 | #include "SelfProtect.h" 2 | 3 | 4 | PVOID RegistrationHandle = NULL; 5 | HANDLE ProtectedProcess = NULL; 6 | 7 | PACCESS_MASK thisis = NULL; 8 | ACCESS_MASK thisis2 = 0; 9 | 10 | 11 | OB_PREOP_CALLBACK_STATUS 12 | ObjectPreCallBack(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation) { 13 | 14 | LPSTR ProcssName; 15 | 16 | PACCESS_MASK DesiredAccess = NULL; 17 | ACCESS_MASK OriginalDesiredAccess = 0; 18 | 19 | HANDLE ProcessIdOfTargetThread; 20 | 21 | if (OperationInformation->ObjectType == *PsProcessType) { 22 | if (OperationInformation->Object == PsGetCurrentProcess()) { 23 | //DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL,"ObCallbackTest: CBTdPreOperationCallback: ignore process open/duplicate from the protected process itself\n"); 24 | return OB_PREOP_SUCCESS; 25 | } 26 | } 27 | else if (OperationInformation->ObjectType == *PsThreadType) { 28 | ProcessIdOfTargetThread = PsGetThreadProcessId((PETHREAD)OperationInformation->Object); 29 | if (ProcessIdOfTargetThread == PsGetCurrentProcessId()) { 30 | //DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL,"ObCallbackTest: CBTdPreOperationCallback: ignore thread open/duplicate from the protected process itself\n"); 31 | return OB_PREOP_SUCCESS; 32 | } 33 | } 34 | else { 35 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[ ProcLogger ] [ SelfProtect ] [ Error ] ObCallbackTest: CBTdPreOperationCallback: unexpected object type\n"); 36 | return OB_PREOP_SUCCESS; 37 | } 38 | 39 | ProcssName = GetProcessNameFromPid(PsGetProcessId((PEPROCESS)OperationInformation->Object)); 40 | 41 | if (OperationInformation->KernelHandle == 1) { 42 | //DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[ SelfProtect ] [ KERNEL ] ObjectPreCallback ----> Process Name [%s] \n", ProcssName); 43 | return OB_PREOP_SUCCESS; 44 | } 45 | 46 | //DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[ ProcLogger ] [ SelfProtect ] [ USER ] ObjectPreCallback ----> Process Name [%s] \n", ProcssName); 47 | 48 | // Write file name want to protect 49 | if (!_stricmp(ProcssName, "notepad.exe")) { 50 | DbgPrint("[ ProcLogger ] [ SelfProtect ] - notepad - is protected \n"); 51 | if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) { 52 | 53 | DesiredAccess = &OperationInformation->Parameters->CreateHandleInformation.DesiredAccess; 54 | OriginalDesiredAccess = OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess; 55 | 56 | if ((OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE) { 57 | *DesiredAccess &= ~PROCESS_TERMINATE; 58 | //DbgPrint("[ SelfProtect ] [ CreateHandleInformation ] Disabling terminate \n"); 59 | } 60 | 61 | if ((OriginalDesiredAccess & PROCESS_VM_OPERATION) == PROCESS_VM_OPERATION) { 62 | *DesiredAccess &= ~PROCESS_VM_OPERATION; 63 | //DbgPrint("[ SelfProtect ] [ CreateHandleInformation ] Disabling vm operation \n"); 64 | } 65 | if ((OriginalDesiredAccess & ~PROCESS_VM_READ) == PROCESS_VM_READ) { 66 | *DesiredAccess &= ~PROCESS_VM_READ; 67 | //DbgPrint("[ SelfProtect ] [ CreateHandleInformation ] Disabling vm read \n"); 68 | } 69 | if ((OriginalDesiredAccess & PROCESS_VM_WRITE) == PROCESS_VM_WRITE) { 70 | *DesiredAccess &= ~PROCESS_VM_WRITE; 71 | //DbgPrint("[ SelfProtect ] [ CreateHandleInformation ] Disabling vm write \n"); 72 | } 73 | 74 | } 75 | else if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE) { 76 | 77 | DesiredAccess = &OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess; 78 | OriginalDesiredAccess = OperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess; 79 | 80 | if ((OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE) { 81 | *DesiredAccess &= ~PROCESS_TERMINATE; 82 | //DbgPrint("[ SelfProtect ] [ DuplicateHandleInformation ] Disabling terminate \n"); 83 | } 84 | if ((OriginalDesiredAccess & PROCESS_VM_OPERATION) == PROCESS_VM_OPERATION) { 85 | *DesiredAccess &= ~PROCESS_VM_OPERATION; 86 | //DbgPrint("[ SelfProtect ] [ DuplicateHandleInformation ] Disabling vm operation \n"); 87 | } 88 | if ((OriginalDesiredAccess & ~PROCESS_VM_READ) == PROCESS_VM_READ) { 89 | *DesiredAccess &= ~PROCESS_VM_READ; 90 | //DbgPrint("[ SelfProtect ] [ DuplicateHandleInformation ] Disabling vm read \n"); 91 | } 92 | if ((OriginalDesiredAccess & PROCESS_VM_WRITE) == PROCESS_VM_WRITE) { 93 | *DesiredAccess &= ~PROCESS_VM_WRITE; 94 | //DbgPrint("[ SelfProtect ] [ DuplicateHandleInformation ] Disabling vm write \n"); 95 | } 96 | 97 | } 98 | } 99 | 100 | return OB_PREOP_SUCCESS; 101 | } 102 | 103 | 104 | VOID ObjectPostCallBack(IN PVOID RegistrationContext, IN POB_POST_OPERATION_INFORMATION OperationInformation) { 105 | } 106 | 107 | 108 | NTSTATUS InstallSelfProtect() { 109 | 110 | NTSTATUS Status; 111 | OB_CALLBACK_REGISTRATION CallBackRegistration; 112 | OB_OPERATION_REGISTRATION OperationRegistration; 113 | 114 | OperationRegistration.ObjectType = PsProcessType; 115 | OperationRegistration.Operations = OB_OPERATION_HANDLE_CREATE; // For creating handle. 116 | OperationRegistration.PreOperation = ObjectPreCallBack; // Registering Callback function. 117 | OperationRegistration.PostOperation = ObjectPostCallBack; 118 | 119 | RtlInitUnicodeString(&CallBackRegistration.Altitude, L"370000"); 120 | CallBackRegistration.Version = OB_FLT_REGISTRATION_VERSION; 121 | CallBackRegistration.OperationRegistrationCount = 1; 122 | CallBackRegistration.RegistrationContext = NULL; 123 | CallBackRegistration.OperationRegistration = &OperationRegistration; 124 | 125 | // [[ ObRegisterCallbacks() ]] 126 | if (!NT_SUCCESS(Status = ObRegisterCallbacks(&CallBackRegistration, &RegistrationHandle))) { 127 | DbgPrint("[ ProcLogger ] [ SelfProtect ] [ ERROR ] ObRegisterCallbacks Failed : (%x)\n", Status); 128 | return Status; 129 | } 130 | else { 131 | DbgPrint("[ ProcLogger ] [ SelfProtect ] [ SUCCESS ] ObRegisterCallbacks Success\n"); 132 | } 133 | 134 | return STATUS_SUCCESS; 135 | 136 | } 137 | 138 | 139 | VOID UnInstallSelfProtect() { 140 | 141 | if (RegistrationHandle) { 142 | ObUnRegisterCallbacks(RegistrationHandle); 143 | DbgPrint("[ ProcLogger ] [ SelfProtect ] [ SUCCESS ] ObResiterCallbacks Success\n"); 144 | } 145 | else { 146 | DbgPrint("[ ProcLogger ] [ SelfProtect ] [ ERROR ] ObResiterCallbacks Failed\n"); 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /ProcLogger/SelfProtect.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utils.h" 3 | 4 | 5 | #define PROCESS_TERMINATE (0x0001) 6 | #define PROCESS_VM_READ (0x0010) 7 | #define PROCESS_VM_WRITE (0x0020) 8 | #define PROCESS_VM_OPERATION (0x0008) 9 | 10 | 11 | OB_PREOP_CALLBACK_STATUS ObjectPreCallBack(IN PVOID RegistrationContext, IN POB_PRE_OPERATION_INFORMATION OperationInformation); 12 | VOID ObjectPostCallBack(IN PVOID RegistrationContext, IN POB_POST_OPERATION_INFORMATION OperationInformation); 13 | NTSTATUS InstallSelfProtect(); 14 | VOID UnInstallSelfProtect(); 15 | -------------------------------------------------------------------------------- /ProcLogger/loggers.c: -------------------------------------------------------------------------------- 1 | #include "loggers.h" 2 | 3 | 4 | #define MY_TAG 'Tag1' 5 | 6 | 7 | VOID ProcessNotifyCallbackEx( 8 | PEPROCESS Process, 9 | HANDLE ProcessId, 10 | PPS_CREATE_NOTIFY_INFO CreateInfo) 11 | { 12 | 13 | 14 | ///* Declation of Variables */// 15 | 16 | /* Create or Exit */ 17 | BOOLEAN boolCreateExit = FALSE; 18 | PUNICODE_STRING CreateOrExit = NULL; 19 | 20 | UNICODE_STRING CreateAndExit[] = { 21 | RTL_CONSTANT_STRING(L"CREATE"), 22 | RTL_CONSTANT_STRING(L"EXIT") 23 | }; 24 | 25 | /* Get Time */ 26 | LARGE_INTEGER CurrentGMTTime; 27 | LARGE_INTEGER CurrentLocalTime; 28 | TIME_FIELDS CurrentLocalTimeField; 29 | 30 | /* Get Integrity Level */ 31 | ULONG dwIntegrityLevel = 0; 32 | PACCESS_TOKEN pAccessToken; 33 | PUNICODE_STRING ilevel = NULL; 34 | 35 | UNICODE_STRING IntegrityLevel[] = { 36 | RTL_CONSTANT_STRING(L"LOW"), 37 | RTL_CONSTANT_STRING(L"MEDIUM"), 38 | RTL_CONSTANT_STRING(L"HIGH"), 39 | RTL_CONSTANT_STRING(L"SYSTEM") 40 | }; 41 | 42 | /* To Log */ 43 | UNICODE_STRING LogFileName; 44 | OBJECT_ATTRIBUTES ObjAttr; 45 | NTSTATUS Status = STATUS_SUCCESS; 46 | HANDLE hLogFile; 47 | IO_STATUS_BLOCK IOStatus; 48 | PCHAR LogEntryText; 49 | ULONG LogEntryTextLen; 50 | LARGE_INTEGER liFileOffset; 51 | 52 | 53 | 54 | 55 | ///* Routines */// 56 | 57 | /* Get Time */ 58 | KeQuerySystemTime(&CurrentGMTTime); 59 | ExSystemTimeToLocalTime(&CurrentGMTTime, &CurrentLocalTime); 60 | RtlTimeToTimeFields(&CurrentLocalTime, &CurrentLocalTimeField); 61 | 62 | 63 | /* Get Integrity Level */ 64 | pAccessToken = PsReferencePrimaryToken(Process); 65 | SeQueryInformationToken(pAccessToken, TokenIntegrityLevel, (PVOID*)&dwIntegrityLevel); 66 | 67 | if (dwIntegrityLevel == SECURITY_MANDATORY_LOW_RID) { 68 | ilevel = &IntegrityLevel[0]; // Low Integrity 69 | } 70 | else if (dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID && dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID) { 71 | ilevel = &IntegrityLevel[1]; // Medium Integrity 72 | } 73 | else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID) { 74 | ilevel = &IntegrityLevel[2]; // High Integrity 75 | } 76 | else if (dwIntegrityLevel >= SECURITY_MANDATORY_SYSTEM_RID) { 77 | ilevel = &IntegrityLevel[3]; // System Integrity 78 | } 79 | 80 | 81 | /* Create or Exit */ 82 | if (CreateInfo != NULL) { 83 | boolCreateExit = TRUE; 84 | } 85 | 86 | 87 | /* To Log */ 88 | 89 | RtlInitUnicodeString(&LogFileName, L"\\??\\C:\\ProcLogger.log"); 90 | 91 | InitializeObjectAttributes( 92 | &ObjAttr, 93 | &LogFileName, 94 | OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 95 | NULL, NULL); 96 | 97 | if (!NT_SUCCESS(Status = ZwCreateFile( 98 | &hLogFile, 99 | GENERIC_WRITE, 100 | &ObjAttr, 101 | &IOStatus, 102 | NULL, 103 | FILE_ATTRIBUTE_NORMAL, 104 | FILE_SHARE_READ | FILE_SHARE_WRITE, 105 | FILE_OPEN_IF, 106 | FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, 107 | NULL, 0))) 108 | { 109 | DbgPrint("[ ProcLogger ] [ Log ] [ Error ] zwWriteFile Error (0x%p)\n", (void*)Status); 110 | return; 111 | } 112 | 113 | // Allocating memory in kernel 114 | LogEntryText = ExAllocatePoolWithTag(PagedPool, 1024, MY_TAG); 115 | 116 | // For Creation 117 | if (boolCreateExit) { 118 | CreateOrExit = &CreateAndExit[0]; 119 | 120 | // See DebugView.exe 121 | DbgPrint("[ ProcLogger ] [ Log ] [ %d:%d:%d:%d:%d:%d ] [ %wZ ] [ %wZ ] [ %s (%Ix) ] [ %s (%Ix) ] [ %s (%Ix) ] [ %wZ ] \n", 122 | CurrentLocalTimeField.Year, 123 | CurrentLocalTimeField.Month, 124 | CurrentLocalTimeField.Day, 125 | CurrentLocalTimeField.Hour, 126 | CurrentLocalTimeField.Minute, 127 | CurrentLocalTimeField.Second, 128 | CreateOrExit, 129 | CreateInfo->ImageFileName, 130 | GetProcessNameFromPid(ProcessId), 131 | (ULONG_PTR)ProcessId, 132 | GetProcessNameFromPid(CreateInfo->ParentProcessId), 133 | (ULONG_PTR)CreateInfo->ParentProcessId, 134 | GetProcessNameFromPid(CreateInfo->CreatingThreadId.UniqueProcess), 135 | (ULONG_PTR)CreateInfo->CreatingThreadId.UniqueProcess, 136 | ilevel 137 | ); 138 | 139 | // Set logs 140 | sprintf( 141 | LogEntryText, 142 | "[ %d:%d:%d:%d:%d:%d ] [ %wZ ] [ %wZ ] [ %s (%Ix) ] [ %s (%Ix) ] [ %s (%Ix) ] [ %wZ ] \r\n", 143 | CurrentLocalTimeField.Year, 144 | CurrentLocalTimeField.Month, 145 | CurrentLocalTimeField.Day, 146 | CurrentLocalTimeField.Hour, 147 | CurrentLocalTimeField.Minute, 148 | CurrentLocalTimeField.Second, 149 | CreateOrExit, 150 | CreateInfo->ImageFileName, 151 | GetProcessNameFromPid(ProcessId), 152 | (ULONG_PTR)ProcessId, 153 | GetProcessNameFromPid(CreateInfo->ParentProcessId), 154 | (ULONG_PTR)CreateInfo->ParentProcessId, 155 | GetProcessNameFromPid(CreateInfo->CreatingThreadId.UniqueProcess), 156 | (ULONG_PTR)CreateInfo->CreatingThreadId.UniqueProcess, 157 | ilevel 158 | ); 159 | 160 | // For Exit 161 | } 162 | else { 163 | CreateOrExit = &CreateAndExit[1]; 164 | 165 | // See DebugView.exe 166 | DbgPrint("[ ProcLogger ] [ Log ] [ %d:%d:%d:%d:%d:%d ] [ %wZ ] [ N/A ] [ %s (%Ix) ] [ N/A ] [ N/A ] [ %wZ ] \n", 167 | CurrentLocalTimeField.Year, 168 | CurrentLocalTimeField.Month, 169 | CurrentLocalTimeField.Day, 170 | CurrentLocalTimeField.Hour, 171 | CurrentLocalTimeField.Minute, 172 | CurrentLocalTimeField.Second, 173 | CreateOrExit, 174 | GetProcessNameFromPid(ProcessId), 175 | (ULONG_PTR)ProcessId, 176 | ilevel 177 | ); 178 | 179 | // Set logs 180 | sprintf( 181 | LogEntryText, 182 | "[ %d:%d:%d:%d:%d:%d ] [ %wZ ] [ N/A ] [ %s (%Ix) ] [ N/A ] [ N/A ] [ %wZ ] \r\n", 183 | CurrentLocalTimeField.Year, 184 | CurrentLocalTimeField.Month, 185 | CurrentLocalTimeField.Day, 186 | CurrentLocalTimeField.Hour, 187 | CurrentLocalTimeField.Minute, 188 | CurrentLocalTimeField.Second, 189 | CreateOrExit, 190 | GetProcessNameFromPid(ProcessId), 191 | (ULONG_PTR)ProcessId, 192 | ilevel 193 | ); 194 | } 195 | 196 | LogEntryTextLen = strlen(LogEntryText); 197 | 198 | liFileOffset.HighPart = -1; 199 | liFileOffset.LowPart = FILE_WRITE_TO_END_OF_FILE; 200 | 201 | // Writing logs 202 | Status = ZwWriteFile( 203 | hLogFile, 204 | NULL, NULL, NULL, 205 | &IOStatus, 206 | LogEntryText, 207 | LogEntryTextLen, 208 | &liFileOffset, 209 | NULL); 210 | 211 | if (!NT_SUCCESS(Status)) { 212 | DbgPrint("[ ProcLogger ] [ Log ] [ Error ] zwWriteFile Fail (0x%x)", Status); 213 | ZwClose(hLogFile); 214 | return; 215 | } 216 | 217 | 218 | /* End */ 219 | 220 | // Free memory in kernel 221 | ExFreePoolWithTag(LogEntryText, MY_TAG); 222 | 223 | ZwClose(hLogFile); 224 | 225 | return; 226 | } 227 | 228 | 229 | 230 | 231 | NTSTATUS InstallProcLogger() { 232 | NTSTATUS Status = STATUS_SUCCESS; 233 | 234 | if (!NT_SUCCESS(Status = PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallbackEx, FALSE))) 235 | { 236 | DbgPrint("[ ProcLogger ] [ Log ] [ ERROR ] Resistering PsSetCreateProcessNotifyRoutineEx Failed : (%x)\n", Status); 237 | return Status; 238 | } 239 | else { 240 | DbgPrint("[ ProcLogger ] [ Log ] [ SUCCESS ] Resistering PsSetCreateProcessNotifyRoutineEx Success\n"); 241 | } 242 | 243 | return STATUS_SUCCESS; 244 | 245 | } 246 | 247 | 248 | 249 | 250 | VOID UnInstallProcLogger() { 251 | 252 | NTSTATUS Status = STATUS_SUCCESS; 253 | 254 | if (!NT_SUCCESS(Status = PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallbackEx, TRUE))) { 255 | DbgPrint("[ ProcLogger ] [ Log ] [ ERROR ] Unresistering PsSetCreateProcessNotifyRoutineEx Failed : (%x)\n", Status); 256 | } 257 | else { 258 | DbgPrint("[ ProcLogger ] [ Log ] [ SUCCESS ] Unresistering PsSetCreateProcessNotifyRoutineEx Success\n"); 259 | } 260 | 261 | } 262 | -------------------------------------------------------------------------------- /ProcLogger/loggers.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utils.h" 4 | 5 | 6 | extern UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process); 7 | 8 | 9 | VOID ProcessNotifyCallbackEx( 10 | PEPROCESS Process, 11 | HANDLE ProcessId, 12 | PPS_CREATE_NOTIFY_INFO CreateInfo); 13 | NTSTATUS InstallProcLogger(); 14 | VOID UnInstallProcLogger(); 15 | 16 | -------------------------------------------------------------------------------- /ProcLogger/utils.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | 4 | char * GetProcessNameFromPid(HANDLE pid) 5 | { 6 | PEPROCESS Process; 7 | if (PsLookupProcessByProcessId(pid, &Process) == STATUS_INVALID_PARAMETER) 8 | { 9 | return "??"; 10 | } 11 | return (CHAR*)PsGetProcessImageFileName(Process); 12 | } 13 | -------------------------------------------------------------------------------- /ProcLogger/utils.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process); 4 | 5 | LPSTR GetProcessNameFromPid(HANDLE pid); 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ProcLogger 2 | Windows Simple Process Logger implemented as driver 3 | 4 | 5 | 6 | ## Blog 7 | [ http://sanseolab.tistory.com/38 ] 8 | 9 | 10 | ## Result 11 | ![start](http://cfile6.uf.tistory.com/image/9904653359F38C9A2251B3) 12 | --------------------------------------------------------------------------------