Compare commits
2
Commits
v0.3.0
...
99813ae2a3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99813ae2a3 | ||
|
|
90cf4927af |
@@ -168,6 +168,27 @@ Sanctum schützt vertrauliche Daten vor unbeabsichtigten Windows-Spuren:
|
||||
1. **Anti-Leak Dateifilter**: Unterdrückt das Anlegen von `Thumbs.db`, `desktop.ini`, Office-Sperrdateien (`~$*`), temporären Dateien (`*.tmp`) und NTFS Alternate Data Streams (`:Zone.Identifier`).
|
||||
2. **Inactivity Auto-Lock**: Erkennt Inaktivität anhand echter Lese-/Schreibzugriffe und trennt den Container automatisch nach Erreichen des Timeouts.
|
||||
3. **Session Lock Detection**: Reagiert über `WTSRegisterSessionNotification` sofort auf Windows-Sitzungssperren (`Win + L`) oder Abmeldungen und schließt den Container blitzschnell ab.
|
||||
4. **RAM-Paging-Schutz (`VirtualLock`)**: Verriegelt sensible Schlüsselstrukturen (`DEK`) im physischen RAM, um das Auslagern in `pagefile.sys` oder `swapfile.sys` durch den Windows Memory Manager zu verhindern.
|
||||
5. **DFIR ShellBag-Schutz**: Unterdrückt das automatische Öffnen des Windows Explorers für den Hidden Vault, um zu verhindern, dass vertrauliche Ordnernamen persistent in `UsrClass.dat` protokolliert werden.
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Windows-Kompatibilität & AV/EDR-Tuning
|
||||
|
||||
### Windows Defender SmartScreen ("Unbekannter Herausgeber")
|
||||
Wird die Binärdatei über einen Webbrowser heruntergeladen, versieht Windows sie mit dem *Mark-of-the-Web* (MotW). Da Open-Source-Projekte über kein kostenpflichtiges EV-Code-Signing-Zertifikat verfügen, zeigt Windows beim ersten Start den blauen SmartScreen-Dialog:
|
||||
- **Einmalige Freigabe im Dialog:** Klick auf **"Weitere Informationen"** $\to$ **"Trotzdem ausführen"**.
|
||||
- **Schnellfreigabe via PowerShell:**
|
||||
```powershell
|
||||
Unblock-File .\sanctum.exe
|
||||
```
|
||||
|
||||
### Windows Defender "Überwachter Ordnerzugriff" (Controlled Folder Access - CFA)
|
||||
Ist der erweiterte Ransomware-Schutz von Windows aktiv, kann Defender den Schreibzugriff auf Containerdateien in Standard-Benutzerordnern (`Dokumente`, `Desktop`) mit Fehler 5 (*Zugriff verweigert*) blockieren:
|
||||
- **Abhilfe:** Erlauben Sie `sanctum.exe` in den Windows-Sicherheitseinstellungen (*Viren- & Bedrohungsschutz* $\to$ *Ransomware-Schutz verwalten* $\to$ *App durch überwachten Ordnerzugriff zulassen*), oder speichern Sie Container in einem separaten Verzeichnis (z. B. `C:\Sanctum\`).
|
||||
|
||||
### I/O-Performance-Tuning
|
||||
Windows Defender scannt standardmäßig jeden modifizierten 1-MB-Chunk in Echtzeit. Durch das Hinzufügen der Dateiendung `*.sanctum` zu den Defender-Ausschlüssen lässt sich der I/O-Durchsatz bei großen Kopiervorgängen um 30–50% steigern.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -106,23 +106,32 @@ if (-not $Release) {
|
||||
|
||||
|
||||
$UploadUrl = "$GiteaUrl/api/v1/repos/$Owner/$Repo/releases/$($Release.id)/assets"
|
||||
$AuthHeader = "Authorization: token $Token"
|
||||
|
||||
# ZIP Asset hochladen
|
||||
Write-Host "Lade sanctum-$TagName-windows-x86_64.zip hoch..." -ForegroundColor Cyan
|
||||
$ZipResult = & curl.exe -s -X POST "$UploadUrl?name=sanctum-$TagName-windows-x86_64.zip" `
|
||||
-H "Authorization: token $Token" `
|
||||
-F "attachment=@$ZipFile"
|
||||
|
||||
$ZipPathNorm = $ZipFile.Replace('\', '/')
|
||||
$ZipUrl = "$UploadUrl?name=sanctum-$TagName-windows-x86_64.zip"
|
||||
$ZipResult = & curl.exe -s -X POST $ZipUrl -H $AuthHeader -F "attachment=@$ZipPathNorm"
|
||||
Write-Host "[OK] sanctum-$TagName-windows-x86_64.zip hochgeladen." -ForegroundColor Green
|
||||
|
||||
# SHA256SUMS.txt hochladen
|
||||
Write-Host "Lade SHA256SUMS.txt hoch..." -ForegroundColor Cyan
|
||||
$SumResult = & curl.exe -s -X POST "$UploadUrl?name=SHA256SUMS.txt" `
|
||||
-H "Authorization: token $Token" `
|
||||
-F "attachment=@$ChecksumFile"
|
||||
|
||||
$SumPathNorm = $ChecksumFile.Replace('\', '/')
|
||||
$SumUrl = "$UploadUrl?name=SHA256SUMS.txt"
|
||||
$SumResult = & curl.exe -s -X POST $SumUrl -H $AuthHeader -F "attachment=@$SumPathNorm"
|
||||
Write-Host "[OK] SHA256SUMS.txt hochgeladen." -ForegroundColor Green
|
||||
|
||||
# Standalone EXE hochladen
|
||||
$ExeFile = Join-Path $ProjectRoot "target\release\sanctum.exe"
|
||||
if (Test-Path $ExeFile) {
|
||||
Write-Host "Lade sanctum.exe hoch..." -ForegroundColor Cyan
|
||||
$ExePathNorm = $ExeFile.Replace('\', '/')
|
||||
$ExeUrl = "$UploadUrl?name=sanctum.exe"
|
||||
$ExeResult = & curl.exe -s -X POST $ExeUrl -H $AuthHeader -F "attachment=@$ExePathNorm"
|
||||
Write-Host "[OK] sanctum.exe hochgeladen." -ForegroundColor Green
|
||||
}
|
||||
|
||||
|
||||
Write-Host "`n============================================================" -ForegroundColor Green
|
||||
Write-Host " Release $TagName erfolgreich auf Gitea veroeffentlicht!" -ForegroundColor Green
|
||||
|
||||
@@ -345,6 +345,13 @@ impl CarrierFsInner {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for CarrierFsInner {
|
||||
fn drop(&mut self) {
|
||||
crate::windows::unlock_memory(self.dek_outer.as_ptr(), 32);
|
||||
crate::windows::unlock_memory(self.dek_inner.as_ptr(), 32);
|
||||
}
|
||||
}
|
||||
|
||||
/// WebDAV-Filesystem-Treiber für den steganografischen Alibi-Carrier (Hidden Vault).
|
||||
#[derive(Clone)]
|
||||
pub struct CarrierFs {
|
||||
@@ -380,6 +387,10 @@ impl CarrierFs {
|
||||
.map(|d| d.as_secs())
|
||||
.unwrap_or(0);
|
||||
|
||||
// Forensischer RAM-Paging-Schutz via VirtualLock
|
||||
crate::windows::lock_memory(dek_outer.as_ptr(), 32);
|
||||
crate::windows::lock_memory(dek_inner.as_ptr(), 32);
|
||||
|
||||
let inner = CarrierFsInner {
|
||||
db,
|
||||
carrier_node_id,
|
||||
|
||||
+10
-2
@@ -239,9 +239,17 @@ pub async fn mount_container(
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
// Optional automatisch im Windows Explorer öffnen
|
||||
// Optional automatisch im Windows Explorer öffnen (mit DFIR ShellBag-Schutz für Hidden Vault)
|
||||
if open_explorer {
|
||||
let _ = crate::windows::open_in_explorer(drive_letter);
|
||||
if vault_id == 1 {
|
||||
println!(
|
||||
" {} {}",
|
||||
ui::yellow("[!]"),
|
||||
ui::dim("OpSec-Schutz: Explorer-Auto-Open für Hidden Vault unterdrückt (verhindert persistente ShellBag-Spuren in UsrClass.dat).")
|
||||
);
|
||||
} else {
|
||||
let _ = crate::windows::open_in_explorer(drive_letter);
|
||||
}
|
||||
}
|
||||
|
||||
// System-Tray Initialisierung
|
||||
|
||||
+19
-1
@@ -158,7 +158,25 @@ fn current_timestamp() -> u64 {
|
||||
impl Database {
|
||||
/// Öffnet oder erstellt die Container-Datenbank und initialisiert die Pragmas.
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||
let conn = Connection::open(path)?;
|
||||
let path_ref = path.as_ref();
|
||||
let conn = match Connection::open(path_ref) {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
let err_str = e.to_string();
|
||||
if err_str.contains("Access is denied")
|
||||
|| err_str.contains("permission denied")
|
||||
|| err_str.contains("os error 5")
|
||||
{
|
||||
bail!(
|
||||
"Zugriff auf '{}' verweigert (OS Fehler 5 / Access Denied).\n\
|
||||
[!] Möglicherweise blockiert durch Windows Defender 'Überwachter Ordnerzugriff' (Controlled Folder Access).\n\
|
||||
[i] Abhilfe: Fügen Sie 'sanctum.exe' in den Windows-Sicherheitseinstellungen (Viren- & Bedrohungsschutz -> Ransomware-Schutz -> Überwachter Ordnerzugriff) als erlaubte App hinzu, oder platzieren Sie den Container außerhalb geschützter Benutzerordner.",
|
||||
path_ref.display()
|
||||
);
|
||||
}
|
||||
return Err(e.into());
|
||||
}
|
||||
};
|
||||
let db = Self {
|
||||
conn: Arc::new(Mutex::new(conn)),
|
||||
};
|
||||
|
||||
+15
@@ -469,6 +469,12 @@ impl SanctumFs {
|
||||
None
|
||||
};
|
||||
|
||||
// Forensischer RAM-Paging-Schutz via VirtualLock (verhindert Auslagerung in pagefile.sys)
|
||||
crate::windows::lock_memory(dek_arc.as_ptr(), 32);
|
||||
if let Some(ref c_dek) = carrier_dek_arc {
|
||||
crate::windows::lock_memory(c_dek.as_ptr(), 32);
|
||||
}
|
||||
|
||||
Self {
|
||||
db,
|
||||
dek: dek_arc,
|
||||
@@ -550,6 +556,15 @@ impl SanctumFs {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SanctumFs {
|
||||
fn drop(&mut self) {
|
||||
crate::windows::unlock_memory(self.dek.as_ptr(), 32);
|
||||
if let Some(ref c_dek) = self.carrier_dek {
|
||||
crate::windows::unlock_memory(c_dek.as_ptr(), 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DavFileSystem for SanctumFs {
|
||||
fn open<'a>(
|
||||
&'a self,
|
||||
|
||||
@@ -527,10 +527,56 @@ pub fn start_console_ctrl_monitor(
|
||||
}
|
||||
}
|
||||
|
||||
/// Verriegelt einen Speicherbereich im physischen RAM (verhindert Paging in pagefile.sys / swapfile.sys).
|
||||
pub fn lock_memory(ptr: *const u8, len: usize) -> bool {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
extern "system" {
|
||||
fn VirtualLock(lpaddress: *const std::ffi::c_void, dwsize: usize) -> i32;
|
||||
}
|
||||
if ptr.is_null() || len == 0 {
|
||||
return false;
|
||||
}
|
||||
unsafe { VirtualLock(ptr as *const std::ffi::c_void, len) != 0 }
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
let _ = (ptr, len);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Entriegelt einen zuvor mit `lock_memory` geschützten Speicherbereich im RAM.
|
||||
pub fn unlock_memory(ptr: *const u8, len: usize) -> bool {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
extern "system" {
|
||||
fn VirtualUnlock(lpaddress: *const std::ffi::c_void, dwsize: usize) -> i32;
|
||||
}
|
||||
if ptr.is_null() || len == 0 {
|
||||
return false;
|
||||
}
|
||||
unsafe { VirtualUnlock(ptr as *const std::ffi::c_void, len) != 0 }
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
let _ = (ptr, len);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_virtual_lock_memory_lifecycle() {
|
||||
let buffer = vec![0x42u8; 4096];
|
||||
let _ = lock_memory(buffer.as_ptr(), buffer.len());
|
||||
let _ = unlock_memory(buffer.as_ptr(), buffer.len());
|
||||
assert_eq!(buffer[0], 0x42);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_next_available_drive() {
|
||||
let drive = find_next_available_drive().expect("Find next drive");
|
||||
|
||||
Reference in New Issue
Block a user