{"metadata": {"vulnerability": "cve-2018-19320", "count": 45, "kinds": {"milestone": 4, "sighting": 13, "kev": 11, "other": 17}}, "data": [{"timestamp": "2018-11-16T00:00:00Z", "date_only": false, "value": "2018-11-16T00:00:00.000Z", "kind": "milestone", "label": "Reserved", "source": "cvelistv5", "record": "cve-2018-19320", "field": "cveMetadata.dateReserved"}, {"timestamp": "2018-12-18T00:00:00Z", "date_only": false, "value": "2018-12-18T00:00:00.000Z", "kind": "other", "label": "Made public", "source": "cvelistv5 / mitre", "record": "cve-2018-19320", "field": "containers.cna.datePublic"}, {"timestamp": "2018-12-21T23:00:00Z", "date_only": false, "value": "2018-12-21T23:00:00.000Z", "kind": "milestone", "label": "Published", "source": "cvelistv5", "record": "cve-2018-19320", "field": "cveMetadata.datePublished"}, {"timestamp": "2018-12-21T23:29:00Z", "date_only": false, "value": "2018-12-21T23:29:00Z", "kind": "other", "label": "Nvd published at", "source": "github \u00b7 GHSA-WG2V-FX2J-3JRR", "record": "GHSA-WG2V-FX2J-3JRR", "field": "database_specific.nvd_published_at"}, {"timestamp": "2018-12-21T23:29:00Z", "date_only": false, "value": "2018-12-21T23:29Z", "kind": "other", "label": "Published Date", "source": "gsd \u00b7 GSD-2018-19320", "record": "GSD-2018-19320", "field": "namespaces.nvd.nist.gov.publishedDate"}, {"timestamp": "2018-12-21T23:29:00.493Z", "date_only": false, "value": "2018-12-21T23:29:00.493", "kind": "milestone", "label": "Published", "source": "fkie_nvd \u00b7 FKIE_CVE-2018-19320", "record": "FKIE_CVE-2018-19320", "field": "published"}, {"timestamp": "2018-12-25T00:00:00Z", "date_only": true, "value": "2018-12-25", "kind": "other", "label": "Open Time", "source": "cnvd \u00b7 CNVD-2018-26457", "record": "CNVD-2018-26457", "field": "openTime"}, {"timestamp": "2018-12-25T00:00:00Z", "date_only": true, "value": "2018-12-25", "kind": "other", "label": "Submit Time", "source": "cnvd \u00b7 CNVD-2018-26457", "record": "CNVD-2018-26457", "field": "submitTime"}, {"timestamp": "2020-02-07T13:20:11Z", "date_only": false, "value": "2020-02-07T13:20:11.000000Z", "kind": "sighting", "label": "Seen", "source": "MISP/5e3d62c3-cc10-494e-b305-4c270a3b4631", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "a4905cb5-e0f6-4e28-9ceb-81c03e184172"}, {"timestamp": "2020-05-19T12:37:06Z", "date_only": false, "value": "2020-05-19T12:37:06.000Z", "kind": "other", "label": "Updated", "source": "cvelistv5 / mitre", "record": "cve-2018-19320", "field": "containers.cna.providerMetadata.dateUpdated"}, {"timestamp": "2020-08-24T17:37:00Z", "date_only": false, "value": "2020-08-24T17:37Z", "kind": "other", "label": "Last Modified Date", "source": "gsd \u00b7 GSD-2018-19320", "record": "GSD-2018-19320", "field": "namespaces.nvd.nist.gov.lastModifiedDate"}, {"timestamp": "2022-05-13T01:19:46Z", "date_only": false, "value": "2022-05-13T01:19:46Z", "kind": "milestone", "label": "Published", "source": "github \u00b7 GHSA-WG2V-FX2J-3JRR", "record": "GHSA-WG2V-FX2J-3JRR", "field": "published"}, {"timestamp": "2022-10-24T00:00:00Z", "date_only": false, "value": "2022-10-24T00:00:00+00:00", "kind": "kev", "label": "Asserted", "source": "cisa-kev", "record": "CVE-2018-19320", "field": "timestamps.asserted_at", "uuid": "0089d730-00bc-4874-afa3-7c50456fc4a0", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2022-10-24T00:00:00Z", "date_only": false, "value": "2022-10-24T00:00:00+00:00", "kind": "kev", "label": "Asserted", "source": "kevintel", "record": "CVE-2018-19320", "field": "timestamps.asserted_at", "uuid": "1f24029b-7e6c-4260-be82-6898381b25ad", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2022-10-24T00:00:00Z", "date_only": true, "value": "2022-10-24", "kind": "other", "label": "Catalog added", "source": "cvelistv5 / CISA-ADP", "record": "cve-2018-19320", "field": "containers.adp.1.metrics.2.other.content.dateAdded"}, {"timestamp": "2022-10-24T00:00:00Z", "date_only": false, "value": "2022-10-24T00:00:00.000Z", "kind": "kev", "label": "Catalog added", "source": "kevintel", "record": "CVE-2018-19320", "field": "evidence.0.details.added_date", "uuid": "1f24029b-7e6c-4260-be82-6898381b25ad", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2022-10-24T00:00:00Z", "date_only": true, "value": "2022-10-24", "kind": "kev", "label": "Date added", "source": "cisa-kev", "record": "CVE-2018-19320", "field": "evidence.0.details.date_added", "uuid": "0089d730-00bc-4874-afa3-7c50456fc4a0", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2022-10-24T00:00:00Z", "date_only": false, "value": "2022-10-24T00:00:00+00:00", "kind": "kev", "label": "First seen", "source": "cisa-kev", "record": "CVE-2018-19320", "field": "timestamps.first_seen_at", "uuid": "0089d730-00bc-4874-afa3-7c50456fc4a0", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2022-10-24T00:00:00Z", "date_only": false, "value": "2022-10-24T00:00:00+00:00", "kind": "kev", "label": "First seen", "source": "kevintel", "record": "CVE-2018-19320", "field": "timestamps.first_seen_at", "uuid": "1f24029b-7e6c-4260-be82-6898381b25ad", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2022-10-24T00:00:00Z", "date_only": false, "value": "2022-10-24T00:00:00+00:00", "kind": "kev", "label": "Status updated", "source": "cisa-kev", "record": "CVE-2018-19320", "field": "status.status_updated_at", "uuid": "0089d730-00bc-4874-afa3-7c50456fc4a0", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2022-10-24T00:00:00Z", "date_only": false, "value": "2022-10-24T00:00:00+00:00", "kind": "kev", "label": "Status updated", "source": "kevintel", "record": "CVE-2018-19320", "field": "status.status_updated_at", "uuid": "1f24029b-7e6c-4260-be82-6898381b25ad", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2022-10-24T00:00:00Z", "date_only": false, "value": "2022-10-24T00:00:00.000Z", "kind": "other", "label": "Time", "source": "cvelistv5 / CISA-ADP", "record": "cve-2018-19320", "field": "containers.adp.1.timeline.0.time"}, {"timestamp": "2022-10-27T00:00:00Z", "date_only": false, "value": "2022-10-27T00:00:00+00:00", "kind": "other", "label": "Recorded", "source": "cvelistv5 / CISA-ADP", "record": "cve-2018-19320", "field": "containers.adp.1.metrics.1.other.content.timestamp"}, {"timestamp": "2022-10-27T00:00:00Z", "date_only": false, "value": "2022-10-27T00:00:00+00:00", "kind": "other", "label": "Recorded", "source": "fkie_nvd \u00b7 FKIE_CVE-2018-19320", "record": "FKIE_CVE-2018-19320", "field": "metrics.ssvcV203.0.ssvcData.timestamp"}, {"timestamp": "2022-11-14T00:00:00Z", "date_only": true, "value": "2022-11-14", "kind": "kev", "label": "Due date", "source": "cisa-kev", "record": "CVE-2018-19320", "field": "evidence.0.details.due_date", "uuid": "0089d730-00bc-4874-afa3-7c50456fc4a0", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2023-06-14T21:10:03Z", "date_only": false, "value": "2023-06-14T21:10:03.000000Z", "kind": "sighting", "label": "Seen", "source": "MISP/3c19819c-1dac-4ef2-bfed-be5efa7e0123", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "a13c6867-ecb5-4cb0-8ada-422b23ffd3e6"}, {"timestamp": "2023-12-03T21:29:24Z", "date_only": false, "value": "2023-12-03T21:29:24.000000Z", "kind": "sighting", "label": "Seen", "source": "https://t.me/arpsyndicate/1033", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "6c70236c-6749-4ef1-b75b-55cc0fbe0fcc", "content": "#ExploitObserverAlert\n\nCVE-2018-19320\n\nDESCRIPTION: Exploit Observer has 21 entries related to CVE-2018-19320. The GDrv low-level driver in GIGABYTE APP Center v1.05.21 and earlier, AORUS GRAPHICS ENGINE before 1.57, XTREME GAMING ENGINE before 1.26, and OC GURU II v2.08 exposes ring0 memcpy-like functionality that could allow a local attacker to take complete control of the affected system.\n\nFIRST-EPSS: 0.001850000\nNVD-IS: 5.9\nNVD-ES: 1.8", "url": "https://t.me/arpsyndicate/1033"}, {"timestamp": "2023-12-13T01:22:39.294Z", "date_only": false, "value": "2023-12-13T01:22:39.294963Z", "kind": "other", "label": "Updated", "source": "gsd \u00b7 GSD-2018-19320", "record": "GSD-2018-19320", "field": "gsd.osvSchema.modified"}, {"timestamp": "2024-08-05T11:30:04.066Z", "date_only": false, "value": "2024-08-05T11:30:04.066Z", "kind": "other", "label": "Updated", "source": "cvelistv5 / CVE", "record": "cve-2018-19320", "field": "containers.adp.0.providerMetadata.dateUpdated"}, {"timestamp": "2024-12-24T20:33:18.476Z", "date_only": false, "value": "2024-12-24T20:33:18.476139Z", "kind": "sighting", "label": "Seen", "source": "https://feedsin.space/feed/CISAKevBot/items/2971726", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "2dc4a7a2-9ef2-4a31-a839-0bea20c0f9ec", "url": "https://feedsin.space/feed/CISAKevBot/items/2971726"}, {"timestamp": "2025-02-23T02:10:19Z", "date_only": false, "value": "2025-02-23T02:10:19.000000Z", "kind": "sighting", "label": "Seen", "source": "MISP/3c19819c-1dac-4ef2-bfed-be5efa7e0123", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "7b4e30c6-19a4-4bfa-a920-5dc9dafd8584"}, {"timestamp": "2025-10-22T00:31:36Z", "date_only": false, "value": "2025-10-22T00:31:36Z", "kind": "other", "label": "Updated", "source": "github \u00b7 GHSA-WG2V-FX2J-3JRR", "record": "GHSA-WG2V-FX2J-3JRR", "field": "modified"}, {"timestamp": "2026-02-02T12:25:39Z", "date_only": false, "value": "2026-02-02T12:25:39+00:00", "kind": "kev", "label": "Recorded", "source": "cisa-kev", "record": "CVE-2018-19320", "field": "timestamps.recorded_at", "uuid": "0089d730-00bc-4874-afa3-7c50456fc4a0", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2026-02-02T12:27:11.253Z", "date_only": false, "value": "2026-02-02T12:27:11.253864Z", "kind": "sighting", "label": "Exploited", "source": "https://vulnerability.circl.lu/known-exploited-vulnerabilities-catalog/0089d730-00bc-4874-afa3-7c50456fc4a0", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "ecc8d4e3-38cf-4a1d-9d82-6fa1b84ce8fe", "url": "https://vulnerability.circl.lu/known-exploited-vulnerabilities-catalog/0089d730-00bc-4874-afa3-7c50456fc4a0"}, {"timestamp": "2026-06-19T12:47:02.181Z", "date_only": false, "value": "2026-06-19T12:47:02.181451Z", "kind": "sighting", "label": "Exploited", "source": "https://vulnerability.circl.lu/known-exploited-vulnerabilities-catalog/8b7ece74-cdab-4c8c-aec7-5e063783a81b", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "6cf7ea1d-68b2-459a-9c0d-33d96f27b6d5", "url": "https://vulnerability.circl.lu/known-exploited-vulnerabilities-catalog/8b7ece74-cdab-4c8c-aec7-5e063783a81b"}, {"timestamp": "2026-06-23T14:02:37Z", "date_only": false, "value": "2026-06-23T14:02:37+00:00", "kind": "kev", "label": "Recorded", "source": "kevintel", "record": "CVE-2018-19320", "field": "timestamps.recorded_at", "uuid": "1f24029b-7e6c-4260-be82-6898381b25ad", "status": {"status_reason": "confirmed", "exploited": true}}, {"timestamp": "2026-06-23T14:05:34.176Z", "date_only": false, "value": "2026-06-23T14:05:34.176998Z", "kind": "sighting", "label": "Exploited", "source": "https://vulnerability.circl.lu/known-exploited-vulnerabilities-catalog/1f24029b-7e6c-4260-be82-6898381b25ad", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "0e785f96-f040-41cd-b5fa-b493e2d7c654", "url": "https://vulnerability.circl.lu/known-exploited-vulnerabilities-catalog/1f24029b-7e6c-4260-be82-6898381b25ad"}, {"timestamp": "2026-07-29T12:00:21.950Z", "date_only": false, "value": "2026-07-29T12:00:21.950013Z", "kind": "sighting", "label": "Seen", "source": "https://t.me/CVEhub/15405", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "64a2dc40-2037-49fa-9d18-a1166d6905d7", "content": "\ud83d\udc7eKEYWORD SERVICE \ud83c\udff7#exploit\nName: *CVE-2018-19320-LPE*\nGithub: https://github.com/hmnthabit/CVE-2018-19320-LPE", "url": "https://t.me/CVEhub/15405"}, {"timestamp": "2026-07-31T00:00:33.436Z", "date_only": false, "value": "2026-07-31T00:00:33.436115Z", "kind": "sighting", "label": "Published proof of concept", "source": "https://t.me/CVEhub/15405", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "c8375f2c-4e60-4a8b-a8e4-6c8b952feeaf", "content": "\ud83d\udc7eKEYWORD SERVICE \ud83c\udff7#exploit\nName: *CVE-2018-19320-LPE*\nGithub: https://github.com/hmnthabit/CVE-2018-19320-LPE", "url": "https://t.me/CVEhub/15405"}, {"timestamp": "2026-08-13T03:55:50.772Z", "date_only": false, "value": "2026-08-13T03:55:50.772Z", "kind": "other", "label": "Updated", "source": "cvelistv5", "record": "cve-2018-19320", "field": "cveMetadata.dateUpdated"}, {"timestamp": "2026-08-13T03:55:50.772Z", "date_only": false, "value": "2026-08-13T03:55:50.772Z", "kind": "other", "label": "Updated", "source": "cvelistv5 / CISA-ADP", "record": "cve-2018-19320", "field": "containers.adp.1.providerMetadata.dateUpdated"}, {"timestamp": "2026-08-13T05:17:16.323Z", "date_only": false, "value": "2026-08-13T05:17:16.323", "kind": "other", "label": "Updated", "source": "fkie_nvd \u00b7 FKIE_CVE-2018-19320", "record": "FKIE_CVE-2018-19320", "field": "lastModified"}, {"timestamp": "2026-08-13T07:09:51.766Z", "date_only": false, "value": "2026-08-13T07:09:51.766980Z", "kind": "sighting", "label": "Seen", "source": "https://bsky.app/profile/vulnsea.com/post/3msx3lxluyp25", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "0dbb9325-8d3c-46df-93c6-ba1a1786abd7", "content": "\ud83c\udf0a ABYSSAL \u00b7 critical with a public exploit\nCVE-2018-19320: The GDrv low-level driver in GIGABYTE APP Center v1.05.21 and earlier, AORUS GRAPHICS ENGINE before 1.57, XTREME GAMING E\u2026\nCVSS 7.8 \u00b7 EPSS 3.6% \u00b7 CISA KEV\nhttps://beta.vulnsea.com/cve/CVE-2018-19320\n\n#CVE #infosec #cybersecurity #threatintel", "url": "https://bsky.app/profile/vulnsea.com/post/3msx3lxluyp25"}, {"timestamp": "2026-09-23T13:02:51.875Z", "date_only": false, "value": "2026-09-23T13:02:51.875485Z", "kind": "sighting", "label": "Seen", "source": "https://gist.github.com/analystdark/efed7e96c74e14fb6b7163de5d9cfa27", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "bdefc65f-4b7f-47b9-a836-c61eb6ca6abd", "content": "# ============================================================\n#  CTC by Dark (CatchTheCheat)\n#  Hardware- und Cheat-Analyse\n#  Ausfuehren als Administrator\n# ============================================================\n\n$L      = 'Microsoft-Windows-Kernel-PnP/Configuration'\n$OKVEN  = @('8086','1022','1002')\n$MUSTER = 'anydesk|rustdesk|teamviewer|parsec|dwservice|ultraviewer|ammyy'\n\n# ------------------------------------------------------------\nfunction Test-Admin {\n    $id = [Security.Principal.WindowsIdentity]::GetCurrent()\n    (New-Object Security.Principal.WindowsPrincipal $id).IsInRole(\n        [Security.Principal.WindowsBuiltInRole]::Administrator)\n}\n\n# ------------------------------------------------------------\nfunction Get-DevId {\n    param($Event)\n    $x = [xml]$Event.ToXml()\n    ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'DeviceInstanceId' }).'#text'\n}\n\n# ============================================================\n#  1 - PnP-Ereignisse\n# ============================================================\nfunction Invoke-PnpEvents {\n    Write-Host \"`n=== Event-ID 411 (Startprobleme) ===\" -ForegroundColor Cyan\n    $e411 = @(Get-WinEvent -FilterHashtable @{LogName=$L;Id=411} -ErrorAction SilentlyContinue)\n    if ($e411.Count -gt 0) {\n        $e411 | Select-Object TimeCreated, Id,\n            @{n='Details';e={($_.Message -replace '\\s+',' ').Trim()}} |\n            Sort-Object TimeCreated -Descending | Format-List\n        Write-Host \"Anzahl 411: $($e411.Count)\" -ForegroundColor Red\n    } else {\n        Write-Host \"Keine 411er gefunden.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`n=== PnP-Konfigurationsereignisse (400/410/420/430) ===\" -ForegroundColor Cyan\n    $cfg = @(Get-WinEvent -FilterHashtable @{LogName=$L;Id=400,410,420,430} -ErrorAction SilentlyContinue |\n        ForEach-Object { [PSCustomObject]@{ Zeit=$_.TimeCreated; EID=$_.Id; Geraet=(Get-DevId $_) } })\n    if ($cfg.Count -gt 0) {\n        $cfg | Sort-Object Zeit | Format-Table -AutoSize -Wrap\n        Write-Host \"Gesamt: $($cfg.Count) Ereignisse\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"Keine Konfigurationsereignisse.\" -ForegroundColor Yellow\n    }\n}\n\n# ============================================================\n#  2 - Log-Integritaet und System-Eckdaten\n# ============================================================\nfunction Invoke-LogIntegrity {\n    Write-Host \"`n=== Geleerte Ereignisprotokolle (System EID 104) ===\" -ForegroundColor Cyan\n    $clr = @(Get-WinEvent -FilterHashtable @{LogName='System';Id=104} -MaxEvents 50 -ErrorAction SilentlyContinue)\n    if ($clr.Count -gt 0) {\n        $clr | ForEach-Object {\n            [PSCustomObject]@{\n                Zeit     = $_.TimeCreated\n                Benutzer = $_.Properties[0].Value\n                Computer = $_.Properties[1].Value\n                Log      = $_.Properties[2].Value\n            }\n        } | Format-Table -AutoSize -Wrap\n        Write-Host \"ACHTUNG: Protokolle wurden geleert.\" -ForegroundColor Red\n    } else {\n        Write-Host \"Keine Loeschvorgaenge protokolliert.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`n=== Security-Log geleert (EID 1102) ===\" -ForegroundColor Cyan\n    $s1102 = @(Get-WinEvent -FilterHashtable @{LogName='Security';Id=1102} -MaxEvents 20 -ErrorAction SilentlyContinue)\n    if ($s1102.Count -gt 0) {\n        $s1102 | Select-Object TimeCreated | Format-Table -AutoSize\n        Write-Host \"ACHTUNG: Security-Log wurde geleert.\" -ForegroundColor Red\n    } else {\n        Write-Host \"Keine Loeschung des Security-Logs.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`n=== System ===\" -ForegroundColor Cyan\n    $os = Get-CimInstance Win32_OperatingSystem\n    Write-Host \"Installiert:  $($os.InstallDate)\"\n    Write-Host \"Letzter Boot: $($os.LastBootUpTime)\"\n    Write-Host \"Computer:     $env:COMPUTERNAME\"\n    Write-Host \"Benutzer:     $env:USERNAME\"\n\n    Write-Host \"`n=== Log-Status ===\" -ForegroundColor Cyan\n    Get-WinEvent -ListLog $L,'System','Security','Application',\n        'Microsoft-Windows-Partition/Diagnostic' -ErrorAction SilentlyContinue |\n        Select-Object LogName, IsEnabled, RecordCount, LogMode | Format-Table -AutoSize\n\n    Write-Host \"=== Zeitaenderungen (Kernel-General EID 1) ===\" -ForegroundColor Cyan\n    $zt = @(Get-WinEvent -FilterHashtable @{LogName='System';Id=1;ProviderName='Microsoft-Windows-Kernel-General'} -MaxEvents 20 -ErrorAction SilentlyContinue)\n    if ($zt.Count -gt 0) {\n        $zt | Select-Object TimeCreated, @{n='Info';e={($_.Message -replace '\\s+',' ').Trim()}} | Format-List\n    } else {\n        Write-Host \"Keine manuellen Zeitaenderungen.\" -ForegroundColor Green\n    }\n\n    # --- Ausfuehrungsartefakte: Zustand und Auffaelligkeiten ---\n    Write-Host \"`n=== Ausfuehrungsartefakte ===\" -ForegroundColor Cyan\n    Write-Host \"(Zeigt Zustand, KEIN kryptografischer Manipulationsbeweis.\" -ForegroundColor DarkGray\n    Write-Host \" Tiefenauswertung: Zimmerman-Tools AmcacheParser / AppCompatCacheParser / MFTECmd)\" -ForegroundColor DarkGray\n\n    # Amcache.hve\n    Write-Host \"`n--- Amcache.hve ---\" -ForegroundColor DarkGray\n    $am = \"$env:SystemRoot\\AppCompat\\Programs\\Amcache.hve\"\n    if (Test-Path $am) {\n        $f = Get-Item $am -Force\n        Write-Host (\"Groesse: {0:N0} Bytes | Erstellt: {1} | Geaendert: {2}\" -f $f.Length,$f.CreationTime,$f.LastWriteTime)\n        if ($f.Length -lt 100KB) {\n            Write-Host \"AUFFAELLIG: Datei sehr klein - koennte geleert/zurueckgesetzt sein.\" -ForegroundColor Red\n        }\n        $os2 = Get-CimInstance Win32_OperatingSystem\n        if ($f.CreationTime -gt $os2.InstallDate.AddDays(1)) {\n            Write-Host \"AUFFAELLIG: Erstellt deutlich nach Windows-Installation - moeglw. neu angelegt.\" -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"FEHLT - Amcache.hve nicht vorhanden (regeneriert sich normalerweise).\" -ForegroundColor Red\n    }\n\n    # USN-Journal (NTFS-Aenderungsjournal)\n    Write-Host \"`n--- USN-Journal (Laufwerk C:) ---\" -ForegroundColor DarkGray\n    $usn = &amp; fsutil usn queryjournal C: 2&gt;&amp;1\n    if ($LASTEXITCODE -eq 0 -and $usn) {\n        $usn | ForEach-Object { Write-Host \"   $_\" }\n        $first = ($usn | Select-String 'Erste USN|First USN' | Select-Object -First 1) -replace '[^0-9x]',''\n        if ($first -match '^0x0+$' -or $first -eq '0') {\n            Write-Host \"AUFFAELLIG: Erste USN = 0 - Journal wurde geloescht und neu angelegt.\" -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"Journal nicht abfragbar oder deaktiviert.\" -ForegroundColor Yellow\n        Write-Host \"Ein DEAKTIVIERTES USN-Journal ist auf einem Gaming-PC ungewoehnlich.\" -ForegroundColor Red\n    }\n\n    # ShimCache / AppCompatCache\n    Write-Host \"`n--- ShimCache (AppCompatCache) ---\" -ForegroundColor DarkGray\n    $shim = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCompatCache'\n    if (Test-Path $shim) {\n        $val = (Get-ItemProperty $shim -Name AppCompatCache -ErrorAction SilentlyContinue).AppCompatCache\n        if ($val) {\n            Write-Host (\"Vorhanden, {0:N0} Bytes. Binaer - Auswertung nur mit AppCompatCacheParser.\" -f $val.Length)\n        } else {\n            Write-Host \"AUFFAELLIG: Schluessel vorhanden, aber leer.\" -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"AUFFAELLIG: AppCompatCache nicht vorhanden.\" -ForegroundColor Red\n    }\n\n    # Prefetch\n    Write-Host \"`n--- Prefetch ---\" -ForegroundColor DarkGray\n    $pfE = (Get-ItemProperty 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters' -Name EnablePrefetcher -ErrorAction SilentlyContinue).EnablePrefetcher\n    $pfDir = \"$env:SystemRoot\\Prefetch\"\n    $pfCount = if (Test-Path $pfDir) { @(Get-ChildItem \"$pfDir\\*.pf\" -ErrorAction SilentlyContinue).Count } else { 0 }\n    Write-Host (\"EnablePrefetcher: {0} | .pf-Dateien: {1}\" -f $pfE, $pfCount)\n    if ($pfE -eq 0) {\n        Write-Host \"AUFFAELLIG: Prefetch deaktiviert - haeufige Anti-Forensik-Massnahme.\" -ForegroundColor Red\n    } elseif ($pfCount -lt 20) {\n        Write-Host \"AUFFAELLIG: Sehr wenige .pf-Dateien - Prefetch koennte geleert worden sein.\" -ForegroundColor Red\n    }\n\n    # SRUM\n    Write-Host \"`n--- SRUM ---\" -ForegroundColor DarkGray\n    $srum = \"$env:SystemRoot\\System32\\sru\\SRUDB.dat\"\n    if (Test-Path $srum) {\n        $f = Get-Item $srum -Force\n        Write-Host (\"SRUDB.dat: {0:N0} Bytes | Geaendert: {1}\" -f $f.Length,$f.LastWriteTime)\n    } else {\n        Write-Host \"SRUDB.dat nicht vorhanden.\" -ForegroundColor Yellow\n    }\n}\n\n# ============================================================\n#  3 - PCI/PCIe-Geraete\n# ============================================================\nfunction Invoke-PciDevices {\n    Write-Host \"`n=== PCI/PCIe-Geraete (aktuell) ===\" -ForegroundColor Cyan\n    Write-Host (\"{0,-6} {1,-6} {2,-10} {3,-18} {4}\" -f 'VEN','DEV','STATUS','KLASSE','NAME') -ForegroundColor Cyan\n    Get-PnpDevice | Where-Object { $_.InstanceId -like 'PCI*' } | Sort-Object Class | ForEach-Object {\n        $v = [regex]::Match($_.InstanceId,'VEN_([0-9A-Fa-f]{4})').Groups[1].Value.ToUpper()\n        $d = [regex]::Match($_.InstanceId,'DEV_([0-9A-Fa-f]{4})').Groups[1].Value.ToUpper()\n        $c = if ($OKVEN -contains $v) { 'Green' } else { 'Red' }\n        Write-Host (\"{0,-6} {1,-6} {2,-10} {3,-18} {4}\" -f $v,$d,$_.Status,$_.Class,$_.FriendlyName) -ForegroundColor $c\n    }\n\n    Write-Host \"`n=== Nicht mehr vorhandene PCI-Geraete ===\" -ForegroundColor Cyan\n    $reg = @(Get-ChildItem 'HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\PCI' -ErrorAction SilentlyContinue |\n        Select-Object -ExpandProperty PSChildName)\n    $da  = @(Get-PnpDevice -PresentOnly -ErrorAction SilentlyContinue |\n        Where-Object { $_.InstanceId -like 'PCI*' } |\n        ForEach-Object { ($_.InstanceId -split '\\\\')[1] })\n    $weg = @($reg | Where-Object { $da -notcontains $_ })\n    if ($weg.Count -gt 0) {\n        $weg | ForEach-Object { Write-Host \"FEHLT: $_\" -ForegroundColor Red }\n    } else {\n        Write-Host \"Keine Abweichung.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`n=== setupapi.dev.log ===\" -ForegroundColor Cyan\n    $sp = 'C:\\Windows\\INF\\setupapi.dev.log'\n    if (Test-Path $sp) {\n        $fi = Get-Item $sp\n        Write-Host (\"Groesse: {0:N0} Bytes | Erstellt: {1} | Geaendert: {2}\" -f $fi.Length,$fi.CreationTime,$fi.LastWriteTime)\n        $ids = @(Select-String -Path $sp -Pattern 'PCI\\\\VEN_[0-9A-Fa-f]{4}&amp;DEV_[0-9A-Fa-f]{4}' -AllMatches |\n            ForEach-Object { $_.Matches.Value } | Sort-Object -Unique)\n        if ($ids.Count -gt 0) { $ids }\n        else { Write-Host \"Keine PCI-Eintraege in der Datei.\" -ForegroundColor Yellow }\n    } else {\n        Write-Host \"Datei nicht vorhanden.\" -ForegroundColor Yellow\n    }\n}\n\n# ============================================================\n#  4 - Entfernte Geraete im Zeitfenster\n# ============================================================\nfunction Invoke-RemovedDevices {\n    param([int]$Stunden = 1)\n\n    $seit = (Get-Date).AddHours(-$Stunden)\n    Write-Host \"`n=== Entfernte Geraete seit $($seit.ToString('dd.MM.yyyy HH:mm')) ===\" -ForegroundColor Cyan\n\n    $rem = @(Get-WinEvent -FilterHashtable @{LogName=$L;Id=420;StartTime=$seit} -ErrorAction SilentlyContinue |\n        ForEach-Object { [PSCustomObject]@{ Zeit=$_.TimeCreated; Geraet=(Get-DevId $_) } })\n    if ($rem.Count -gt 0) {\n        Write-Host \"--- Abgezogen (Ereignisprotokoll) ---\" -ForegroundColor Red\n        $rem | Sort-Object Zeit | Format-Table -AutoSize -Wrap\n    } else {\n        Write-Host \"Keine 420-Ereignisse im Zeitfenster.\" -ForegroundColor Green\n    }\n\n    $sig = '[DllImport(\"advapi32.dll\")]public static extern int RegQueryInfoKey(Microsoft.Win32.SafeHandles.SafeRegistryHandle h,System.Text.StringBuilder a,ref int b,int c,ref int d,ref int e,ref int f,ref int g,ref int i,ref int j,ref int k,ref long l);'\n    Add-Type -MemberDefinition $sig -Name RK -Namespace W -ErrorAction SilentlyContinue\n\n    $da = @(Get-PnpDevice -PresentOnly -ErrorAction SilentlyContinue | ForEach-Object { $_.InstanceId })\n    $treffer = @()\n    foreach ($zweig in @('PCI','USB','USBSTOR','HID')) {\n        $pfad = \"HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\$zweig\"\n        if (-not (Test-Path $pfad)) { continue }\n        Get-ChildItem $pfad -ErrorAction SilentlyContinue | ForEach-Object {\n            $el = $_\n            Get-ChildItem $el.PSPath -ErrorAction SilentlyContinue | ForEach-Object {\n                $t = 0L; $z = 0; $n = New-Object Text.StringBuilder 1024\n                [void][W.RK]::RegQueryInfoKey($_.Handle,$n,[ref]$z,0,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$t)\n                $zeit = [DateTime]::FromFileTime($t)\n                $iid  = \"$zweig\\$($el.PSChildName)\\$($_.PSChildName)\"\n                if ($zeit -ge $seit -and ($da -notcontains $iid)) {\n                    $treffer += [PSCustomObject]@{\n                        Zuletzt = $zeit\n                        Geraet  = $iid\n                        Name    = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue).FriendlyName\n                    }\n                }\n            }\n        }\n    }\n    if ($treffer.Count -gt 0) {\n        Write-Host \"--- Registry frisch angefasst, Geraet nicht mehr vorhanden ---\" -ForegroundColor Red\n        $treffer | Sort-Object Zuletzt -Descending | Format-Table -AutoSize -Wrap\n    } else {\n        Write-Host \"Keine Registry-Auffaelligkeiten im Zeitfenster.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`nHinweis: Bei ausgeschaltetem Rechner entfernte Hardware\" -ForegroundColor DarkGray\n    Write-Host \"erzeugt KEINE Spur. Leeres Ergebnis ist keine Entlastung.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  5 - Datentraeger-Historie\n# ============================================================\nfunction Invoke-DiskHistory {\n    Write-Host \"`n=== Datentraeger-Historie (Partition/Diagnostic) ===\" -ForegroundColor Cyan\n\n    $plog = @(Get-WinEvent -LogName 'Microsoft-Windows-Partition/Diagnostic' -ErrorAction SilentlyContinue |\n        ForEach-Object {\n            $dat = ([xml]$_.ToXml()).Event.EventData.Data\n            [PSCustomObject]@{\n                Zeit   = $_.TimeCreated\n                EID    = $_.Id\n                Modell = ($dat | Where-Object { $_.Name -eq 'Model' }).'#text'\n                Serie  = ($dat | Where-Object { $_.Name -eq 'SerialNumber' }).'#text'\n            }\n        })\n\n    if ($plog.Count -eq 0) {\n        Write-Host \"Log leer oder nicht lesbar.\" -ForegroundColor Yellow\n        return\n    }\n\n    $s = $plog | Sort-Object Zeit\n    Write-Host (\"Zeitraum: {0} bis {1}  ({2} Eintraege)\" -f $s[0].Zeit, $s[-1].Zeit, $plog.Count) -ForegroundColor DarkGray\n\n    Write-Host \"`n--- Alle jemals erfassten Datentraeger ---\" -ForegroundColor DarkGray\n    $plog | Group-Object Serie | ForEach-Object {\n        $e = $_.Group | Sort-Object Zeit\n        [PSCustomObject]@{\n            Modell   = $e[0].Modell\n            Serie    = $_.Name\n            Erstmals = $e[0].Zeit\n            Zuletzt  = $e[-1].Zeit\n            Anzahl   = $_.Count\n        }\n    } | Sort-Object Zuletzt -Descending | Format-Table -AutoSize\n\n    Write-Host \"--- Im Log erfasst, aktuell NICHT angeschlossen ---\" -ForegroundColor DarkGray\n    $jetzt = @(Get-Disk -ErrorAction SilentlyContinue | ForEach-Object { $_.SerialNumber -replace '\\s','' })\n    $fehlt = @($plog | Group-Object Serie | Where-Object {\n        $sn = $_.Name -replace '[\\s\\.]',''\n        -not ($jetzt | Where-Object { $_ -and ($_ -replace '[\\s\\.]','') -like \"*$sn*\" })\n    })\n    if ($fehlt.Count -gt 0) {\n        $fehlt | ForEach-Object {\n            $e = $_.Group | Sort-Object Zeit\n            Write-Host (\"FEHLT: {0} | Serie {1} | zuletzt {2}\" -f $e[0].Modell, $_.Name, $e[-1].Zeit) -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"Alle erfassten Datentraeger sind angeschlossen.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`n--- Letzte 30 Ereignisse ---\" -ForegroundColor DarkGray\n    $plog | Sort-Object Zeit -Descending | Select-Object -First 30 | Format-Table -AutoSize\n}\n\n# ============================================================\n#  6 - USB-Geraetehistorie\n# ============================================================\nfunction Invoke-UsbHistory {\n    Write-Host \"`n=== USB-Geraetehistorie ===\" -ForegroundColor Cyan\n    $da = @(Get-PnpDevice -PresentOnly -ErrorAction SilentlyContinue | ForEach-Object { $_.InstanceId })\n    foreach ($zweig in @('USBSTOR','USB')) {\n        $pfad = \"HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\$zweig\"\n        if (-not (Test-Path $pfad)) { continue }\n        Write-Host \"`n--- $zweig ---\" -ForegroundColor DarkGray\n        Get-ChildItem $pfad -ErrorAction SilentlyContinue | ForEach-Object {\n            $el = $_\n            Get-ChildItem $el.PSPath -ErrorAction SilentlyContinue | ForEach-Object {\n                $p = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue\n                $iid = \"$zweig\\$($el.PSChildName)\\$($_.PSChildName)\"\n                [PSCustomObject]@{\n                    Status = if ($da -contains $iid) { 'vorhanden' } else { 'FEHLT' }\n                    Name   = $p.FriendlyName\n                    Klasse = $p.Class\n                    Geraet = $el.PSChildName\n                    Serie  = $_.PSChildName\n                }\n            }\n        } | Sort-Object Status, Name | Format-Table -AutoSize -Wrap\n    }\n    Write-Host \"Hinweis: Viele FEHLT-Eintraege unter USB sind normal (Ports, Hubs, Kabel).\" -ForegroundColor DarkGray\n\n    # --- DeviceSetupManager: MAKCU / Arduino / Input-Emulator Spuren ---\n    Write-Host \"`n--- DeviceSetupManager: MAKCU / Arduino / Input-Emulator ---\" -ForegroundColor Cyan\n    Write-Host \"(CH343/CH340/CH341 = Arduino-Klon | ESP32-S3 = MAKCU | COM-Port = serielles Geraet)\" -ForegroundColor DarkGray\n\n    $dsmLog   = 'Microsoft-Windows-DeviceSetupManager/Admin'\n    $dsmOper  = 'Microsoft-Windows-DeviceSetupManager/Operational'\n    $dsmMuster = 'CH34|CH340|CH341|CH343|ESP32|ESP8266|MAKCU|Arduino|CP2102|CP210|PL2303|FT232|FTDI|silabser|usbser'\n    $comMuster = 'COM\\d+'\n\n    $dsmTreffer = @()\n    foreach ($log in @($dsmLog, $dsmOper)) {\n        $events = @(Get-WinEvent -LogName $log -MaxEvents 500 -ErrorAction SilentlyContinue)\n        foreach ($e in $events) {\n            if ($e.Message -match $dsmMuster -or $e.Message -match 'COM[3-9]|COM[1-9][0-9]') {\n                $comPort = if ($e.Message -match '(COM\\d+)') { $matches[1] } else { '' }\n                $chip    = ''\n                foreach ($m in @('CH343','CH340','CH341','CH34','ESP32-S3','ESP32','ESP8266','CP2102','CP210','PL2303','FT232','FTDI','silabser','usbser','MAKCU','Arduino')) {\n                    if ($e.Message -match [regex]::Escape($m)) { $chip = $m; break }\n                }\n                $dsmTreffer += [PSCustomObject]@{\n                    Zeit    = $e.TimeCreated\n                    EID     = $e.Id\n                    Chip    = $chip\n                    COM     = $comPort\n                    Meldung = ($e.Message -replace '\\s+',' ').Substring(0, [Math]::Min(120, $e.Message.Length))\n                }\n            }\n        }\n    }\n\n    if ($dsmTreffer.Count -gt 0) {\n        Write-Host \"`n  [!] TREFFER: Serielle/Arduino/MAKCU-Geraete im DeviceSetupManager-Log!\" -ForegroundColor Red\n        $dsmTreffer | Sort-Object Zeit -Descending | Select-Object -First 20 | ForEach-Object {\n            $col = if ($_.Chip -match 'ESP32|MAKCU') { 'Red' } else { 'Yellow' }\n            Write-Host (\"`n  [{0}] EID {1}\" -f $_.Zeit, $_.EID) -ForegroundColor $col\n            if ($_.Chip) { Write-Host (\"  Chip/Typ : {0}\" -f $_.Chip) -ForegroundColor $col }\n            if ($_.COM)  { Write-Host (\"  COM-Port : {0}\" -f $_.COM)  -ForegroundColor $col }\n            Write-Host (\"  Meldung  : {0}...\" -f $_.Meldung) -ForegroundColor DarkGray\n        }\n        Write-Host \"`n  Bedeutung: CH34x = Arduino-Klon (Input-Emulator Basis)\" -ForegroundColor DarkGray\n        Write-Host \"             ESP32-S3 = MAKCU oder aehnliches Aim-Geraet\" -ForegroundColor DarkGray\n        Write-Host \"             COM-Port-Eintrag = serielles USB-Geraet war angeschlossen\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"  Keine Arduino/MAKCU/ESP32-Spuren im DeviceSetupManager-Log.\" -ForegroundColor Green\n    }\n\n    # --- COM-Port-Registry: jemals registrierte serielle Geraete ---\n    Write-Host \"`n--- COM-Port-Historie (Registry) ---\" -ForegroundColor DarkGray\n    $comKey = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\COM Name Arbiter\\Devices'\n    if (Test-Path $comKey) {\n        $comPorts = Get-ItemProperty $comKey -ErrorAction SilentlyContinue\n        if ($comPorts) {\n            $comPorts.PSObject.Properties | Where-Object { $_.Name -notmatch '^PS' } | ForEach-Object {\n                Write-Host (\"  {0} = {1}\" -f $_.Name, $_.Value)\n            }\n        }\n    } else {\n        Write-Host \"  COM-Arbiter-Key nicht vorhanden.\" -ForegroundColor DarkGray\n    }\n}\n\n# ============================================================\n#  7 - Fernwartungssoftware\n# ============================================================\nfunction Invoke-RemoteTools {\n    Write-Host \"`n=== Fernwartungssoftware ===\" -ForegroundColor Cyan\n    $fund = $false\n\n    Write-Host \"`n--- Installiert (Registry) ---\" -ForegroundColor DarkGray\n    $uninst = @(\n      'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*',\n      'HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*',\n      'HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n    )\n    $tr = @(Get-ItemProperty $uninst -ErrorAction SilentlyContinue |\n        Where-Object { $_.DisplayName -match $MUSTER } |\n        Select-Object DisplayName, DisplayVersion, InstallDate, InstallLocation)\n    if ($tr) { $tr | Format-Table -AutoSize -Wrap; $fund = $true }\n    else { Write-Host \"Nichts gefunden.\" -ForegroundColor Green }\n\n    Write-Host \"`n--- Prefetch (belegt AUSFUEHRUNG) ---\" -ForegroundColor DarkGray\n    $pfEnabled = (Get-ItemProperty 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters' -Name EnablePrefetcher -ErrorAction SilentlyContinue).EnablePrefetcher\n    if ($pfEnabled -eq 0) {\n        Write-Host \"Prefetch ist DEAKTIVIERT - dieser Test ist wertlos.\" -ForegroundColor Yellow\n    }\n    $pf = @(Get-ChildItem 'C:\\Windows\\Prefetch\\*.pf' -ErrorAction SilentlyContinue |\n        Where-Object { $_.Name -match $MUSTER } |\n        Select-Object Name, CreationTime, LastWriteTime)\n    if ($pf) { $pf | Format-Table -AutoSize; $fund = $true }\n    else { Write-Host \"Kein Prefetch-Eintrag.\" -ForegroundColor Green }\n\n    Write-Host \"`n--- Dateien / Ordner ---\" -ForegroundColor DarkGray\n    $pfade = @(\"$env:ProgramFiles\",\"${env:ProgramFiles(x86)}\",\"$env:APPDATA\",\n               \"$env:LOCALAPPDATA\",\"$env:ProgramData\",\"$env:USERPROFILE\\Downloads\",\"$env:USERPROFILE\\Desktop\")\n    $df = @(foreach ($p in $pfade) {\n        if (Test-Path $p) {\n            Get-ChildItem $p -Recurse -Depth 2 -ErrorAction SilentlyContinue |\n                Where-Object { $_.Name -match $MUSTER } |\n                Select-Object FullName, Length, CreationTime, LastWriteTime\n        }\n    })\n    if ($df) { $df | Sort-Object CreationTime | Format-Table -AutoSize -Wrap; $fund = $true }\n    else { Write-Host \"Keine Dateien gefunden.\" -ForegroundColor Green }\n\n    Write-Host \"`n--- Dienste ---\" -ForegroundColor DarkGray\n    $sv = @(Get-CimInstance Win32_Service -ErrorAction SilentlyContinue |\n        Where-Object { $_.Name -match $MUSTER -or $_.DisplayName -match $MUSTER -or $_.PathName -match $MUSTER } |\n        Select-Object Name, DisplayName, State, StartMode, PathName)\n    if ($sv) { $sv | Format-Table -AutoSize -Wrap; $fund = $true }\n    else { Write-Host \"Keine Dienste.\" -ForegroundColor Green }\n\n    Write-Host \"`n--- Programmspuren in der Registry ---\" -ForegroundColor DarkGray\n    $rk = @(\n      'HKCU:\\SOFTWARE\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache',\n      'HKCU:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Compatibility Assistant\\Store',\n      'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Compatibility Assistant\\Store'\n    )\n    $sp = @(foreach ($k in $rk) {\n        if (Test-Path $k) {\n            (Get-Item $k).Property | Where-Object { $_ -match $MUSTER } |\n                ForEach-Object { [PSCustomObject]@{ Quelle=(Split-Path $k -Leaf); Eintrag=$_ } }\n        }\n    })\n    if ($sp) { $sp | Format-Table -AutoSize -Wrap; $fund = $true }\n    else { Write-Host \"Keine Registry-Spuren.\" -ForegroundColor Green }\n\n    Write-Host \"`n--- Firewall-Regeln ---\" -ForegroundColor DarkGray\n    $fw = @(Get-NetFirewallRule -ErrorAction SilentlyContinue |\n        Where-Object { $_.DisplayName -match $MUSTER } |\n        Select-Object DisplayName, Enabled, Direction, Action)\n    if ($fw) { $fw | Format-Table -AutoSize; $fund = $true }\n    else { Write-Host \"Keine Firewall-Regeln.\" -ForegroundColor Green }\n\n    if ($fund) {\n        Write-Host \"`nTREFFER vorhanden - Eintraege einzeln pruefen.\" -ForegroundColor Red\n        Write-Host \"Fernwartung hat viele harmlose Gruende. Der Zeitpunkt entscheidet.\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"`nKeine Hinweise auf Fernwartungssoftware.\" -ForegroundColor Green\n    }\n}\n\n# ============================================================\n#  8 - Fernwartung: Sitzungen und Dateiuebertragungen\n# ============================================================\nfunction Invoke-RemoteSessions {\n    Write-Host \"`n=== Fernwartung: Sitzungen und Dateiuebertragungen ===\" -ForegroundColor Cyan\n\n    # Schluesselwoerter, die auf Dateiuebertragung hindeuten\n    $ftMuster = 'file transfer|filetransfer|Files\\b|Starting file|Download|Upload|transfer of|Dateiuebertragung|Datei\u00c3\u00bcbertragung'\n\n    # --- AnyDesk ---\n    Write-Host \"`n--- AnyDesk ---\" -ForegroundColor DarkGray\n    $adPfade = @(\"$env:ProgramData\\AnyDesk\", \"$env:APPDATA\\AnyDesk\")\n    $adGefunden = $false\n    foreach ($p in $adPfade) {\n        if (-not (Test-Path $p)) { continue }\n        $adGefunden = $true\n        Write-Host \"Ordner: $p\" -ForegroundColor DarkGray\n        Get-ChildItem $p -Filter '*.trace' -ErrorAction SilentlyContinue |\n            Select-Object Name, Length, CreationTime, LastWriteTime | Format-Table -AutoSize\n\n        # connection_trace.txt: eine Zeile pro Sitzung\n        $ct = Join-Path $p 'connection_trace.txt'\n        if (Test-Path $ct) {\n            Write-Host \"-- Sitzungen (connection_trace.txt) --\" -ForegroundColor Yellow\n            Get-Content $ct -ErrorAction SilentlyContinue | Where-Object { $_.Trim() } |\n                ForEach-Object { Write-Host \"   $_\" }\n        }\n\n        # Dateiuebertragungen aus den Trace-Dateien\n        $tf = @(Get-ChildItem $p -Filter '*.trace' -ErrorAction SilentlyContinue)\n        foreach ($f in $tf) {\n            $hits = @(Select-String -Path $f.FullName -Pattern $ftMuster -ErrorAction SilentlyContinue)\n            if ($hits.Count -gt 0) {\n                Write-Host \"-- Moegliche Dateiuebertragung in $($f.Name) --\" -ForegroundColor Red\n                $hits | Select-Object -Last 40 | ForEach-Object { Write-Host \"   $($_.Line.Trim())\" }\n            }\n        }\n    }\n    if (-not $adGefunden) { Write-Host \"Keine AnyDesk-Ordner vorhanden.\" -ForegroundColor Green }\n\n    # --- RustDesk ---\n    Write-Host \"`n--- RustDesk ---\" -ForegroundColor DarkGray\n    $rdPfade = @(\"$env:APPDATA\\RustDesk\", \"$env:ProgramData\\RustDesk\", \"$env:LOCALAPPDATA\\RustDesk\")\n    $rdGefunden = $false\n    foreach ($p in $rdPfade) {\n        if (-not (Test-Path $p)) { continue }\n        $rdGefunden = $true\n        Write-Host \"Ordner: $p\" -ForegroundColor DarkGray\n        Get-ChildItem $p -Recurse -Include '*.log','*.toml' -ErrorAction SilentlyContinue |\n            Select-Object FullName, Length, CreationTime, LastWriteTime | Format-Table -AutoSize -Wrap\n\n        $logs = @(Get-ChildItem $p -Recurse -Filter '*.log' -ErrorAction SilentlyContinue)\n        foreach ($f in $logs) {\n            $hits = @(Select-String -Path $f.FullName -Pattern ($ftMuster + '|remote_id|Connection from|session') -ErrorAction SilentlyContinue)\n            if ($hits.Count -gt 0) {\n                Write-Host \"-- Eintraege in $($f.Name) --\" -ForegroundColor Yellow\n                $hits | Select-Object -Last 40 | ForEach-Object { Write-Host \"   $($_.Line.Trim())\" }\n            }\n        }\n    }\n    if (-not $rdGefunden) { Write-Host \"Keine RustDesk-Ordner vorhanden.\" -ForegroundColor Green }\n\n    # --- TeamViewer ---\n    Write-Host \"`n--- TeamViewer ---\" -ForegroundColor DarkGray\n    $tvPfade = @(\"$env:APPDATA\\TeamViewer\", \"$env:ProgramData\\TeamViewer\",\n                 \"$env:ProgramFiles\\TeamViewer\", \"${env:ProgramFiles(x86)}\\TeamViewer\")\n    $tvGefunden = $false\n    foreach ($p in $tvPfade) {\n        if (-not (Test-Path $p)) { continue }\n        $tvGefunden = $true\n        $conn = @(Get-ChildItem $p -Recurse -Include 'Connections*.txt' -ErrorAction SilentlyContinue)\n        foreach ($f in $conn) {\n            Write-Host \"-- $($f.FullName) --\" -ForegroundColor Yellow\n            Get-Content $f.FullName -ErrorAction SilentlyContinue | Where-Object { $_.Trim() } |\n                Select-Object -Last 40 | ForEach-Object { Write-Host \"   $_\" }\n        }\n        $tvlogs = @(Get-ChildItem $p -Recurse -Filter '*Logfile*.log' -ErrorAction SilentlyContinue)\n        foreach ($f in $tvlogs) {\n            $hits = @(Select-String -Path $f.FullName -Pattern $ftMuster -ErrorAction SilentlyContinue)\n            if ($hits.Count -gt 0) {\n                Write-Host \"-- Moegliche Dateiuebertragung in $($f.Name) --\" -ForegroundColor Red\n                $hits | Select-Object -Last 30 | ForEach-Object { Write-Host \"   $($_.Line.Trim())\" }\n            }\n        }\n    }\n    if (-not $tvGefunden) { Write-Host \"Keine TeamViewer-Ordner vorhanden.\" -ForegroundColor Green }\n\n    # --- Gegenprobe: geloeschte Logs / Ordnerzeiten ---\n    Write-Host \"`n--- Gegenprobe ---\" -ForegroundColor DarkGray\n    foreach ($p in ($adPfade + $rdPfade + $tvPfade)) {\n        if (Test-Path $p) {\n            $d = Get-Item $p\n            $anz = @(Get-ChildItem $p -Recurse -File -ErrorAction SilentlyContinue).Count\n            Write-Host (\"{0} | Erstellt {1} | Geaendert {2} | {3} Dateien\" -f $p, $d.CreationTime, $d.LastWriteTime, $anz)\n        }\n    }\n\n    Write-Host \"`nHinweis: Ordner vorhanden, aber Logdateien fehlen oder sind leer\" -ForegroundColor DarkGray\n    Write-Host \"= Spuren wurden geloescht. Das ist selbst ein Befund.\" -ForegroundColor DarkGray\n    Write-Host \"Zeitangaben in den Logs sind Ortszeit des Rechners.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  9 - Unsignierte Dateien (Treiber / Prozesse / Ablageorte)\n# ============================================================\nfunction Invoke-Unsigned {\n    Write-Host \"`n=== Unsignierte Dateien ===\" -ForegroundColor Cyan\n\n    # Signaturstatus, der als unauffaellig gilt\n    $okStatus = @('Valid')\n\n    # --- 9a: Geladene Kernel-Treiber (wichtigster Teil) ---\n    Write-Host \"`n--- Geladene Kernel-Treiber ---\" -ForegroundColor DarkGray\n    $drv = @(Get-CimInstance Win32_SystemDriver -ErrorAction SilentlyContinue |\n        Where-Object { $_.State -eq 'Running' -and $_.PathName })\n    $drvBad = @()\n    foreach ($d in $drv) {\n        $path = ($d.PathName -replace '\\\\SystemRoot', $env:SystemRoot) -replace '^\\\\\\?\\?\\\\',''\n        if (-not (Test-Path $path)) { continue }\n        $sig = Get-AuthenticodeSignature $path -ErrorAction SilentlyContinue\n        if ($sig.Status -notin $okStatus) {\n            $drvBad += [PSCustomObject]@{\n                Name    = $d.Name\n                Status  = $sig.Status\n                Signierer = if ($sig.SignerCertificate) { $sig.SignerCertificate.Subject -replace '^CN=([^,]+).*','$1' } else { '-' }\n                Pfad    = $path\n            }\n        }\n    }\n    if ($drvBad.Count -gt 0) {\n        $drvBad | Format-Table -AutoSize -Wrap\n        Write-Host \"$($drvBad.Count) nicht gueltig signierte Treiber - EINZELN pruefen.\" -ForegroundColor Red\n    } else {\n        Write-Host \"Alle geladenen Treiber gueltig signiert.\" -ForegroundColor Green\n    }\n\n    # --- 9b: Laufende Prozesse ---\n    Write-Host \"`n--- Laufende Prozesse ---\" -ForegroundColor DarkGray\n    $procBad = @()\n    Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Path } |\n        Select-Object -Property Path -Unique | ForEach-Object {\n            $sig = Get-AuthenticodeSignature $_.Path -ErrorAction SilentlyContinue\n            if ($sig.Status -notin $okStatus) {\n                $procBad += [PSCustomObject]@{\n                    Status    = $sig.Status\n                    Signierer = if ($sig.SignerCertificate) { $sig.SignerCertificate.Subject -replace '^CN=([^,]+).*','$1' } else { '-' }\n                    Pfad      = $_.Path\n                }\n            }\n        }\n    if ($procBad.Count -gt 0) {\n        $procBad | Sort-Object Pfad | Format-Table -AutoSize -Wrap\n        Write-Host \"$($procBad.Count) nicht gueltig signierte Prozesse.\" -ForegroundColor Red\n    } else {\n        Write-Host \"Alle laufenden Prozesse gueltig signiert.\" -ForegroundColor Green\n    }\n\n    # --- 9c: Ausfuehrbare Dateien in typischen Ablageorten ---\n    Write-Host \"`n--- .exe/.sys/.dll in Ablageorten (Temp, Downloads, AppData) ---\" -ForegroundColor DarkGray\n    $orte = @(\"$env:TEMP\",\"$env:USERPROFILE\\Downloads\",\"$env:APPDATA\",\"$env:LOCALAPPDATA\\Temp\",\"$env:ProgramData\")\n    $fileBad = @()\n    foreach ($o in $orte) {\n        if (-not (Test-Path $o)) { continue }\n        Get-ChildItem $o -Recurse -Depth 2 -Include '*.exe','*.sys','*.dll' -ErrorAction SilentlyContinue |\n            ForEach-Object {\n                $sig = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue\n                if ($sig.Status -eq 'NotSigned') {\n                    $fileBad += [PSCustomObject]@{\n                        Erstellt = $_.CreationTime\n                        Groesse  = $_.Length\n                        Pfad     = $_.FullName\n                    }\n                }\n            }\n    }\n    if ($fileBad.Count -gt 0) {\n        $fileBad | Sort-Object Erstellt -Descending | Select-Object -First 60 | Format-Table -AutoSize -Wrap\n        Write-Host \"$($fileBad.Count) unsignierte Dateien (max. 60 gezeigt).\" -ForegroundColor Yellow\n    } else {\n        Write-Host \"Keine unsignierten Dateien in den Ablageorten.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`nHinweis: 'UnknownError' heisst meist, dass die Datei nicht\" -ForegroundColor DarkGray\n    Write-Host \"signiert ist. Viele legitime Programme sind unsigniert -\" -ForegroundColor DarkGray\n    Write-Host \"ein unsignierter KERNEL-TREIBER ist der relevante Befund,\" -ForegroundColor DarkGray\n    Write-Host \"unsignierte Nutzerprogramme sind es meist nicht.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  10 - PowerShell-History und Ausfuehrungsprotokoll\n# ============================================================\nfunction Invoke-PSHistory {\n    Write-Host \"`n=== PowerShell-History ===\" -ForegroundColor Cyan\n\n    # --- 10a: PSReadline-History aller Benutzer ---\n    Write-Host \"`n--- PSReadline ConsoleHost_history.txt (alle Profile) ---\" -ForegroundColor DarkGray\n    $profile = Get-ChildItem 'C:\\Users' -Directory -ErrorAction SilentlyContinue\n    $gefunden = $false\n    foreach ($u in $profile) {\n        $hf = Join-Path $u.FullName 'AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadline\\ConsoleHost_history.txt'\n        if (Test-Path $hf) {\n            $gefunden = $true\n            $f = Get-Item $hf -Force\n            $zeilen = @(Get-Content $hf -ErrorAction SilentlyContinue)\n            Write-Host \"`nBenutzer: $($u.Name)\" -ForegroundColor Yellow\n            Write-Host (\"  Datei: {0:N0} Bytes | Geaendert: {1} | {2} Zeilen\" -f $f.Length,$f.LastWriteTime,$zeilen.Count)\n            if ($zeilen.Count -eq 0) {\n                Write-Host \"  AUFFAELLIG: History-Datei ist LEER.\" -ForegroundColor Red\n            } else {\n                Write-Host \"  --- Inhalt ---\" -ForegroundColor DarkGray\n                $zeilen | ForEach-Object { Write-Host \"    $_\" }\n            }\n        } else {\n            # Datei fehlt, aber Profil existiert\n            $psDir = Join-Path $u.FullName 'AppData\\Roaming\\Microsoft\\Windows\\PowerShell'\n            if (Test-Path $psDir) {\n                Write-Host \"`nBenutzer: $($u.Name)\" -ForegroundColor Yellow\n                Write-Host \"  AUFFAELLIG: PowerShell genutzt, aber History-Datei fehlt.\" -ForegroundColor Red\n            }\n        }\n    }\n    if (-not $gefunden) {\n        Write-Host \"Keine PSReadline-History gefunden.\" -ForegroundColor Yellow\n    }\n\n    # --- 10b: ScriptBlock-Logging (EID 4104) - ergiebigste Quelle ---\n    Write-Host \"`n--- ScriptBlock-Logging (PowerShell/Operational EID 4104) ---\" -ForegroundColor DarkGray\n    $sb = @(Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational';Id=4104} -MaxEvents 200 -ErrorAction SilentlyContinue)\n    if ($sb.Count -gt 0) {\n        Write-Host \"$($sb.Count) Ereignisse geladen. Zeige zusammengesetzte Skriptbloecke:\" -ForegroundColor Green\n        # Nur den ersten Teil jedes mehrteiligen Blocks nehmen (Teil 1 von N),\n        # damit ein Skript nicht N-fach erscheint; Windows-Eigenaufrufe filtern.\n        $sb | Sort-Object TimeCreated -Descending | ForEach-Object {\n            $x = [xml]$_.ToXml()\n            $data = $x.Event.EventData.Data\n            $teil = ($data | Where-Object { $_.Name -eq 'MessageNumber' }).'#text'\n            $code = ($data | Where-Object { $_.Name -eq 'ScriptBlockText' }).'#text'\n            [PSCustomObject]@{ Zeit=$_.TimeCreated; Teil=$teil; Code=$code }\n        } | Where-Object {\n            $_.Teil -eq '1' -and\n            $_.Code -and\n            $_.Code -notmatch 'prompt|PSConsoleHostReadLine|Set-PSReadLine|__VSCode|Get-Module|CompletionPredictor|IsAzureContextPresent'\n        } | Select-Object -First 25 | ForEach-Object {\n            $c = ($_.Code -replace '\\s+',' ').Trim()\n            if ($c.Length -gt 200) { $c = $c.Substring(0,200) + ' [...]' }\n            Write-Host (\"`n  [{0}]\" -f $_.Zeit) -ForegroundColor Yellow\n            Write-Host (\"  {0}\" -f $c)\n        }\n    } else {\n        Write-Host \"ScriptBlock-Logging nicht aktiv oder keine Eintraege.\" -ForegroundColor Yellow\n        Write-Host \"(Standardmaessig aus - Fehlen ist hier NICHT auffaellig.)\" -ForegroundColor DarkGray\n    }\n\n    # --- 10c: Modul-Logging (EID 4103) ---\n    Write-Host \"`n--- Modul-Logging (EID 4103) ---\" -ForegroundColor DarkGray\n    $ml = @(Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational';Id=4103} -MaxEvents 20 -ErrorAction SilentlyContinue)\n    if ($ml.Count -gt 0) {\n        Write-Host \"$($ml.Count) Ereignisse vorhanden.\" -ForegroundColor Green\n    } else {\n        Write-Host \"Kein Modul-Logging.\" -ForegroundColor Yellow\n    }\n\n    # --- 10e: HostApplication aus Klassik-Log (EID 400/600) ---\n    # Standardmaessig AKTIV - zeigt die Startkommandozeile jeder PS-Sitzung.\n    Write-Host \"`n--- Start-Kommandozeilen (Windows PowerShell EID 400/600) ---\" -ForegroundColor DarkGray\n    $klassik = @(Get-WinEvent -FilterHashtable @{LogName='Windows PowerShell';Id=400,600} -MaxEvents 500 -ErrorAction SilentlyContinue)\n    if ($klassik.Count -gt 0) {\n        $verdacht = '-enc |-encodedcommand|-e [A-Za-z0-9+/]{20}|downloadstring|downloadfile|downloaddata|-w hidden|-windowstyle hidden|invoke-expression| iex |frombase64|webclient|start-bitstransfer|certutil.*-urlcache|bitsadmin|invoke-webrequest|invoke-restmethod|\\bcurl |\\bwget |\\birm |\\biwr |net\\.webclient|system\\.net\\.http|http://|https://'\n        $cmds = $klassik | ForEach-Object {\n            if ($_.Message -match 'HostApplication=(.+?)(\\r?\\n|$)') {\n                [PSCustomObject]@{ Zeit=$_.TimeCreated; Cmd=$matches[1].Trim() }\n            }\n        } | Where-Object { $_.Cmd } |\n            Group-Object Cmd | ForEach-Object {\n                $g = $_.Group | Sort-Object Zeit\n                [PSCustomObject]@{ Erstmals=$g[0].Zeit; Zuletzt=$g[-1].Zeit; Anzahl=$_.Count; Cmd=$_.Name }\n            } | Sort-Object Zuletzt -Descending\n\n        Write-Host \"$($cmds.Count) unterschiedliche Start-Kommandozeilen:\" -ForegroundColor Green\n        # Bekannt-gute Aufrufe, die trotz Download-Muster NICHT rot sein sollen\n        # (der Lade-Einzeiler des Pruefwerkzeugs selbst).\n        $eigenesTool = 'gist\\.githubusercontent\\.com/analystdark|pnpcheck\\.ps1'\n        foreach ($c in $cmds) {\n            $ausg = $c.Cmd\n            if ($ausg.Length -gt 200) { $ausg = $ausg.Substring(0,200) + ' [...]' }\n            if ($c.Cmd -match $verdacht -and $c.Cmd -notmatch $eigenesTool) {\n                Write-Host (\"`n  [{0}]  ({1}x)\" -f $c.Zuletzt, $c.Anzahl) -ForegroundColor Red\n                Write-Host (\"  VERDAECHTIG: {0}\" -f $ausg) -ForegroundColor Red\n            } else {\n                Write-Host (\"`n  [{0}]  ({1}x)\" -f $c.Zuletzt, $c.Anzahl) -ForegroundColor Yellow\n                Write-Host (\"  {0}\" -f $ausg)\n            }\n        }\n        Write-Host \"`nRot = Muster wie -enc, hidden, DownloadString, IEX (nicht immer boese,\" -ForegroundColor DarkGray\n        Write-Host \"aber typisch fuer verschleierte Ausfuehrung - einzeln pruefen).\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"Keine 400/600-Ereignisse - Klassik-Log leer oder geleert.\" -ForegroundColor Red\n        Write-Host \"(Dieses Log ist normal AKTIV; ein leeres ist auffaellig.)\" -ForegroundColor DarkGray\n    }\n\n    # --- 10d: Wurde das PowerShell-Log geleert? ---\n    Write-Host \"`n--- PowerShell-Log-Status ---\" -ForegroundColor DarkGray\n    Get-WinEvent -ListLog 'Microsoft-Windows-PowerShell/Operational','Windows PowerShell' -ErrorAction SilentlyContinue |\n        Select-Object LogName, IsEnabled, RecordCount | Format-Table -AutoSize\n\n    Write-Host \"Hinweis: Eine leere/fehlende History bei sonst genutztem PowerShell\" -ForegroundColor DarkGray\n    Write-Host \"deutet auf gezieltes Loeschen hin - selbst ein Befund.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  11 - Discord-Account-IDs (nur User-ID, KEINE Token)\n# ============================================================\nfunction Invoke-DiscordId {\n    Write-Host \"`n=== Discord-Account-IDs ===\" -ForegroundColor Cyan\n    Write-Host \"(Liest ausschliesslich die user_id_cache-Kennung.\" -ForegroundColor DarkGray\n    Write-Host \" Token werden NICHT gelesen oder ausgegeben.)\" -ForegroundColor DarkGray\n\n    $enc = [System.Text.Encoding]::GetEncoding('ISO-8859-1')\n    $script:treffer = @()\n\n    # Hilfsfunktion: eine Datei nach user_id_cache absuchen\n    $scan = {\n        param($file,$user,$quelle)\n        try { $raw = [System.IO.File]::ReadAllText($file, $enc) } catch { return }\n        foreach ($m in [regex]::Matches($raw, 'user_id_cache[^\\d]{0,20}(\\d{17,20})')) {\n            $script:treffer += [PSCustomObject]@{ Benutzer=$user; Quelle=$quelle; ID=$m.Groups[1].Value }\n        }\n    }\n\n    Get-ChildItem 'C:\\Users' -Directory -ErrorAction SilentlyContinue | ForEach-Object {\n        $user   = $_.Name\n        $roam   = Join-Path $_.FullName 'AppData\\Roaming'\n        $local  = Join-Path $_.FullName 'AppData\\Local'\n\n        # --- Desktop-App (alle Discord-Varianten) ---\n        foreach ($fl in @('discord','discordcanary','discordptb','discorddevelopment')) {\n            $ldb = Join-Path $roam \"$fl\\Local Storage\\leveldb\"\n            if (Test-Path $ldb) {\n                Get-ChildItem $ldb -Include '*.ldb','*.log' -Recurse -ErrorAction SilentlyContinue |\n                    ForEach-Object { &amp; $scan $_.FullName $user \"App:$fl\" }\n            }\n        }\n\n        # --- Chromium-Browser (Profile: Default, Profile 1, ...) ---\n        $chromium = @{\n            'Chrome'  = \"$local\\Google\\Chrome\\User Data\"\n            'Edge'    = \"$local\\Microsoft\\Edge\\User Data\"\n            'Brave'   = \"$local\\BraveSoftware\\Brave-Browser\\User Data\"\n            'Vivaldi' = \"$local\\Vivaldi\\User Data\"\n            'OperaGX' = \"$roam\\Opera Software\\Opera GX Stable\"\n            'Opera'   = \"$roam\\Opera Software\\Opera Stable\"\n        }\n        foreach ($b in $chromium.Keys) {\n            $root = $chromium[$b]\n            if (-not (Test-Path $root)) { continue }\n            # Opera hat kein Profile-Unterverzeichnis, Chrome/Edge/Brave schon\n            Get-ChildItem $root -Directory -ErrorAction SilentlyContinue |\n                Where-Object { $_.Name -eq 'Default' -or $_.Name -like 'Profile *' } |\n                ForEach-Object {\n                    $ldb = Join-Path $_.FullName 'Local Storage\\leveldb'\n                    if (Test-Path $ldb) {\n                        Get-ChildItem $ldb -Include '*.ldb','*.log' -Recurse -ErrorAction SilentlyContinue |\n                            ForEach-Object { &amp; $scan $_.FullName $user \"$b/$($_.Directory.Parent.Parent.Name)\" }\n                    }\n                }\n            # Opera-Fall (leveldb direkt unter root)\n            $ldbDirect = Join-Path $root 'Local Storage\\leveldb'\n            if (Test-Path $ldbDirect) {\n                Get-ChildItem $ldbDirect -Include '*.ldb','*.log' -Recurse -ErrorAction SilentlyContinue |\n                    ForEach-Object { &amp; $scan $_.FullName $user $b }\n            }\n        }\n\n        # --- Firefox (localStorage in SQLite) ---\n        $ffRoot = Join-Path $roam 'Mozilla\\Firefox\\Profiles'\n        if (Test-Path $ffRoot) {\n            Get-ChildItem $ffRoot -Directory -ErrorAction SilentlyContinue | ForEach-Object {\n                $lsRoot = Join-Path $_.FullName 'storage\\default'\n                if (Test-Path $lsRoot) {\n                    Get-ChildItem $lsRoot -Directory -ErrorAction SilentlyContinue |\n                        Where-Object { $_.Name -like '*discord*' } | ForEach-Object {\n                            Get-ChildItem $_.FullName -Include '*.sqlite' -Recurse -ErrorAction SilentlyContinue |\n                                ForEach-Object { &amp; $scan $_.FullName $user 'Firefox' }\n                        }\n                }\n            }\n        }\n    }\n\n    if ($script:treffer.Count -eq 0) {\n        Write-Host \"`nKeine Discord-User-ID gefunden.\" -ForegroundColor Yellow\n        Write-Host \"(Discord nicht installiert/eingeloggt, nur portable genutzt, oder Daten entfernt.)\" -ForegroundColor DarkGray\n        return\n    }\n\n    # Deduplizieren und Account-Alter aus der Snowflake ableiten\n    $script:treffer | Group-Object ID | ForEach-Object {\n        $id = $_.Name\n        $created = try {\n            $ms = ([int64]$id -shr 22) + 1420070400000\n            [DateTimeOffset]::FromUnixTimeMilliseconds($ms).UtcDateTime\n        } catch { $null }\n        [PSCustomObject]@{\n            DiscordID   = $id\n            Erstellt    = if ($created) { $created.ToString('dd.MM.yyyy HH:mm') + ' UTC' } else { '?' }\n            GefundenBei = (($_.Group | Select-Object -ExpandProperty Benutzer -Unique) -join ', ')\n            Quelle      = (($_.Group | Select-Object -ExpandProperty Quelle -Unique) -join ', ')\n        }\n    } | Sort-Object Erstellt | Format-Table -AutoSize -Wrap\n\n    $anz = @($script:treffer | Select-Object -ExpandProperty ID -Unique).Count\n    if ($anz -gt 1) {\n        Write-Host \"$anz unterschiedliche Discord-IDs auf diesem Rechner.\" -ForegroundColor Red\n        Write-Host \"Mehrere Accounts koennen auf geteilte Nutzung oder Ban-Ausweichen deuten - im Kontext pruefen.\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"1 Discord-ID gefunden.\" -ForegroundColor Green\n    }\n    Write-Host \"Quelle = App-Variante oder Browser/Profil, in dem die ID lag.\" -ForegroundColor DarkGray\n    Write-Host \"Erstelldatum ist aus der ID berechnet (Snowflake), kein Online-Abruf.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  12 - PE Binary &amp; Driver Heuristics Inspector\n# ============================================================\nfunction Invoke-PEInspector {\n    Write-Host \"`n=== PE Binary &amp; Driver Heuristics Inspector ===\" -ForegroundColor Cyan\n    Write-Host \"(SHA256, BYOVD-Abgleich, Signatur, PE-Header, Entropie, APIs, Keywords)\" -ForegroundColor DarkGray\n    Write-Host \"Tipp: Start-Transcript (P) vorher aktivieren um Ergebnis zu sichern.\" -ForegroundColor DarkGray\n\n    $byovdHashes = @{\n        \"01ee72782b1d4182da0eef7f9859f7aa2f89cc46e9df51ef2807f43db4872121\" = \"RTCore64.sys (Micro-Star CVE-2019-16098)\"\n        \"31f4d725d8d7e01dd582120aa0f23223fa1ac3cb4414f4e5da801db9402ab490\" = \"gdrv.sys (GIGABYTE CVE-2018-19320)\"\n        \"eb601822c9a7da4175345a55018698dc54fe66d11a91d1e434f676ab65d382bb\" = \"Capcom.sys (Root-Exploit / SMEP)\"\n        \"046e8c8959d72215a774136e632831f2ff2cc0bcbc2becc278912efee7e3cf40\" = \"mhyprot2.sys (miHoYo Process/Memory Killer)\"\n        \"a66d92ff488e0402b8813c9fb60cf649372d65ab19aa67a421dff03fc29fc2a2\" = \"AsrDrv103.sys (ASRock Physical Memory R/W)\"\n        \"60c38ea120015ff363fe9d63c5a70ebfb44766b9319de8d98d248b6bb83c509a\" = \"ene.sys (ENE Technology DeviceIoControl)\"\n    }\n    $packerSections = @(\"upx0\",\"upx1\",\"upx2\",\".vmp0\",\".vmp1\",\".vmp2\",\"themida\",\".themida\",\".enigma1\",\".enigma2\",\".aspack\",\".adata\",\"pec1\",\"pec2\",\".mpress1\",\".mpress2\")\n    $dangerousAPIs = @{\n        \"Process Injection\"  = @(\"VirtualAllocEx\",\"WriteProcessMemory\",\"CreateRemoteThread\",\"NtQueueApcThread\",\"RtlCreateUserThread\",\"SetThreadContext\")\n        \"Memory Tampering\"   = @(\"NtMapViewOfSection\",\"ZwMapViewOfSection\",\"VirtualProtectEx\",\"NtWriteVirtualMemory\")\n        \"Kernel Interaction\" = @(\"ZwLoadDriver\",\"NtLoadDriver\",\"DeviceIoControl\",\"ObRegisterCallbacks\",\"MmCopyVirtualMemory\",\"MmMapIoSpace\")\n        \"Anti-Debug/Evasion\" = @(\"IsDebuggerPresent\",\"CheckRemoteDebuggerPresent\",\"NtQueryInformationProcess\",\"NtSetInformationThread\")\n    }\n    $suspiciousStrings = @(\n        # Cheat-Funktionen\n        'aimbot','wallhack','silentaim','triggerbot','cheatengine',\n        'processhacker','kdmapper','blackbone','drvload','kernelhook','minifilter',\n        # Injection-Techniken (aus realem WptsExtensions.dll Fund)\n        'manualmap','manual map','manualmapping',\n        'kernelmap','kernel manual map',\n        'injecthost','injectmonitor','injecttrigger',\n        'trigger=%s','injected ok','inject failed',\n        # Weitere Injection-Indikatoren\n        'reflectiveinject','reflective inject','shellcode',\n        'dllinjection','dll injection','remotethread',\n        'mapviewofsection inject','zwmapviewofsection'\n    )\n    # Wortgrenz-Keywords (kommen auch in legitimen Dateien vor)\n    $suspiciousStringsWB = @('hack','inject')\n\n    # Datei waehlen\n    $ziel = Read-Host \"`nPfad zur Datei (.exe/.dll/.sys) - leer lassen fuer Datei-Dialog\"\n    if ([string]::IsNullOrWhiteSpace($ziel)) {\n        Add-Type -AssemblyName System.Windows.Forms -ErrorAction SilentlyContinue\n        $dlg = New-Object System.Windows.Forms.OpenFileDialog\n        $dlg.Filter = \"Binaries &amp; Treiber (*.exe;*.dll;*.sys)|*.exe;*.dll;*.sys|Alle (*.*)|*.*\"\n        if ($dlg.ShowDialog() -eq 'OK') { $ziel = $dlg.FileName }\n        else { Write-Host \"Abgebrochen.\" -ForegroundColor Yellow; return }\n    }\n    if (-not (Test-Path $ziel)) { Write-Host \"Datei nicht gefunden: $ziel\" -ForegroundColor Red; return }\n    if ((Get-Item $ziel).PSIsContainer) { Write-Host \"Pfad ist ein Ordner, keine Datei: $ziel\" -ForegroundColor Red; return }\n\n    $dateiname = Split-Path $ziel -Leaf\n    Write-Host \"`nZiel: $ziel\" -ForegroundColor White\n    Write-Host (\"=\" * 70) -ForegroundColor DarkGray\n\n    try { $bytes = [System.IO.File]::ReadAllBytes($ziel) }\n    catch { Write-Host \"Lesefehler: $_\" -ForegroundColor Red; return }\n\n    # Phase 1: SHA256 &amp; BYOVD\n    Write-Host \"`n[*] Phase 1: SHA256 &amp; BYOVD-Abgleich\" -ForegroundColor Cyan\n    $hasher = [System.Security.Cryptography.SHA256]::Create()\n    $sha256 = [BitConverter]::ToString($hasher.ComputeHash($bytes)).Replace(\"-\",\"\").ToLower()\n    Write-Host \"    SHA256 : $sha256\"\n    if ($byovdHashes.ContainsKey($sha256)) {\n        Write-Host \"    [!!!] BYOVD ERKANNT: $($byovdHashes[$sha256])\" -ForegroundColor Red\n    } else {\n        Write-Host \"    BYOVD  : Kein bekannter anfaelliger Treiber-Hash.\" -ForegroundColor Green\n    }\n\n    # Phase 2: Signatur &amp; EKUs\n    Write-Host \"`n[*] Phase 2: Digitale Signatur &amp; Zertifikats-EKUs\" -ForegroundColor Cyan\n    $sig = Get-AuthenticodeSignature -FilePath $ziel -ErrorAction SilentlyContinue\n    if ($sig) {\n        $sigCol = if ($sig.Status -eq 'Valid') { 'Green' } else { 'Red' }\n        Write-Host \"    Status     : $($sig.Status)\" -ForegroundColor $sigCol\n        if ($sig.SignerCertificate) {\n            Write-Host \"    Inhaber    : $($sig.SignerCertificate.Subject -replace '^CN=([^,]+).*','$1')\"\n            Write-Host \"    Aussteller : $($sig.SignerCertificate.Issuer -replace '^CN=([^,]+).*','$1')\"\n            foreach ($ext in $sig.SignerCertificate.Extensions) {\n                if ($ext -is [System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension]) {\n                    foreach ($oid in $ext.EnhancedKeyUsages) {\n                        switch ($oid.Value) {\n                            \"1.3.6.1.4.1.311.61.1.1\" { Write-Host \"    [EKU] WHQL Hardware-Signatur\" -ForegroundColor Green }\n                            \"1.3.6.1.4.1.311.10.3.6\" { Write-Host \"    [EKU] Windows Kernel-Mode Driver Signing\" -ForegroundColor Green }\n                            \"1.3.6.1.5.5.7.3.3\"       { Write-Host \"    [EKU] Standard Code-Signing\" }\n                        }\n                    }\n                }\n            }\n        } else { Write-Host \"    [!] Nicht signiert.\" -ForegroundColor Red }\n    }\n\n    # Phase 3: PE-Header\n    Write-Host \"`n[*] Phase 3: PE-Header &amp; Anomalien\" -ForegroundColor Cyan\n    if ($bytes.Length -lt 64) { Write-Host \"    Datei zu klein.\" -ForegroundColor Red; return }\n\n    $stream = [System.IO.FileStream]::new($ziel, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)\n    $reader = [System.IO.BinaryReader]::new($stream)\n    $highestRawEnd = 0\n\n    try {\n        if ($reader.ReadUInt16() -ne 0x5A4D) { Write-Host \"    Kein MZ-Header.\" -ForegroundColor Red; return }\n        $null = $stream.Seek(0x3C, 0); $peOff = $reader.ReadUInt32()\n        $null = $stream.Seek($peOff, 0)\n        if ($reader.ReadUInt32() -ne 0x00004550) { Write-Host \"    Keine PE-Signatur.\" -ForegroundColor Red; return }\n\n        $null = $reader.ReadUInt16()              # Machine\n        $numSec = $reader.ReadUInt16()\n        $null = $reader.ReadUInt32()              # TimeDateStamp\n        $null = $stream.Seek(10, 1)\n        $optHdrSize = $reader.ReadUInt16()\n        $null = $reader.ReadUInt16()              # Characteristics\n        $optPos = $stream.Position\n        $optMagic = $reader.ReadUInt16()\n        $is64 = ($optMagic -eq 0x20B)\n        $null = $stream.Seek($optPos + 16, 0); $epRVA = $reader.ReadUInt32()\n        $null = $stream.Seek($optPos + 32, 0)\n        $secAlign = $reader.ReadUInt32(); $fileAlign = $reader.ReadUInt32()\n        $null = $stream.Seek(16, 1); $sizeHdr = $reader.ReadUInt32()\n        $dllCharOff = if ($is64) { $optPos + 70 } else { $optPos + 46 }\n        $null = $stream.Seek($dllCharOff, 0); $dllChar = $reader.ReadUInt16()\n        $hasASLR = ($dllChar -band 0x0040) -ne 0\n        $hasDEP  = ($dllChar -band 0x0100) -ne 0\n\n        Write-Host \"    Architektur : $(if($is64){'x64'}else{'x86'})\"\n        Write-Host (\"    ASLR        : \" + $(if($hasASLR){'An'}else{'[!] AUS'})) -ForegroundColor $(if($hasASLR){'White'}else{'Red'})\n        Write-Host (\"    DEP/NX      : \" + $(if($hasDEP){'An'}else{'[!] AUS'})) -ForegroundColor $(if($hasDEP){'White'}else{'Red'})\n        Write-Host \"    Alignments  : Sektion=0x$($secAlign.ToString('X')) | Datei=0x$($fileAlign.ToString('X'))\"\n        if ($sizeHdr -gt 4096) { Write-Host \"    [!] SizeOfHeaders ungewoehnlich gross: $sizeHdr Bytes\" -ForegroundColor Yellow }\n\n        # Sanity-Check: Werte ausserhalb realistischer Grenzen = gepackt/geschuetzt\n        $parserValid = $true\n        if ($secAlign -gt 0x200000 -or $fileAlign -gt 0x100000 -or $sizeHdr -gt 0x100000) {\n            Write-Host \"`n    [!] PARSER-WARNUNG: Header-Werte ausserhalb normaler Bereiche.\" -ForegroundColor Yellow\n            Write-Host \"        SectionAlignment=0x$($secAlign.ToString('X')) | FileAlignment=0x$($fileAlign.ToString('X')) | SizeOfHeaders=$sizeHdr\" -ForegroundColor Yellow\n            Write-Host \"        Datei ist wahrscheinlich gepackt oder geschuetzt (z.B. Electron/Chromium, VMProtect, Themida).\" -ForegroundColor Yellow\n            Write-Host \"        Phase 4 (Sektionen) wird uebersprungen - Ergebnisse waeren nicht zuverlaessig.\" -ForegroundColor Yellow\n            $parserValid = $false\n        }\n\n        # Phase 4: Sektionen\n        Write-Host \"`n[*] Phase 4: Sektionen, Entropie &amp; Packer-Erkennung\" -ForegroundColor Cyan\n        if (-not $parserValid) {\n            Write-Host \"    Uebersprungen (siehe Warnung oben).\" -ForegroundColor Yellow\n        } else {\n        $null = $stream.Seek($peOff + 4 + 20 + $optHdrSize, 0)\n        $sectionMap = @()\n\n        for ($i = 0; $i -lt $numSec; $i++) {\n            $nameB = $reader.ReadBytes(8)\n            $sn    = [System.Text.Encoding]::ASCII.GetString($nameB).Trim([char]0)\n            $vSize = $reader.ReadUInt32(); $vAddr = $reader.ReadUInt32()\n            $rSize = $reader.ReadUInt32(); $rPtr  = $reader.ReadUInt32()\n            $null = $stream.Seek(12, 1); $sChar = $reader.ReadUInt32()\n            $isX = ($sChar -band 0x20000000) -ne 0\n            $isW = ($sChar -band 0x80000000) -ne 0\n            if (($rPtr + $rSize) -gt $highestRawEnd) { $highestRawEnd = $rPtr + $rSize }\n            $sectionMap += @{ VirtAddr=$vAddr; VirtSize=[Math]::Max($vSize,1); RawPtr=$rPtr }\n\n            # Entropie inline berechnen\n            $ent = 0.0\n            if ($rSize -gt 0 -and ($rPtr + $rSize) -le $bytes.Length) {\n                $cnt = @{}\n                for ($x = $rPtr; $x -lt ($rPtr + $rSize); $x++) { $b = $bytes[$x]; $cnt[$b] = $cnt[$b] + 1 }\n                foreach ($k in $cnt.Keys) { $p = $cnt[$k] / $rSize; $ent -= $p * [Math]::Log($p, 2) }\n                $ent = [Math]::Round($ent, 2)\n            }\n\n            $fl = \"\"\n            if ($isW -and $isX) { $fl += \" [ALERT: W+X]\" }\n            if ($packerSections -contains $sn.ToLower()) { $fl += \" [PACKER]\" }\n            $col = if ($fl) { 'Red' } elseif ($ent -gt 7.0) { 'Yellow' } else { 'White' }\n            Write-Host (\"    [{0}] Raw:{1,-8} Virt:{2,-8} Entropie:{3}{4}\" -f $sn.PadRight(8),$rSize,$vSize,$ent,$fl) -ForegroundColor $col\n            if ($rSize -eq 0 -and $vSize -gt 0) { Write-Host \"      [!] 0 Bytes auf Platte, $vSize im RAM (Loader/Unpacker)\" -ForegroundColor Yellow }\n            if ($sn -eq '.text' -and $ent -gt 7.0) { Write-Host \"      [!] .text Entropie $ent/8.0 - Code verschluesselt oder gepackt!\" -ForegroundColor Red }\n        }\n\n        # Phase 4b: Import-Tabelle &amp; DLL-Hijacking-Kandidaten\n        Write-Host \"`n[*] Phase 4b: Import-Tabelle &amp; DLL-Hijacking-Check\" -ForegroundColor Cyan\n        $importDirPos = if ($is64) { $optPos + 120 } else { $optPos + 104 }\n        $null = $stream.Seek($importDirPos, 0)\n        $importRVA  = $reader.ReadUInt32()\n        $importSz   = $reader.ReadUInt32()\n\n        if ($importRVA -eq 0 -or $importSz -eq 0) {\n            Write-Host \"    Keine Import-Tabelle vorhanden.\" -ForegroundColor DarkGray\n        } else {\n            # RVA -&gt; Datei-Offset\n            $importOff = -1L\n            foreach ($s in $sectionMap) {\n                if ($importRVA -ge $s.VirtAddr -and $importRVA -lt ($s.VirtAddr + $s.VirtSize)) {\n                    $importOff = [int64]($importRVA - $s.VirtAddr + $s.RawPtr); break\n                }\n            }\n\n            if ($importOff -lt 0) {\n                Write-Host \"    Import-Tabelle nicht mappbar (gepackt?).\" -ForegroundColor Yellow\n            } else {\n                $importedDLLs = @()\n                $pos = [int64]$importOff\n                while ($pos + 20 -le $bytes.Length) {\n                    $nameRVA = [BitConverter]::ToUInt32($bytes, $pos + 12)\n                    if ($nameRVA -eq 0) { break }\n                    $nameOff = -1L\n                    foreach ($s in $sectionMap) {\n                        if ($nameRVA -ge $s.VirtAddr -and $nameRVA -lt ($s.VirtAddr + $s.VirtSize)) {\n                            $nameOff = [int64]($nameRVA - $s.VirtAddr + $s.RawPtr); break\n                        }\n                    }\n                    if ($nameOff -ge 0) {\n                        $sb = [System.Text.StringBuilder]::new()\n                        $nx = [int64]$nameOff\n                        while ($nx -lt $bytes.Length -and $bytes[$nx] -ne 0) { $null = $sb.Append([char]$bytes[$nx]); $nx++ }\n                        $dn = $sb.ToString()\n                        if ($dn -match '(?i)\\.dll$') { $importedDLLs += $dn }\n                    }\n                    $pos += 20\n                }\n\n                Write-Host \"    Importierte DLLs: $($importedDLLs.Count)\"\n                $parentDir = Split-Path $ziel -Parent\n                $hijackFound = $false\n                foreach ($dll in $importedDLLs) {\n                    $sameDir = Join-Path $parentDir $dll\n                    if (Test-Path $sameDir) {\n                        $dllSig = Get-AuthenticodeSignature $sameDir -ErrorAction SilentlyContinue\n                        $dllStatus = if ($dllSig) { $dllSig.Status } else { 'Unbekannt' }\n                        $dllColor = if ($dllStatus -eq 'Valid') { 'Yellow' } else { 'Red' }\n                        Write-Host (\"    [!] HIJACK-KANDIDAT: {0}\" -f $dll) -ForegroundColor $dllColor\n                        Write-Host (\"        Pfad: {0}\" -f $sameDir) -ForegroundColor $dllColor\n                        Write-Host (\"        Signatur: {0}\" -f $dllStatus) -ForegroundColor $dllColor\n                        $hijackFound = $true\n                    }\n                }\n                if (-not $hijackFound) {\n                    Write-Host \"    Keine gleichnamigen DLLs im selben Ordner.\" -ForegroundColor Green\n                }\n            }\n        }\n        } # Ende else parserValid\n\n        # Phase 5: Overlay &amp; eingebettete PEs\n        Write-Host \"`n[*] Phase 5: Overlay &amp; eingebettete PE-Dateien\" -ForegroundColor Cyan\n        if ($bytes.Length -gt $highestRawEnd -and $highestRawEnd -gt 0) {\n            $ovSize = $bytes.Length - $highestRawEnd\n            $cnt2 = @{}\n            for ($x = $highestRawEnd; $x -lt $bytes.Length; $x++) { $b=$bytes[$x]; $cnt2[$b]=$cnt2[$b]+1 }\n            $oe = 0.0\n            foreach ($k in $cnt2.Keys) { $p=$cnt2[$k]/$ovSize; $oe -= $p*[Math]::Log($p,2) }\n            Write-Host \"    [!] OVERLAY: $ovSize Bytes angehaengt (Entropie $([Math]::Round($oe,2))/8.0)\" -ForegroundColor Red\n        } else { Write-Host \"    Kein Overlay.\" -ForegroundColor Green }\n\n        $embN = 0\n        for ($j = 64; $j -lt ($bytes.Length - 1024); $j += 4) {\n            if ($bytes[$j] -eq 0x4D -and $bytes[$j+1] -eq 0x5A) {\n                $lf = [BitConverter]::ToUInt32($bytes, $j + 0x3C)\n                if ($lf -gt 0 -and ($j+$lf+4) -lt $bytes.Length -and $bytes[$j+$lf] -eq 0x50 -and $bytes[$j+$lf+1] -eq 0x45) {\n                    Write-Host \"    [!] Eingebettetes PE bei Offset 0x$($j.ToString('X')) (Dropper/Payload?)\" -ForegroundColor Red\n                    $embN++\n                }\n            }\n        }\n        if ($embN -eq 0) { Write-Host \"    Keine eingebetteten PE-Dateien.\" -ForegroundColor Green }\n\n    } finally { $reader.Close() }\n\n    # Phase 6: PDB-Pfad\n    Write-Host \"`n[*] Phase 6: Debug-Informationen (PDB-Pfad)\" -ForegroundColor Cyan\n    $pdb = $null\n    for ($i = 0; $i -lt ($bytes.Length - 28); $i++) {\n        if ($bytes[$i] -eq 0x52 -and $bytes[$i+1] -eq 0x53 -and $bytes[$i+2] -eq 0x44 -and $bytes[$i+3] -eq 0x53) {\n            $ss = $i + 24; $se = $ss\n            while ($se -lt $bytes.Length -and $bytes[$se] -ne 0) { $se++ }\n            if ($se -gt $ss) {\n                $p = [System.Text.Encoding]::UTF8.GetString($bytes, $ss, $se-$ss)\n                if ($p -match '(?i)\\.pdb$') { $pdb = $p; break }\n            }\n        }\n    }\n    if (-not $pdb) {\n        $ra = [System.Text.Encoding]::ASCII.GetString($bytes)\n        if ($ra -match '([a-zA-Z]:\\\\[^\\x00-\\x1F\\x7F-\\xFF]+\\.pdb)') { $pdb = $matches[1] }\n    }\n    if ($pdb) {\n        Write-Host \"    Build-Pfad: $pdb\"\n        if ($pdb -match '(?i)(cheat|inject|hook|hack|aim|esp|driver|bypass)') {\n            Write-Host \"    [!] ALERT: Verdaechtiges Keyword im Build-Pfad!\" -ForegroundColor Red\n        }\n    } else { Write-Host \"    PDB: Nicht gefunden oder gestrippt.\" -ForegroundColor DarkGray }\n\n    # Phase 7: High-Risk APIs &amp; Cheat-Keywords\n    Write-Host \"`n[*] Phase 7: High-Risk APIs &amp; Cheat-Keywords\" -ForegroundColor Cyan\n    $rawAscii = [System.Text.Encoding]::ASCII.GetString($bytes)\n    $apiTreffer = $false\n    foreach ($cat in $dangerousAPIs.Keys) {\n        $matched = @($dangerousAPIs[$cat] | Where-Object { $rawAscii -match [regex]::Escape($_) })\n        if ($matched.Count -gt 0) {\n            Write-Host \"    [!] $cat ($($matched.Count)): $($matched -join ', ')\" -ForegroundColor Red\n            $apiTreffer = $true\n        }\n    }\n    if (-not $apiTreffer) { Write-Host \"    Keine gefaehrlichen APIs im Klartext.\" -ForegroundColor Green }\n\n    $foundKW = @($suspiciousStrings | Where-Object { $rawAscii -match [regex]::Escape($_) })\n    $foundKW += @($suspiciousStringsWB | Where-Object { $rawAscii -match \"\\b$([regex]::Escape($_))\\b\" })\n    $foundKW = $foundKW | Select-Object -Unique\n    if ($foundKW.Count -gt 0) {\n        Write-Host \"    [!] Verdaechtige Keywords: $($foundKW -join ', ')\" -ForegroundColor Red\n    } else { Write-Host \"    Keine Cheat-Keywords im Klartext.\" -ForegroundColor Green }\n\n    Write-Host \"`n$('=' * 70)\" -ForegroundColor DarkGray\n    Write-Host \"Scan abgeschlossen: $dateiname\" -ForegroundColor Cyan\n    Write-Host \"Hinweis: Ergebnis wird im aktiven Transcript gesichert (Menue P).\" -ForegroundColor DarkGray\n    Write-Host \"Fuer groessere Dateien (.sys/.exe) empfiehlt sich zusaetzlich VirusTotal.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  13 - DLL Hijacking Live-Check (laufende Prozesse)\n# ============================================================\nfunction Invoke-DLLHijackCheck {\n    Write-Host \"`n=== DLL Hijacking Live-Check ===\" -ForegroundColor Cyan\n    Write-Host \"(Pr\u00c3\u00bcft laufende Prozesse auf Module aus unerwarteten Pfaden)\" -ForegroundColor DarkGray\n\n    # Pfade die als legitim gelten\n    $okPfade = @(\n        \"$env:SystemRoot\\\",\n        \"$env:ProgramFiles\\\",\n        \"${env:ProgramFiles(x86)}\\\",\n        \"$env:ProgramData\\Microsoft\\\"\n    )\n\n    Write-Host \"`n--- Module aus unerwarteten Pfaden ---\" -ForegroundColor DarkGray\n    $treffer = @()\n\n    Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Path } | ForEach-Object {\n        $proc    = $_\n        $procDir = (Split-Path $proc.Path -Parent).ToLower().TrimEnd('\\') + '\\'\n        try {\n            $proc.Modules | Where-Object { $_.FileName -and $_.FileName -notmatch '(?i)\\.(node|ocx|cpl|ax)$' } | ForEach-Object {\n                $modPath = $_.FileName\n                $modPathL = $modPath.ToLower()\n                $istOK = ($okPfade | Where-Object { $modPathL.StartsWith($_.ToLower()) }) -or\n                         $modPathL.StartsWith($procDir)\n                if (-not $istOK) {\n                    $sig = Get-AuthenticodeSignature $modPath -ErrorAction SilentlyContinue\n                    $status = if ($sig) { $sig.Status } else { 'Unbekannt' }\n                    $treffer += [PSCustomObject]@{\n                        Prozess  = $proc.Name\n                        PID      = $proc.Id\n                        Modul    = $_.ModuleName\n                        Pfad     = $modPath\n                        Signatur = $status\n                    }\n                }\n            }\n        } catch {}\n    }\n\n    if ($treffer.Count -gt 0) {\n        # Unsignierte zuerst\n        $treffer | Sort-Object Signatur, Prozess | ForEach-Object {\n            $col = if ($_.Signatur -eq 'Valid') { 'Yellow' } else { 'Red' }\n            Write-Host (\"`n  [{0}] PID {1}\" -f $_.Prozess, $_.PID) -ForegroundColor $col\n            Write-Host (\"  Modul : {0}\" -f $_.Modul) -ForegroundColor $col\n            Write-Host (\"  Pfad  : {0}\" -f $_.Pfad) -ForegroundColor $col\n            Write-Host (\"  Sig   : {0}\" -f $_.Signatur) -ForegroundColor $col\n        }\n        $unsigned = @($treffer | Where-Object { $_.Signatur -ne 'Valid' })\n        Write-Host \"`n$($treffer.Count) Treffer gesamt, davon $($unsigned.Count) nicht gueltig signiert.\" -ForegroundColor $(if($unsigned.Count -gt 0){'Red'}else{'Yellow'})\n    } else {\n        Write-Host \"Keine auffaelligen Module gefunden.\" -ForegroundColor Green\n    }\n\n    # Spielprozesse gezielt pruefen\n    Write-Host \"`n--- Spielprozesse gezielt pruefen ---\" -ForegroundColor DarkGray\n    $spielNamen = @('FiveM','FiveM_GTAProcess','GTA5','RageMP','altv','RedM','cfx')\n    $spielProcs = @(Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Name -match ($spielNamen -join '|') })\n    if ($spielProcs.Count -gt 0) {\n        foreach ($sp in $spielProcs) {\n            Write-Host \"`n  Prozess: $($sp.Name) (PID $($sp.Id))\" -ForegroundColor Yellow\n            try {\n                $sp.Modules | Where-Object { $_.FileName } | ForEach-Object {\n                    $sig = Get-AuthenticodeSignature $_.FileName -ErrorAction SilentlyContinue\n                    $status = if ($sig) { $sig.Status } else { 'Unbekannt' }\n                    if ($status -ne 'Valid') {\n                        Write-Host (\"  [!] Unsigniert: {0}\" -f $_.FileName) -ForegroundColor Red\n                    }\n                }\n            } catch {\n                Write-Host \"  Zugriff auf Module verweigert (Adminrechte noetig).\" -ForegroundColor Yellow\n            }\n        }\n    } else {\n        Write-Host \"Keine FiveM/GTA-Prozesse laufend.\" -ForegroundColor DarkGray\n    }\n\n    Write-Host \"`nHinweis: Gelb = signiert aber ungewoehnlicher Pfad.\" -ForegroundColor DarkGray\n    Write-Host \"         Rot  = unsigniert oder Signatur ungueltig = Befund pruefen.\" -ForegroundColor DarkGray\n    Write-Host \"Fuer Live-Analyse laufender Injektion: Sysinternals Process Monitor empfohlen.\" -ForegroundColor DarkGray\n\n    # --- Bekannte DLL-Hijacking-Zielordner ---\n    Write-Host \"`n--- Bekannte Hijacking-Zielordner (wbem, Tasks, Sysprep...) ---\" -ForegroundColor DarkGray\n\n    # Bekannte Ziel-DLLs fuer wbem-Hijacking (aus realen Faellen)\n    # PHANTOM = diese Dateien existieren auf normalem Windows NICHT in wbem\n    # Ihr blo\u00c3\u0178es Vorhandensein ist bereits verdaechtig - Signatur egal\n    $wbemPhantom = @(\n        'WptsExtensions.dll',   # Phantom-DLL - existiert nie in wbem (Trojan.Yogi u.a.)\n        'WaasMedicSvc.dll',     # Phantom-DLL - gehoert nicht in wbem\n        'wlbsctrl.dll'          # Phantom-DLL - IKEEXT-Hijacking-Ziel\n    )\n    $wbemTargets = @(\n        'msdtcprx.dll',\n        'wmicmiplugin.dll',\n        'wbemcomn.dll'\n    )\n\n    $hijackOrdner = @{\n        'wbem'    = 'C:\\Windows\\System32\\wbem'\n        'Tasks'   = 'C:\\Windows\\System32\\Tasks'\n        'Sysprep' = 'C:\\Windows\\System32\\Sysprep'\n        'Spool'   = 'C:\\Windows\\System32\\spool\\drivers\\x64\\3'\n    }\n\n    $hijackFund = $false\n    foreach ($name in $hijackOrdner.Keys) {\n        $ordner = $hijackOrdner[$name]\n        if (-not (Test-Path $ordner)) { continue }\n\n        $dlls = @(Get-ChildItem $ordner -Filter '*.dll' -ErrorAction SilentlyContinue)\n        if ($dlls.Count -eq 0) { continue }\n\n        Write-Host \"`n  [$name] $ordner\" -ForegroundColor DarkGray\n        foreach ($f in $dlls) {\n            $sig = Get-AuthenticodeSignature $f.FullName -ErrorAction SilentlyContinue\n            $status = if ($sig) { $sig.Status } else { 'Unbekannt' }\n            $signierer = if ($sig -and $sig.SignerCertificate) {\n                $sig.SignerCertificate.Subject -replace '^CN=([^,]+).*','$1'\n            } else { '-' }\n\n            $istMS      = $signierer -match '(?i)Microsoft'\n            $istPhantom = $wbemPhantom -contains $f.Name\n            $istTarget  = $wbemTargets -contains $f.Name\n            $istVerd    = (-not $istMS) -or ($status -ne 'Valid')\n\n            if ($istPhantom) {\n                # Phantom-DLLs sind immer ein Befund - egal ob signiert\n                $col = 'Red'\n                Write-Host (\"    [!!!] PHANTOM-DLL: {0} | Sig: {1} | {2}\" -f $f.Name, $status, $signierer) -ForegroundColor $col\n                Write-Host (\"          Diese Datei gehoert NICHT in diesen Ordner - Hijacking-Beweis!\" ) -ForegroundColor $col\n                $hijackFound = $true\n            } elseif ($istVerd -or $istTarget) {\n                $col = if ($status -ne 'Valid' -or -not $istMS) { 'Red' } else { 'Yellow' }\n                $hinweis = if ($istTarget -and -not $istMS) { ' [BEKANNTES HIJACK-ZIEL + FREMD]' } elseif ($istTarget) { ' [BEKANNTES HIJACK-ZIEL]' } else { '' }\n                Write-Host (\"    [!] {0} | Sig: {1} | {2}{3}\" -f $f.Name, $status, $signierer, $hinweis) -ForegroundColor $col\n                $hijackFund = $true\n            }\n        }\n    }\n\n    if (-not $hijackFund) {\n        Write-Host \"  Keine auffaelligen DLLs in Hijacking-Zielordnern.\" -ForegroundColor Green\n    }\n\n    # --- setupapi.dev.log auf USB-Spuren pruefen ---\n    Write-Host \"`n--- SetupAPI: USB-Cheat-Lader-Spuren ---\" -ForegroundColor DarkGray\n    $setupLog = 'C:\\Windows\\INF\\setupapi.dev.log'\n    if (Test-Path $setupLog) {\n        $hits = @(Select-String -Path $setupLog -Pattern 'setupplatform|cheat|hack|bypass|inject|loader|DMASetup|dma_setup' -ErrorAction SilentlyContinue)\n        if ($hits.Count -gt 0) {\n            Write-Host \"  [!] Verdaechtige Begriffe in setupapi.dev.log:\" -ForegroundColor Red\n            $hits | Select-Object -First 20 | ForEach-Object { Write-Host \"    $($_.Line.Trim())\" -ForegroundColor Red }\n        } else {\n            Write-Host \"  Keine verdaechtigen Cheat-Begriffe in setupapi.dev.log.\" -ForegroundColor Green\n        }\n        # Datei-Zeitstempel: frisch erstellt nach Windows-Installation?\n        $f = Get-Item $setupLog\n        $os2 = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue\n        if ($os2 -and $f.CreationTime -gt $os2.InstallDate.AddDays(7)) {\n            Write-Host \"  [!] setupapi.dev.log wurde deutlich nach Windows-Installation erstellt - moeglicherweise neu angelegt (Spurverwischung).\" -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"  setupapi.dev.log fehlt - Datei koennte geloescht worden sein.\" -ForegroundColor Red\n    }\n}\n\n# ============================================================\n#  14 - Systemprozesse &amp; Registry-Injection-Vektoren\n# ============================================================\nfunction Invoke-SystemProcessCheck {\n    Write-Host \"`n=== Systemprozesse &amp; Injection-Vektoren ===\" -ForegroundColor Cyan\n    Write-Host \"(Pr\u00c3\u00bcft kritische Prozesse auf fremde Module + Registry-Einstiegspunkte)\" -ForegroundColor DarkGray\n\n    # --- 14a: Kritische Systemprozesse auf nicht-Microsoft-Module ---\n    Write-Host \"`n--- Fremde Module in Systemprozessen ---\" -ForegroundColor DarkGray\n    $kritisch = @('svchost','lsass','winlogon','services','spoolsv','wininit',\n                  'csrss','explorer','lsm','dllhost','dwm','ctfmon','taskhostw',\n                  'msdtc','audiodg','SearchIndexer','WmiPrvSE')\n\n    # Bekannte legitime Dritt-Hersteller die in Systemprozesse laden duerfen\n    $vertrauenswuerdig = @(\n        'Malwarebytes','NVIDIA','Adobe','Intel Corporation','Advanced Micro Devices',\n        'Logitech','Razer','SteelSeries','Corsair','ASUS','MSI','Gigabyte',\n        'Realtek','Qualcomm','Broadcom','Apple','Google','Dropbox','OneDrive'\n    )\n    # Geschuetzte Prozesse bei denen leere Module normal sind (PPL)\n    $geschuetzt = @('lsass','csrss','wininit','services','smss','MsMpEng')\n\n    $systemFund = $false\n    foreach ($pName in $kritisch) {\n        $procs = @(Get-Process -Name $pName -ErrorAction SilentlyContinue)\n        foreach ($proc in $procs) {\n            try {\n                $fremd   = @()\n                $pathlos = @()\n                $proc.Modules | ForEach-Object {\n                    # Nur Module MIT Namen aber OHNE Pfad = Reflective Injection Kandidat\n                    # Leere Eintraege ohne Namen = Enumerierungs-Artefakt, kein Fund\n                    if ($_.ModuleName -and -not $_.FileName) {\n                        if ($geschuetzt -notcontains $pName) {\n                            $pathlos += $_.ModuleName\n                        }\n                        return\n                    }\n                    if (-not $_.FileName) { return }\n\n                    $sig = Get-AuthenticodeSignature $_.FileName -ErrorAction SilentlyContinue\n                    $istMS = $sig -and $sig.Status -eq 'Valid' -and\n                             $sig.SignerCertificate -and\n                             $sig.SignerCertificate.Subject -match '(?i)Microsoft'\n                    if (-not $istMS) {\n                        $status = if ($sig) { $sig.Status } else { 'Unbekannt' }\n                        $sign   = if ($sig -and $sig.SignerCertificate) {\n                            $sig.SignerCertificate.Subject -replace '^CN=([^,]+).*','$1'\n                        } else { 'Nicht signiert' }\n                        # Bekannte legitime Hersteller: grau, nicht rot\n                        $istBekannt = $vertrauenswuerdig | Where-Object { $sign -match [regex]::Escape($_) }\n                        $fremd += [PSCustomObject]@{\n                            Modul    = $_.ModuleName\n                            Pfad     = $_.FileName\n                            Sig      = $status\n                            Signierer= $sign\n                            Bekannt  = [bool]$istBekannt\n                        }\n                    }\n                }\n\n                # Nur ausgeben wenn wirklich verdaechtig (unbekannt/unsigniert ODER pathlos)\n                $echteWarnungen = @($fremd | Where-Object { -not $_.Bekannt -or $_.Sig -ne 'Valid' })\n                $bekannteListe  = @($fremd | Where-Object { $_.Bekannt -and $_.Sig -eq 'Valid' })\n\n                if ($echteWarnungen.Count -gt 0 -or $pathlos.Count -gt 0) {\n                    Write-Host (\"`n  [{0}] PID {1}\" -f $proc.Name, $proc.Id) -ForegroundColor Red\n                    $systemFund = $true\n                    foreach ($m in $echteWarnungen) {\n                        $col = if ($m.Sig -ne 'Valid') { 'Red' } else { 'Yellow' }\n                        Write-Host (\"    [!] {0}\" -f $m.Modul) -ForegroundColor $col\n                        Write-Host (\"        Pfad     : {0}\" -f $m.Pfad) -ForegroundColor $col\n                        Write-Host (\"        Sig      : {0} | {1}\" -f $m.Sig, $m.Signierer) -ForegroundColor $col\n                    }\n                    foreach ($m in $pathlos) {\n                        Write-Host (\"    [!!!] Modul ohne Dateipfad: $m (Reflective Injection?)\" ) -ForegroundColor Red\n                    }\n                }\n                if ($bekannteListe.Count -gt 0) {\n                    Write-Host (\"`n  [{0}] PID {1} - bekannte Dritt-Software ({2} Module):\" -f $proc.Name, $proc.Id, $bekannteListe.Count) -ForegroundColor DarkGray\n                    $bekannteListe | ForEach-Object { Write-Host (\"    $($_.Modul) | $($_.Signierer)\") -ForegroundColor DarkGray }\n                }\n            } catch {\n                if ($geschuetzt -notcontains $pName) {\n                    Write-Host (\"  [{0}] PID {1} - Zugriff verweigert\" -f $pName, $proc.Id) -ForegroundColor DarkGray\n                }\n            }\n        }\n    }\n    if (-not $systemFund) {\n        Write-Host \"Alle geprueften Systemprozesse: nur Microsoft-signierte Module.\" -ForegroundColor Green\n    }\n\n    # --- 14b: AppInit_DLLs ---\n    Write-Host \"`n--- AppInit_DLLs (laedt in JEDEN Prozess mit user32.dll) ---\" -ForegroundColor DarkGray\n    $appInitKeys = @(\n        'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows',\n        'HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows'\n    )\n    foreach ($k in $appInitKeys) {\n        if (Test-Path $k) {\n            $val = (Get-ItemProperty $k -ErrorAction SilentlyContinue).AppInit_DLLs\n            $load = (Get-ItemProperty $k -ErrorAction SilentlyContinue).LoadAppInit_DLLs\n            if ($val -and $val.Trim()) {\n                Write-Host \"  [!!!] AppInit_DLLs GESETZT: $val\" -ForegroundColor Red\n                Write-Host \"        LoadAppInit_DLLs: $load\" -ForegroundColor Red\n            } else {\n                Write-Host \"  $k : Leer (gut).\" -ForegroundColor Green\n            }\n        }\n    }\n\n    # --- 14c: Winlogon Injection (Shell, Userinit, Notify) ---\n    Write-Host \"`n--- Winlogon Injection-Vektoren ---\" -ForegroundColor DarkGray\n    $wlKey = 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon'\n    if (Test-Path $wlKey) {\n        $wl = Get-ItemProperty $wlKey -ErrorAction SilentlyContinue\n        # Shell sollte nur explorer.exe sein\n        if ($wl.Shell -and $wl.Shell -notmatch '^explorer\\.exe$') {\n            Write-Host \"  [!] Shell != explorer.exe: $($wl.Shell)\" -ForegroundColor Red\n        } else { Write-Host \"  Shell     : $($wl.Shell) (OK)\" -ForegroundColor Green }\n        # Userinit\n        if ($wl.Userinit -and $wl.Userinit -notmatch 'userinit\\.exe') {\n            Write-Host \"  [!] Userinit auffaellig: $($wl.Userinit)\" -ForegroundColor Red\n        } else { Write-Host \"  Userinit  : $($wl.Userinit) (OK)\" -ForegroundColor Green }\n    }\n\n    # --- 14d: LSA Security Packages ---\n    Write-Host \"`n--- LSA Authentication &amp; Security Packages ---\" -ForegroundColor DarkGray\n    $lsaKey = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa'\n    if (Test-Path $lsaKey) {\n        $lsa = Get-ItemProperty $lsaKey -ErrorAction SilentlyContinue\n        $authPkg = $lsa.'Authentication Packages'\n        $secPkg  = $lsa.'Security Packages'\n        $notifPkg= $lsa.'Notification Packages'\n        $standard = @('msv1_0','','scecli')\n        foreach ($pkg in $authPkg) {\n            if ($pkg -and $standard -notcontains $pkg.ToLower()) {\n                Write-Host \"  [!] Unbekanntes Auth-Package: $pkg\" -ForegroundColor Red\n            }\n        }\n        Write-Host \"  Auth-Packages  : $($authPkg -join ', ')\"\n        Write-Host \"  Sec-Packages   : $($secPkg -join ', ')\"\n        Write-Host \"  Notify-Packages: $($notifPkg -join ', ')\"\n    }\n\n    # --- 14e: Dienste mit DLL in ungewoehnlichem Pfad ---\n    Write-Host \"`n--- Dienst-DLLs ausserhalb von System32/SysWOW64 ---\" -ForegroundColor DarkGray\n    $dienste = Get-ItemProperty 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\*' -ErrorAction SilentlyContinue |\n        Where-Object { $_.ImagePath -like '*svchost*' }\n    $fremdDienst = $false\n    foreach ($svc in $dienste) {\n        $param = $svc.PSPath -replace 'Registry::',''\n        $paramKey = $param + '\\Parameters'\n        if (Test-Path \"Registry::$paramKey\") {\n            $dll = (Get-ItemProperty \"Registry::$paramKey\" -ErrorAction SilentlyContinue).ServiceDll\n            if ($dll -and $dll -notmatch '(?i)^(%SystemRoot%|C:\\\\Windows)\\\\(System32|SysWOW64)\\\\') {\n                Write-Host (\"  [!] Dienst '{0}' laedt DLL aus ungewoehnlichem Pfad:\" -f $svc.PSChildName) -ForegroundColor Red\n                Write-Host (\"      $dll\") -ForegroundColor Red\n                $sig = Get-AuthenticodeSignature ($dll -replace '%SystemRoot%',$env:SystemRoot) -ErrorAction SilentlyContinue\n                if ($sig) { Write-Host (\"      Sig: {0}\" -f $sig.Status) -ForegroundColor Red }\n                $fremdDienst = $true\n            }\n        }\n    }\n    if (-not $fremdDienst) { Write-Host \"  Alle Dienst-DLLs in erwarteten Systempfaden.\" -ForegroundColor Green }\n\n    Write-Host \"`nHinweis: lsass-Module sind ohne SeDebugPrivilege oft nicht lesbar.\" -ForegroundColor DarkGray\n    Write-Host \"Fuer Kernel-Level-Injection (DKOM, direkte Speichermanipulation):\" -ForegroundColor DarkGray\n    Write-Host \"PowerShell reicht nicht aus - da braucht es WinPmem oder Volatility.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  15 - HVCI / Memory Integrity &amp; Code Integrity Treiber-Check\n# ============================================================\nfunction Invoke-HVCICheck {\n    Write-Host \"`n=== HVCI / Memory Integrity &amp; Inkompatible Treiber ===\" -ForegroundColor Cyan\n    Write-Host \"(Deaktivierte Speicherintegritaet + geblockte Kernel-Treiber = DMA-Indiz)\" -ForegroundColor DarkGray\n\n    # --- 15a: HVCI-Status ---\n    Write-Host \"`n--- Memory Integrity (HVCI) Status ---\" -ForegroundColor DarkGray\n    $hvciKey = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\DeviceGuard\\Scenarios\\HypervisorEnforcedCodeIntegrity'\n    $vbsKey  = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\DeviceGuard'\n    $hvciAktiv = $false\n\n    if (Test-Path $hvciKey) {\n        $hvci = Get-ItemProperty $hvciKey -ErrorAction SilentlyContinue\n        $hvciAktiv = $hvci.Enabled -eq 1\n        $col = if ($hvciAktiv) { 'Green' } else { 'Red' }\n        Write-Host (\"  HVCI (Speicherintegritaet) : {0}\" -f $(if($hvciAktiv){'AKTIV'}else{'DEAKTIVIERT [!]'})) -ForegroundColor $col\n        if (-not $hvciAktiv) {\n            Write-Host \"  --&gt; Inkompatible Treiber koennen in den Kernel geladen werden.\" -ForegroundColor Yellow\n            Write-Host \"      DMA-Karten mit schwach signierten Treibern nutzen genau das.\" -ForegroundColor Yellow\n            Write-Host \"  Manuell pruefen: Windows-Sicherheit \u00e2\u2020\u2019 Geraetesicherheit \u00e2\u2020\u2019 Kernisolierung\" -ForegroundColor DarkGray\n        }\n    } else {\n        Write-Host \"  HVCI-Key nicht gefunden - VBS moeglicherweise nicht konfiguriert.\" -ForegroundColor Yellow\n    }\n\n    if (Test-Path $vbsKey) {\n        $vbs = Get-ItemProperty $vbsKey -ErrorAction SilentlyContinue\n        $vbsAktiv = $vbs.EnableVirtualizationBasedSecurity -eq 1\n        Write-Host (\"  VBS (Virt. Based Security)  : {0}\" -f $(if($vbsAktiv){'AKTIV'}else{'DEAKTIVIERT'})) -ForegroundColor $(if($vbsAktiv){'Green'}else{'Yellow'})\n    }\n\n    # Secure Boot\n    try {\n        $sb = Confirm-SecureBootUEFI -ErrorAction Stop\n        Write-Host (\"  Secure Boot                 : {0}\" -f $(if($sb){'AKTIV'}else{'DEAKTIVIERT [!]'})) -ForegroundColor $(if($sb){'Green'}else{'Red'})\n    } catch {\n        Write-Host \"  Secure Boot                 : Nicht abfragbar (Legacy BIOS oder kein UEFI)\" -ForegroundColor Yellow\n    }\n\n    # --- 15b: Code Integrity Log - geblockte Treiber ---\n    Write-Host \"`n--- Code Integrity: geblockte / abgelehnte Treiber ---\" -ForegroundColor DarkGray\n    Write-Host \"(Event 3033 = geblockt | 3034 = Boot-Treiber | 3076 = Audit | 3077 = Prozess)\" -ForegroundColor DarkGray\n\n    $ciEvents = @(Get-WinEvent -FilterHashtable @{\n        LogName = 'Microsoft-Windows-CodeIntegrity/Operational'\n        Id      = 3033, 3034, 3076, 3077\n    } -MaxEvents 100 -ErrorAction SilentlyContinue)\n\n    # Bekannte legitime Security-DLLs die bei HVCI haeufig 3033 ausloesen\n    $ciWhitelist = @('mbae64\\.dll','mbae\\.dll','mbamswissarmy','MBAMSwissArmy',\n                     'mbamsi64\\.dll','mbamsi\\.dll','mbamupdatetool',\n                     'hmpalert','hmpalert64','CrExigency','sophos','mbae')\n\n    if ($ciEvents.Count -gt 0) {\n        $ciGefiltert = @($ciEvents | Where-Object {\n            $msg = $_.Message\n            -not ($ciWhitelist | Where-Object { $msg -match $_ })\n        })\n        $ciGefiltert_kurz = @($ciEvents | Where-Object {\n            $msg = $_.Message\n            ($ciWhitelist | Where-Object { $msg -match $_ })\n        })\n\n        if ($ciGefiltert_kurz.Count -gt 0) {\n            Write-Host \"  (Herausgefiltert: $($ciGefiltert_kurz.Count)x bekannte Security-Software wie Malwarebytes Anti-Exploit)\" -ForegroundColor DarkGray\n        }\n\n        if ($ciGefiltert.Count -gt 0) {\n            Write-Host \"  $($ciGefiltert.Count) relevante Ereignisse:\" -ForegroundColor Red\n            $ciGefiltert | Sort-Object TimeCreated -Descending | Select-Object -First 20 | ForEach-Object {\n                $eid = $_.Id\n                $col = if ($eid -in @(3033,3034)) { 'Red' } else { 'Yellow' }\n                $msg = ($_.Message -replace '\\s+',' ')\n                $datei = if ($msg -match '\\\\([^\\\\]+\\.sys|[^\\\\]+\\.dll)') { $matches[1] } else { '' }\n                Write-Host (\"`n  [{0}] EID {1}\" -f $_.TimeCreated, $eid) -ForegroundColor $col\n                if ($datei) { Write-Host (\"  Treiber : {0}\" -f $datei) -ForegroundColor $col }\n                Write-Host (\"  Details : {0}...\" -f $msg.Substring(0, [Math]::Min(160, $msg.Length))) -ForegroundColor DarkGray\n            }\n        } else {\n            Write-Host \"  Keine unbekannten geblockten Treiber - nur bekannte Security-Software.\" -ForegroundColor Green\n        }\n    } else {\n        Write-Host \"  Keine geblockten Treiber im Code Integrity Log.\" -ForegroundColor Green\n        if ($hvciAktiv) {\n            Write-Host \"  (HVCI aktiv = Treiber werden gar nicht erst geladen - das ist gut)\" -ForegroundColor DarkGray\n        }\n    }\n\n    # --- 15c: bcdedit - Testsigning und Integritaets-Bypass ---\n    Write-Host \"`n--- Boot-Konfiguration: Testsigning &amp; Integrity-Checks ---\" -ForegroundColor DarkGray\n    $bcd = &amp; bcdedit /enum 2&gt;&amp;1 | Out-String\n    $testsigning = $bcd -match 'testsigning\\s+yes'\n    $nointegrity = $bcd -match 'nointegritychecks\\s+yes'\n    $dbgmode     = $bcd -match 'debug\\s+yes'\n\n    Write-Host (\"  Testsigning        : {0}\" -f $(if($testsigning){'[!!!] AKTIV - unsignierte Treiber erlaubt!'}else{'Deaktiviert (OK)'})) -ForegroundColor $(if($testsigning){'Red'}else{'Green'})\n    Write-Host (\"  NoIntegrityChecks  : {0}\" -f $(if($nointegrity){'[!!!] AKTIV - Integritaetspruefung umgangen!'}else{'Deaktiviert (OK)'})) -ForegroundColor $(if($nointegrity){'Red'}else{'Green'})\n    Write-Host (\"  Debug-Modus        : {0}\" -f $(if($dbgmode){'[!] Aktiv'}else{'Deaktiviert (OK)'})) -ForegroundColor $(if($dbgmode){'Yellow'}else{'Green'})\n\n    if ($testsigning -or $nointegrity) {\n        Write-Host \"`n  [!!!] Treibersignaturen sind aktiv umgangen.\" -ForegroundColor Red\n        Write-Host \"        Jeder beliebige unsignierte Kernel-Treiber kann geladen werden.\" -ForegroundColor Red\n        Write-Host \"        Das ist eine Grundvoraussetzung vieler DMA- und Cheat-Treiber.\" -ForegroundColor Red\n    }\n\n    # --- 15d: Inkompatible Treiber aus pnputil (ergaenzt HVCI-Liste) ---\n    Write-Host \"`n--- Installierte Treiber ohne gueltige WHQL-Signatur ---\" -ForegroundColor DarkGray\n    Write-Host \"(Diese wuerden die HVCI-Aktivierung verhindern)\" -ForegroundColor DarkGray\n    try {\n        $pnpOut = &amp; pnputil /enum-drivers 2&gt;&amp;1 | Out-String\n        $bloecke = $pnpOut -split '(?=Veroeffentlichter Name|Published Name)'\n        $verdaechtig = @($bloecke | Where-Object {\n            $_ -match 'Nicht signiert|Not Signed|Unsigned' -or\n            ($_ -match '(Signierer|Signer)\\s*:' -and $_ -notmatch '(?i)Microsoft|WHQL')\n        })\n        if ($verdaechtig.Count -gt 0) {\n            Write-Host \"  [!] $($verdaechtig.Count) potenziell inkompatible Treiber:\" -ForegroundColor Red\n            $verdaechtig | Select-Object -First 10 | ForEach-Object {\n                $name = if ($_ -match 'oem\\d+\\.inf') { $matches[0] } else { '' }\n                $pub  = if ($_ -match '(?:Herausgeber|Publisher)\\s*:\\s*(.+)') { $matches[1].Trim() } else { '' }\n                if ($name) { Write-Host (\"  {0} | {1}\" -f $name, $pub) -ForegroundColor Yellow }\n            }\n        } else {\n            Write-Host \"  Keine offensichtlich unsignierten Treiber gefunden.\" -ForegroundColor Green\n        }\n    } catch {\n        Write-Host \"  pnputil nicht verfuegbar.\" -ForegroundColor DarkGray\n    }\n\n    Write-Host \"`nFazit-Hilfe:\" -ForegroundColor DarkGray\n    Write-Host \"  Testsigning=Ja + unbekannter Treiber = starker DMA-Hinweis\" -ForegroundColor DarkGray\n    Write-Host \"  HVCI deaktiviert + CI-Events = Treiber wurde installiert und verweigert\" -ForegroundColor DarkGray\n    Write-Host \"  Gut konfigurierte DMA-Karten (echt signiert) erscheinen NICHT im CI-Log\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  16 - System32 Fremdkoerper &amp; Typosquatting-Check\n# ============================================================\nfunction Invoke-System32Check {\n    Write-Host \"`n=== System32 Fremdkoerper &amp; Typosquatting ===\" -ForegroundColor Cyan\n    Write-Host \"(Nicht-Microsoft DLLs + verdaechtige Namen + frische Dateien in System32)\" -ForegroundColor DarkGray\n\n    $sys32 = \"$env:SystemRoot\\System32\"\n    $osInstall = (Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue).InstallDate\n\n    # Bekannte kritische DLL-Namen fuer Typosquatting-Pruefung\n    # Angreifer ersetzen gerne l\u00e2\u2020\u20191, o\u00e2\u2020\u20190, I\u00e2\u2020\u2019l usw.\n    $kritischeDLLs = @(\n        'ntdll','kernel32','kernelbase','user32','advapi32','rpcrt4',\n        'msvcrt','sechost','combase','ucrtbase','win32u','gdi32',\n        'ole32','oleaut32','shell32','shlwapi','wininet','ws2_32',\n        'crypt32','bcrypt','ncrypt','lsasrv','wintrust','wldp'\n    )\n\n    # Bekannte Phantom-DLLs die NIE in System32 gehoeren\n    $system32Phantom = @(\n        'WptsExtensions.dll','WaasMedicSvc.dll','wlbsctrl.dll',\n        'cryptbase2.dll','version2.dll','cryptsp2.dll'\n    )\n\n    Write-Host \"`n--- Nicht-Microsoft DLLs in System32 ---\" -ForegroundColor DarkGray\n    Write-Host \"Scanne... (kann 30-60 Sekunden dauern)\" -ForegroundColor DarkGray\n\n    $fremd   = @()\n    $phantom = @()\n    $frisch  = @()\n    $typo    = @()\n\n    $dlls = @(Get-ChildItem $sys32 -Filter '*.dll' -ErrorAction SilentlyContinue)\n    $total = $dlls.Count\n    $i = 0\n\n    foreach ($f in $dlls) {\n        $i++\n        if ($i % 200 -eq 0) { Write-Host \"  ... $i / $total gepr\u00c3\u00bcft\" -ForegroundColor DarkGray }\n\n        # Phantom-DLL Direkttreffer\n        if ($system32Phantom -contains $f.Name) {\n            $phantom += $f\n            continue\n        }\n\n        # Signaturpruefung - bei gueltigem MS-Zertifikat sofort weiter\n        $sig = Get-AuthenticodeSignature $f.FullName -ErrorAction SilentlyContinue\n        $istMS = $sig -and $sig.Status -eq 'Valid' -and\n                 $sig.SignerCertificate -and\n                 $sig.SignerCertificate.Subject -match '(?i)Microsoft'\n        if ($istMS) { continue }\n\n        $status   = if ($sig) { $sig.Status } else { 'Unbekannt' }\n        $signierer = if ($sig -and $sig.SignerCertificate) {\n            $sig.SignerCertificate.Subject -replace '^CN=([^,]+).*','$1'\n        } else { 'Nicht signiert' }\n\n        $fremd += [PSCustomObject]@{\n            Name      = $f.Name\n            Sig       = $status\n            Signierer = $signierer\n            Erstellt  = $f.CreationTime\n            Groesse   = $f.Length\n        }\n\n        # Frisch nach Windows-Installation erstellt?\n        if ($osInstall -and $f.CreationTime -gt $osInstall.AddDays(30)) {\n            $frisch += $f.Name\n        }\n\n        # Typosquatting-Pruefung\n        $nameBasis = [System.IO.Path]::GetFileNameWithoutExtension($f.Name).ToLower()\n        foreach ($legit in $kritischeDLLs) {\n            if ($nameBasis -ne $legit) {\n                # Levenshtein-Distanz 1 = ein Zeichen anders\n                $dist = 0\n                $a = $nameBasis.ToCharArray()\n                $b = $legit.ToCharArray()\n                if ([Math]::Abs($a.Length - $b.Length) -le 1) {\n                    $diff = 0\n                    $minLen = [Math]::Min($a.Length, $b.Length)\n                    for ($x = 0; $x -lt $minLen; $x++) {\n                        if ($a[$x] -ne $b[$x]) { $diff++ }\n                    }\n                    $diff += [Math]::Abs($a.Length - $b.Length)\n                    if ($diff -le 1) {\n                        $typo += [PSCustomObject]@{ Datei=$f.Name; AehnlichWie=\"$legit.dll\" }\n                    }\n                }\n            }\n        }\n    }\n\n    # --- Ausgabe Phantom ---\n    if ($phantom.Count -gt 0) {\n        Write-Host \"`n  [!!!] PHANTOM-DLLs in System32 (gehoeren NICHT hierher):\" -ForegroundColor Red\n        $phantom | ForEach-Object {\n            $sig2 = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue\n            Write-Host (\"  {0} | Sig: {1} | Erstellt: {2}\" -f $_.Name, $(if($sig2){$sig2.Status}else{'Unbekannt'}), $_.CreationTime) -ForegroundColor Red\n        }\n    }\n\n    # --- Ausgabe Fremd ---\n    if ($fremd.Count -gt 0) {\n        Write-Host (\"`n  {0} nicht-Microsoft DLLs in System32:\" -f $fremd.Count) -ForegroundColor Red\n        $fremd | Sort-Object Erstellt -Descending | ForEach-Object {\n            $col = if ($_.Sig -ne 'Valid') { 'Red' } else { 'Yellow' }\n            Write-Host (\"  [!] {0,-35} Sig: {1,-12} Erstellt: {2}\" -f $_.Name, $_.Sig, $_.Erstellt) -ForegroundColor $col\n            if ($_.Signierer -ne 'Nicht signiert') {\n                Write-Host (\"      Signierer: {0}\" -f $_.Signierer) -ForegroundColor DarkGray\n            }\n        }\n    } else {\n        Write-Host \"`n  Alle DLLs in System32 sind Microsoft-signiert.\" -ForegroundColor Green\n    }\n\n    # --- Ausgabe Frisch ---\n    if ($frisch.Count -gt 0) {\n        Write-Host (\"`n  [!] {0} DLLs nach Windows-Installation erstellt/geaendert:\" -f $frisch.Count) -ForegroundColor Yellow\n        $frisch | ForEach-Object { Write-Host \"  $_\" -ForegroundColor Yellow }\n    }\n\n    # --- Ausgabe Typosquatting ---\n    if ($typo.Count -gt 0) {\n        Write-Host \"`n  [!!!] Moegliches Typosquatting:\" -ForegroundColor Red\n        $typo | ForEach-Object {\n            Write-Host (\"  {0} sieht aus wie {1}\" -f $_.Datei, $_.AehnlichWie) -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"`n  Kein Typosquatting bekannter System-DLLs gefunden.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`nHinweis: Nicht-MS-signierte DLLs koennen legitim sein (z.B. AV-Software).\" -ForegroundColor DarkGray\n    Write-Host \"Rot + frisches Erstelldatum + unbekannter Signierer = hoechste Prioritaet.\" -ForegroundColor DarkGray\n    Write-Host \"Typosquatting-Treffer immer manuell pruefen.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  17 - DMA Fuser &amp; Zweiter-PC-Verbindungen\n# ============================================================\nfunction Invoke-FuserCheck {\n    Write-Host \"`n=== DMA Fuser &amp; Zweiter-PC-Verbindungen ===\" -ForegroundColor Cyan\n    Write-Host \"(Netzwerkverbindungen, windowlose Prozesse, Named Pipes, bekannte Fuser)\" -ForegroundColor DarkGray\n\n    # --- 17a: Bekannte Fuser-Prozessnamen ---\n    Write-Host \"`n--- Bekannte DMA-Fuser Prozesse ---\" -ForegroundColor DarkGray\n    $fuserNamen = @(\n        'pcileech','memflow','memprocfs','dmaclient','dmaservice',\n        'easymapi','leechcore','leechagent','fpga','dma_client',\n        'scatterclient','scatter','vmmdll','vmmsharp',\n        'winpmem','rekall','volatility','dumpit'\n    )\n    $fuserGefunden = $false\n    foreach ($n in $fuserNamen) {\n        $p = @(Get-Process -Name $n -ErrorAction SilentlyContinue)\n        if ($p.Count -gt 0) {\n            $p | ForEach-Object {\n                Write-Host (\"  [!!!] {0} (PID {1}) - {2}\" -f $_.Name, $_.Id, $_.Path) -ForegroundColor Red\n            }\n            $fuserGefunden = $true\n        }\n    }\n    if (-not $fuserGefunden) {\n        Write-Host \"  Keine bekannten Fuser-Prozesse gefunden.\" -ForegroundColor Green\n    }\n\n    # --- 17b: Netzwerkverbindungen zu lokalen IPs (PC2-Verbindung) ---\n    Write-Host \"`n--- Netzwerkverbindungen zu lokalen IPs (DMA PC2) ---\" -ForegroundColor DarkGray\n    Write-Host \"(192.168.x.x / 10.x.x.x / 172.16-31.x.x auf ungewoehnlichen Ports)\" -ForegroundColor DarkGray\n\n    $bekanntePortsOK = @(80,443,8080,8443,3389,5985,5986,53,67,68,123,137,138,139,445,1900,5353)\n    $lokaleVerbindungen = @()\n\n    Get-NetTCPConnection -State Established -ErrorAction SilentlyContinue | ForEach-Object {\n        $remIP = $_.RemoteAddress\n        $remPort = $_.RemotePort\n        $istLokal = $remIP -match '^192\\.168\\.|^10\\.|^172\\.(1[6-9]|2[0-9]|3[01])\\.'\n        $portUngewoehnlich = $bekanntePortsOK -notcontains $remPort\n\n        if ($istLokal -and $portUngewoehnlich) {\n            $proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue\n            $lokaleVerbindungen += [PSCustomObject]@{\n                Prozess  = if ($proc) { $proc.Name } else { 'Unbekannt' }\n                PID      = $_.OwningProcess\n                LokPort  = $_.LocalPort\n                RemoteIP = $remIP\n                RemPort  = $remPort\n                Pfad     = if ($proc) { $proc.Path } else { '-' }\n            }\n        }\n    }\n\n    if ($lokaleVerbindungen.Count -gt 0) {\n        Write-Host \"  [!] $($lokaleVerbindungen.Count) Verbindungen zu lokalen IPs auf ungewoehnlichen Ports:\" -ForegroundColor Red\n        $lokaleVerbindungen | Sort-Object RemoteIP | ForEach-Object {\n            Write-Host (\"`n  [{0}] PID {1}\" -f $_.Prozess, $_.PID) -ForegroundColor Red\n            Write-Host (\"  Remote: {0}:{1}  (lokal Port {2})\" -f $_.RemoteIP, $_.RemPort, $_.LokPort) -ForegroundColor Red\n            Write-Host (\"  Pfad  : {0}\" -f $_.Pfad) -ForegroundColor DarkGray\n        }\n    } else {\n        Write-Host \"  Keine auffaelligen lokalen Netzwerkverbindungen.\" -ForegroundColor Green\n    }\n\n    # --- 17c: Windowlose Prozesse ohne bekanntes Elternteil ---\n    Write-Host \"`n--- Windowlose Hintergrundprozesse (moegliche versteckte Fuser) ---\" -ForegroundColor DarkGray\n    $systemProz = @('svchost','services','lsass','csrss','wininit','smss','System',\n                    'Registry','fontdrvhost','dwm','WmiPrvSE','spoolsv','SearchIndexer',\n                    'RuntimeBroker','ShellExperienceHost','StartMenuExperienceHost',\n                    'sihost','taskhostw','ctfmon','conhost','dllhost','audiodg',\n                    'MsMpEng','NisSrv','SecurityHealthService','TextInputHost')\n\n    $verdaechtigeProz = @()\n    Add-Type @\"\nusing System;\nusing System.Runtime.InteropServices;\npublic class WinAPI {\n    [DllImport(\"user32.dll\")]\n    public static extern bool IsWindowVisible(IntPtr hWnd);\n    [DllImport(\"user32.dll\")]\n    public static extern IntPtr GetForegroundWindow();\n}\n\"@ -ErrorAction SilentlyContinue\n\n    Get-Process -ErrorAction SilentlyContinue | Where-Object {\n        $_.Name -notin $systemProz -and\n        $_.MainWindowHandle -eq [IntPtr]::Zero -and\n        $_.SessionId -eq (Get-Process -PID $PID).SessionId\n    } | ForEach-Object {\n        $p = $_\n        # Nur Prozesse mit Pfad und ohne Fenster die nicht bekannte Apps sind\n        if ($p.Path -and $p.Path -notmatch '(?i)\\\\Windows\\\\|\\\\Program Files\\\\|\\\\Program Files \\(x86\\)\\\\') {\n            $sig = Get-AuthenticodeSignature $p.Path -ErrorAction SilentlyContinue\n            $istMS = $sig -and $sig.Status -eq 'Valid' -and $sig.SignerCertificate -and $sig.SignerCertificate.Subject -match '(?i)Microsoft'\n            if (-not $istMS) {\n                $verdaechtigeProz += [PSCustomObject]@{\n                    Name     = $p.Name\n                    PID      = $p.Id\n                    Pfad     = $p.Path\n                    Sig      = if ($sig) { $sig.Status } else { 'Unbekannt' }\n                    Signierer= if ($sig -and $sig.SignerCertificate) { $sig.SignerCertificate.Subject -replace '^CN=([^,]+).*','$1' } else { '-' }\n                }\n            }\n        }\n    }\n\n    if ($verdaechtigeProz.Count -gt 0) {\n        Write-Host \"  $($verdaechtigeProz.Count) windowlose, nicht-MS-signierte Prozesse ausserhalb Systemordner:\" -ForegroundColor Yellow\n        $verdaechtigeProz | ForEach-Object {\n            $col = if ($_.Sig -ne 'Valid') { 'Red' } else { 'Yellow' }\n            Write-Host (\"`n  [{0}] PID {1}\" -f $_.Name, $_.PID) -ForegroundColor $col\n            Write-Host (\"  Pfad : {0}\" -f $_.Pfad) -ForegroundColor $col\n            Write-Host (\"  Sig  : {0} | {1}\" -f $_.Sig, $_.Signierer) -ForegroundColor DarkGray\n        }\n    } else {\n        Write-Host \"  Keine auffaelligen windowlosen Prozesse.\" -ForegroundColor Green\n    }\n\n    # --- 17d: Named Pipes mit DMA-typischen Namen ---\n    Write-Host \"`n--- Named Pipes (DMA/Fuser-Kommunikation) ---\" -ForegroundColor DarkGray\n    $dmaPipeMuster = 'dma|fuser|pcileech|memflow|leech|scatter|fpga|cheat|inject|overlay|radar'\n    try {\n        $pipes = @([System.IO.Directory]::GetFiles('\\\\.\\pipe\\') 2&gt;$null)\n        $verdPipes = @($pipes | Where-Object { $_ -match $dmaPipeMuster })\n        if ($verdPipes.Count -gt 0) {\n            Write-Host \"  [!] Verdaechtige Named Pipes:\" -ForegroundColor Red\n            $verdPipes | ForEach-Object { Write-Host \"  $_\" -ForegroundColor Red }\n        } else {\n            Write-Host \"  Keine DMA-typischen Named Pipes.\" -ForegroundColor Green\n        }\n        Write-Host \"  (Alle Pipes: $($pipes.Count) vorhanden)\" -ForegroundColor DarkGray\n    } catch {\n        # Alternativer Weg ueber Sysinternals wenn verfuegbar\n        Write-Host \"  Direkter Pipe-Zugriff nicht moeglich. Alternativ:\" -ForegroundColor DarkGray\n        Write-Host \"  handle.exe -a | findstr '\\pipe' (Sysinternals)\" -ForegroundColor DarkGray\n    }\n\n    # --- 17e: Autostart-Eintraege fuer Fuser ---\n    Write-Host \"`n--- Autostart-Eintraege (Fuser beim Boot) ---\" -ForegroundColor DarkGray\n    $autoKeys = @(\n        'HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run',\n        'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run',\n        'HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce',\n        'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce'\n    )\n    foreach ($k in $autoKeys) {\n        if (-not (Test-Path $k)) { continue }\n        $vals = Get-ItemProperty $k -ErrorAction SilentlyContinue\n        $vals.PSObject.Properties | Where-Object { $_.Name -notmatch '^PS' } | ForEach-Object {\n            $pfad = $_.Value -replace '\"','' -replace ' .*$',''\n            if (Test-Path $pfad -ErrorAction SilentlyContinue) {\n                $sig = Get-AuthenticodeSignature $pfad -ErrorAction SilentlyContinue\n                $istMS = $sig -and $sig.Status -eq 'Valid' -and $sig.SignerCertificate -and $sig.SignerCertificate.Subject -match '(?i)Microsoft'\n                if (-not $istMS) {\n                    $col = if ($sig -and $sig.Status -ne 'Valid') { 'Red' } else { 'Yellow' }\n                    Write-Host (\"  [!] {0} = {1}\" -f $_.Name, $_.Value) -ForegroundColor $col\n                    Write-Host (\"      Sig: {0}\" -f $(if($sig){$sig.Status}else{'Unbekannt'})) -ForegroundColor $col\n                }\n            }\n        }\n    }\n    Write-Host \"  Autostart-Check abgeschlossen.\" -ForegroundColor DarkGray\n\n    Write-Host \"`nFuser-Erkennungs-Tipp:\" -ForegroundColor DarkGray\n    Write-Host \"  Netzwerkverbindung zu 192.168.x.x auf Port &gt;10000 + windowloser Prozess = starkes Indiz.\" -ForegroundColor DarkGray\n    Write-Host \"  Fuser laufen oft nur waehrend des Spiels - deshalb Pruefung waehrend aktiver Session.\" -ForegroundColor DarkGray\n\n    # --- 17f: Display-Analyse (HDMI-Splitter / Capture-Setup) ---\n    Write-Host \"`n--- Display-Analyse (HDMI-Splitter / gespiegeltes Bild) ---\" -ForegroundColor DarkGray\n    Write-Host \"(Mehr Displays als Monitore sichtbar = moeglicher Splitter oder Capture-Input)\" -ForegroundColor DarkGray\n\n    try {\n        $monitors = @(Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorID -ErrorAction SilentlyContinue)\n        Write-Host (\"  Erkannte Displays: {0}\" -f $monitors.Count)\n        foreach ($m in $monitors) {\n            $hersteller = try { [System.Text.Encoding]::ASCII.GetString(($m.ManufacturerName | Where-Object {$_ -ne 0})) } catch { '?' }\n            $modell     = try { [System.Text.Encoding]::ASCII.GetString(($m.UserFriendlyName  | Where-Object {$_ -ne 0})) } catch { '?' }\n            $serial     = try { [System.Text.Encoding]::ASCII.GetString(($m.SerialNumberID    | Where-Object {$_ -ne 0})) } catch { '' }\n            $col = 'White'\n            $hinweis = ''\n            # Typische Capture-Card oder Virtual-Display Hersteller\n            if ($hersteller -match '(?i)AVerMedia|Elgato|Magewell|Blackmagic|Datapath|DisplayLink|ITE|GENERIC|VirtualDisplay|Parsec|NoMachine') {\n                $col = 'Red'\n                $hinweis = ' [!] CAPTURE/VIRTUAL DISPLAY'\n            }\n            Write-Host (\"  {0,-8} {1,-25} Serial: {2}{3}\" -f $hersteller.Trim(), $modell.Trim(), $serial.Trim(), $hinweis) -ForegroundColor $col\n        }\n\n        if ($monitors.Count -gt 2) {\n            Write-Host (\"  [!] {0} Displays erkannt - mehr als 2 ist ungewoehnlich fuer einen Gaming-PC.\" -f $monitors.Count) -ForegroundColor Yellow\n            Write-Host \"      Moeglicher HDMI-Splitter oder Capture-Eingang aktiv.\" -ForegroundColor Yellow\n        }\n    } catch {\n        Write-Host \"  Display-Abfrage fehlgeschlagen.\" -ForegroundColor DarkGray\n    }\n\n    # --- 17g: Capture-Cards und Video-Devices auf PC1 ---\n    Write-Host \"`n--- Capture-Cards &amp; Video-Geraete auf diesem PC ---\" -ForegroundColor DarkGray\n    $captureGeraete = @(Get-PnpDevice -ErrorAction SilentlyContinue | Where-Object {\n        $_.Class -match '(?i)Media|Image|Camera' -and $_.Status -eq 'OK'\n    })\n    if ($captureGeraete.Count -gt 0) {\n        foreach ($g in $captureGeraete) {\n            $istVerd = $g.FriendlyName -match '(?i)capture|hdmi|video|grabber|avermedia|elgato|magewell|blackmagic|hauppauge'\n            $col = if ($istVerd) { 'Yellow' } else { 'DarkGray' }\n            Write-Host (\"  [{0}] {1}\" -f $g.Class, $g.FriendlyName) -ForegroundColor $col\n            if ($istVerd) {\n                Write-Host (\"  --&gt; Capture-Device: {0}\" -f $g.InstanceId) -ForegroundColor Yellow\n                Write-Host \"      Pruefe ob das Geraet fuer Cheat-Capture oder legitimes Streaming genutzt wird.\" -ForegroundColor DarkGray\n            }\n        }\n    } else {\n        Write-Host \"  Keine Video/Capture-Geraete gefunden.\" -ForegroundColor Green\n    }\n\n    # --- 17h: Aktive GPU-Ausgaenge (mehr als physische Monitore) ---\n    Write-Host \"`n--- GPU: aktive Video-Ausgaenge ---\" -ForegroundColor DarkGray\n    Get-CimInstance Win32_VideoController -ErrorAction SilentlyContinue | ForEach-Object {\n        Write-Host (\"  GPU       : {0}\" -f $_.Name)\n        Write-Host (\"  Adapter   : {0}\" -f $_.AdapterCompatibility)\n        Write-Host (\"  Aufloesung: {0}x{1}\" -f $_.CurrentHorizontalResolution, $_.CurrentVerticalResolution)\n    }\n\n    Write-Host \"`nHDMI-Splitter-Tipp:\" -ForegroundColor DarkGray\n    Write-Host \"  Physische Pruefung: 2 HDMI-Kabel am Monitor (Input 1 + Input 2) ist verdaechtig.\" -ForegroundColor DarkGray\n    Write-Host \"  Ein zweiter laufender PC ohne sichtbare Aktivitaet = moeglicher Cheat-PC.\" -ForegroundColor DarkGray\n    Write-Host \"  Netzwerk (Punkt 17b) findet die DMA-Verbindung zwischen PC1 und PC2.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  18 - Forensische Tools herunterladen\n# ============================================================\nfunction Invoke-ToolDownload {\n    Write-Host \"`n=== Forensische Tools - Download ===\" -ForegroundColor Cyan\n    Write-Host \"(Alle Tools sind kostenlos und Open Source / Freeware)\" -ForegroundColor DarkGray\n\n    $zielOrdner = \"$env:USERPROFILE\\Desktop\\CTC_Tools\"\n    if (-not (Test-Path $zielOrdner)) {\n        New-Item -ItemType Directory -Path $zielOrdner | Out-Null\n        Write-Host \"Ordner erstellt: $zielOrdner\" -ForegroundColor Green\n    } else {\n        Write-Host \"Zielordner: $zielOrdner\" -ForegroundColor DarkGray\n    }\n\n    $tools = [ordered]@{\n        '1' = @{\n            Name   = 'Everything 1.4 (Blitzschnelle Dateisuche)'\n            URL    = 'https://www.voidtools.com/Everything-1.4.1.1024.x64.zip'\n            Zip    = $true\n            Tipp   = 'Findet DLLs, .sys-Dateien und Cheat-Dateien sofort'\n        }\n        '2' = @{\n            Name   = 'System Informer (Prozesse, Handles, Netzwerk)'\n            URL    = 'github_latest'\n            Repo   = 'winsiderss/systeminformer'\n            Zip    = $true\n            Tipp   = 'Zeigt geladene DLLs, Named Pipes und versteckte Prozesse'\n        }\n        '3' = @{\n            Name   = 'Autoruns (Alle Autostart-Eintraege)'\n            URL    = 'https://download.sysinternals.com/files/Autoruns.zip'\n            Zip    = $true\n            Tipp   = 'Zeigt JEDEN Autostart-Eintrag - Fuser-Erkennung'\n        }\n        '4' = @{\n            Name   = 'Process Monitor (Live Datei/Registry/Netzwerk)'\n            URL    = 'https://download.sysinternals.com/files/ProcessMonitor.zip'\n            Zip    = $true\n            Tipp   = 'Zeigt phantom DLL-Suchen in Echtzeit (DLL Hijacking live)'\n        }\n        '5' = @{\n            Name   = 'TCPView (Netzwerkverbindungen live)'\n            URL    = 'https://download.sysinternals.com/files/TCPView.zip'\n            Zip    = $true\n            Tipp   = 'Fuser-Verbindungen zu PC2 in Echtzeit sehen'\n        }\n        '6' = @{\n            Name   = 'Handle (Named Pipes &amp; Handles)'\n            URL    = 'https://download.sysinternals.com/files/Handle.zip'\n            Zip    = $true\n            Tipp   = 'Zeigt alle Named Pipes - DMA Fuser Kommunikation'\n        }\n        '7' = @{\n            Name   = 'Strings (Strings aus Binaerdateien extrahieren)'\n            URL    = 'https://download.sysinternals.com/files/Strings.zip'\n            Zip    = $true\n            Tipp   = 'Wie im WptsExtensions.dll Fund - inject/manualmap Strings sehen'\n        }\n        '8' = @{\n            Name   = 'Hollows Hunter (Injizierte Module finden)'\n            URL    = 'github_latest'\n            Repo   = 'hasherezade/hollows_hunter'\n            Zip    = $false\n            Tipp   = 'Findet reflective injection und manual mapped Code in Prozessen'\n        }\n        'A' = @{ Name = 'Alle Tools herunterladen'; URL = ''; Zip = $false; Tipp = '' }\n    }\n\n    Write-Host \"`n  Verfuegbare Tools:\" -ForegroundColor Cyan\n    foreach ($k in $tools.Keys) {\n        if ($k -eq 'A') {\n            Write-Host \"`n  [A] Alle herunterladen\" -ForegroundColor Yellow\n        } else {\n            $t = $tools[$k]\n            Write-Host (\"  [{0}] {1}\" -f $k, $t.Name) -ForegroundColor White\n            Write-Host (\"      --&gt; {0}\" -f $t.Tipp) -ForegroundColor DarkGray\n        }\n    }\n    Write-Host \"  [Q] Abbrechen\" -ForegroundColor DarkGray\n\n    $wahl = (Read-Host \"`nAuswahl\").Trim().ToUpper()\n    if ($wahl -eq 'Q') { return }\n\n    $zuLaden = if ($wahl -eq 'A') { $tools.Keys | Where-Object { $_ -ne 'A' } } else { @($wahl) }\n\n    foreach ($k in $zuLaden) {\n        if (-not $tools.ContainsKey($k)) { Write-Host \"Unbekannte Auswahl: $k\" -ForegroundColor Red; continue }\n        $tool = $tools[$k]\n        Write-Host (\"`n[{0}] Lade {1}...\" -f $k, $tool.Name) -ForegroundColor Cyan\n\n        $url = $tool.URL\n\n        # GitHub Latest Release URL holen\n        if ($url -eq 'github_latest') {\n            try {\n                Write-Host \"  GitHub Release API abfragen...\" -ForegroundColor DarkGray\n                $apiUrl = \"https://api.github.com/repos/$($tool.Repo)/releases/latest\"\n                $release = Invoke-RestMethod $apiUrl -Headers @{'User-Agent'='CTC-by-Dark'} -ErrorAction Stop\n                # Passende Asset-URL finden (x64, Windows)\n                $asset = $release.assets | Where-Object {\n                    $_.name -match '(?i)x64|amd64|win64' -and\n                    $_.name -match '(?i)\\.zip$|\\.exe$' -and\n                    $_.name -notmatch '(?i)debug|pdb|symbols'\n                } | Select-Object -First 1\n\n                if ($asset) {\n                    $url = $asset.browser_download_url\n                    Write-Host (\"  Version: {0} | Asset: {1}\" -f $release.tag_name, $asset.name) -ForegroundColor DarkGray\n                } else {\n                    Write-Host \"  Kein passendes Asset gefunden. Bitte manuell herunterladen:\" -ForegroundColor Yellow\n                    Write-Host (\"  https://github.com/{0}/releases\" -f $tool.Repo) -ForegroundColor Yellow\n                    continue\n                }\n            } catch {\n                Write-Host (\"  GitHub-Abfrage fehlgeschlagen: {0}\" -f $_) -ForegroundColor Red\n                Write-Host (\"  Manuell: https://github.com/{0}/releases\" -f $tool.Repo) -ForegroundColor Yellow\n                continue\n            }\n        }\n\n        # Dateiname aus URL\n        $dateiName = [System.IO.Path]::GetFileName($url)\n        $zielPfad  = Join-Path $zielOrdner $dateiName\n\n        try {\n            Write-Host (\"  Download: {0}\" -f $url) -ForegroundColor DarkGray\n            Invoke-WebRequest -Uri $url -OutFile $zielPfad -UseBasicParsing -ErrorAction Stop\n            Write-Host (\"  Gespeichert: {0}\" -f $zielPfad) -ForegroundColor Green\n\n            # ZIP entpacken\n            if ($tool.Zip -and $dateiName -match '\\.zip$') {\n                $extraktOrdner = Join-Path $zielOrdner ([System.IO.Path]::GetFileNameWithoutExtension($dateiName))\n                if (-not (Test-Path $extraktOrdner)) { New-Item -ItemType Directory -Path $extraktOrdner | Out-Null }\n                Expand-Archive -Path $zielPfad -DestinationPath $extraktOrdner -Force\n                Remove-Item $zielPfad -Force\n                Write-Host (\"  Entpackt: {0}\" -f $extraktOrdner) -ForegroundColor Green\n            }\n        } catch {\n            Write-Host (\"  Fehler: {0}\" -f $_) -ForegroundColor Red\n            Write-Host (\"  Manuell herunterladen: {0}\" -f $url) -ForegroundColor Yellow\n        }\n    }\n\n    Write-Host \"`n======================================\" -ForegroundColor Cyan\n    Write-Host \"  Tools gespeichert in:\" -ForegroundColor Cyan\n    Write-Host \"  $zielOrdner\" -ForegroundColor Yellow\n    Write-Host \"======================================\" -ForegroundColor Cyan\n    Write-Host \"Empfohlene Reihenfolge fuer eine Analyse:\" -ForegroundColor DarkGray\n    Write-Host \"  1. Autoruns    - Was startet beim Boot?\" -ForegroundColor DarkGray\n    Write-Host \"  2. TCPView     - Welche Verbindungen laufen?\" -ForegroundColor DarkGray\n    Write-Host \"  3. ProcMon     - Welche DLLs werden gesucht?\" -ForegroundColor DarkGray\n    Write-Host \"  4. SysInformer - Was ist in den Prozessen geladen?\" -ForegroundColor DarkGray\n    Write-Host \"  5. Everything  - Verdaechtige Dateien suchen\" -ForegroundColor DarkGray\n    Write-Host \"  6. HollowsHunter - Injizierte Module aufdecken\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  Menue\n# ============================================================\nfunction Show-Menu {\n    Write-Host \"\"\n    Write-Host \"============================================\" -ForegroundColor Cyan\n    Write-Host \"  CTC by Dark - CatchTheCheat               \" -ForegroundColor Cyan\n    Write-Host \"============================================\" -ForegroundColor Cyan\n    Write-Host \"  1  PnP-Ereignisse (411 / 400 / 410 / 420)\"\n    Write-Host \"  2  Log-Integritaet, System, Ausfuehrungsartefakte\"\n    Write-Host \"  3  PCI/PCIe-Geraete\"\n    Write-Host \"  4  Entfernte Geraete (Zeitfenster)\"\n    Write-Host \"  5  Datentraeger-Historie\"\n    Write-Host \"  6  USB-Geraetehistorie\"\n    Write-Host \"  7  Fernwartungssoftware (installiert / ausgefuehrt)\"\n    Write-Host \"  8  Fernwartung: Sitzungen und Dateiuebertragungen\"\n    Write-Host \"  9  Unsignierte Dateien (Treiber / Prozesse)\"\n    Write-Host \" 10  PowerShell-History und -Protokoll\"\n    Write-Host \" 11  Discord-Account-IDs (nur ID, keine Token)\"\n    Write-Host \" 12  PE Binary &amp; Driver Heuristics Inspector\"\n    Write-Host \" 13  DLL Hijacking Live-Check (laufende Prozesse)\"\n    Write-Host \" 14  Systemprozesse &amp; Registry-Injection-Vektoren\"\n    Write-Host \" 15  HVCI / Memory Integrity &amp; Inkompatible Treiber\"\n    Write-Host \" 16  System32 Fremdkoerper &amp; Typosquatting\"\n    Write-Host \" 17  DMA Fuser &amp; Zweiter-PC-Verbindungen\"\n    Write-Host \" 18  Forensische Tools herunterladen\"\n    Write-Host \"\"\n    Write-Host \"  A  Alles nacheinander\"\n    Write-Host \"  P  Protokoll auf Desktop starten/stoppen\"\n    Write-Host \"  Q  Beenden\"\n    Write-Host \"============================================\" -ForegroundColor Cyan\n}\n\n# ------------------------------------------------------------\nif (-not (Test-Admin)) {\n    Write-Host \"WARNUNG: Nicht als Administrator gestartet.\" -ForegroundColor Red\n    Write-Host \"Das Kernel-PnP-Log ist so nicht lesbar.\" -ForegroundColor Red\n    Write-Host \"\"\n}\n\n$protokoll = $false\n\ndo {\n    Show-Menu\n    $wahl = (Read-Host \"Auswahl\").Trim().ToUpper()\n\n    switch ($wahl) {\n        '1' { Invoke-PnpEvents }\n        '2' { Invoke-LogIntegrity }\n        '3' { Invoke-PciDevices }\n        '4' {\n              $h = Read-Host \"Zeitfenster in Stunden (Enter = 1)\"\n              if ([string]::IsNullOrWhiteSpace($h)) { $h = 1 }\n              Invoke-RemovedDevices -Stunden ([int]$h)\n            }\n        '5' { Invoke-DiskHistory }\n        '6' { Invoke-UsbHistory }\n        '7' { Invoke-RemoteTools }\n        '8' { Invoke-RemoteSessions }\n        '9' { Invoke-Unsigned }\n        '10' { Invoke-PSHistory }\n        '11' { Invoke-DiscordId }\n        '12' { Invoke-PEInspector }\n        '13' { Invoke-DLLHijackCheck }\n        '14' { Invoke-SystemProcessCheck }\n        '15' { Invoke-HVCICheck }\n        '16' { Invoke-System32Check }\n        '17' { Invoke-FuserCheck }\n        '18' { Invoke-ToolDownload }\n        'A' {\n              Invoke-LogIntegrity\n              Invoke-PnpEvents\n              Invoke-PciDevices\n              Invoke-RemovedDevices -Stunden 24\n              Invoke-DiskHistory\n              Invoke-UsbHistory\n              Invoke-RemoteTools\n              Invoke-RemoteSessions\n              Invoke-Unsigned\n              Invoke-PSHistory\n              Invoke-DiscordId\n              Invoke-DLLHijackCheck\n              Invoke-SystemProcessCheck\n              Invoke-HVCICheck\n              Invoke-FuserCheck\n              Write-Host \"`n[Punkt 16 wird im A-Durchlauf uebersprungen - manuell starten wegen Laufzeit]\" -ForegroundColor DarkGray\n            }\n        'P' {\n              if ($protokoll) {\n                  try { Stop-Transcript | Out-Null } catch {}\n                  $protokoll = $false\n                  Write-Host \"Protokoll gestoppt.\" -ForegroundColor Yellow\n              } else {\n                  $pfad = \"$env:USERPROFILE\\Desktop\\ctc_by_dark_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt\"\n                  try {\n                      Start-Transcript -Path $pfad | Out-Null\n                      $protokoll = $true\n                      Write-Host \"Protokoll laeuft: $pfad\" -ForegroundColor Green\n                  } catch {\n                      Write-Host \"Protokoll konnte nicht gestartet werden.\" -ForegroundColor Red\n                  }\n              }\n            }\n        'Q' { }\n        default { Write-Host \"Ungueltige Eingabe.\" -ForegroundColor Yellow }\n    }\n\n    if ($wahl -ne 'Q') {\n        Write-Host \"\"\n        Read-Host \"Enter fuer Menue\"\n        Clear-Host\n    }\n\n} while ($wahl -ne 'Q')\n\nif ($protokoll) { try { Stop-Transcript | Out-Null } catch {} }\nWrite-Host \"Beendet.\" -ForegroundColor Cyan\n", "url": "https://gist.github.com/analystdark/efed7e96c74e14fb6b7163de5d9cfa27"}, {"timestamp": "2026-10-10T19:02:40Z", "date_only": false, "value": "2026-10-10T19:02:40.000000Z", "kind": "sighting", "label": "Seen", "source": "https://gist.github.com/analystdark/f70b483d398735a0a7a1e380bbf01e87", "record": "CVE-2018-19320", "field": "creation_timestamp", "uuid": "38011751-b346-4be8-a6ad-d1e1186b768b", "content": "# ============================================================\n#  CTC by Dark (CatchTheCheat)\n#  Hardware- und Cheat-Analyse\n#  Ausfuehren als Administrator\n# ============================================================\n\n$L      = 'Microsoft-Windows-Kernel-PnP/Configuration'\n$OKVEN  = @('8086','1022','1002')\n$MUSTER = 'anydesk|rustdesk|teamviewer|parsec|dwservice|ultraviewer|ammyy'\n\n# ------------------------------------------------------------\n# BEKANNTE CHEAT-/BYPASS-NAMEN (vom Team pflegen)\n# Werden rot markiert in: Browserverlauf, Suchanfragen, Downloads,\n# DNS-Cache, Prefetch-Ladelisten (22) und Timeline (19).\n# Gross-/Kleinschreibung egal, Treffer auch innerhalb von Woertern.\n# ------------------------------------------------------------\n$CheatNamen = @(\n    # 'name'\n)\n# Bekannte Cheat-Domains (Webseite, Loader-/Auth-Server). Auch Subdomains werden erkannt.\n$CheatDomains = @(\n    # 'beispiel-cheat.xyz'\n)\n# Bekannte Cheat-Signierer: Firmennamen aus Code-Signatur-Zertifikaten, mit denen Cheats signiert sind\n# (Cheat-Anbieter kaufen oder stehlen Zertifikate, um Signatur-Scanner zu umgehen)\n$CheatSigner = @(\n    # 'Firmenname laut Zertifikat'\n)\n# Legitime Treffer, die NICHT markiert werden sollen\n$CheatNamenAusnahmen = '(?!)'   # z. B. '(?i)legitimes-produkt\\.com' - '(?!)' trifft nie zu\n\nfunction Get-CheatName([string]$text) {\n    if (-not $text) { return $null }\n    foreach ($d in $CheatDomains) { if ($text -match ('(?i)(^|[^a-z0-9-])(?:[a-z0-9-]+\\.)*' + [regex]::Escape($d) + '\\b')) { return $d } }\n    if ($CheatNamen.Count -eq 0 -or $text -match $CheatNamenAusnahmen) { return $null }\n    foreach ($n in $CheatNamen) { if ($text -match [regex]::Escape($n)) { return $n } }\n    return $null\n}\n\n# ------------------------------------------------------------\nfunction Test-Admin {\n    $id = [Security.Principal.WindowsIdentity]::GetCurrent()\n    (New-Object Security.Principal.WindowsPrincipal $id).IsInRole(\n        [Security.Principal.WindowsBuiltInRole]::Administrator)\n}\n\n# ------------------------------------------------------------\nfunction Get-DevId {\n    param($Event)\n    $x = [xml]$Event.ToXml()\n    ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'DeviceInstanceId' }).'#text'\n}\n\n# ============================================================\n#  1 - PnP-Ereignisse\n# ============================================================\nfunction Invoke-PnpEvents {\n    Write-Host \"`n=== Event-ID 411 (Startprobleme) ===\" -ForegroundColor Cyan\n    $e411 = @(Get-WinEvent -FilterHashtable @{LogName=$L;Id=411} -ErrorAction SilentlyContinue)\n    if ($e411.Count -gt 0) {\n        $e411 | Select-Object TimeCreated, Id,\n            @{n='Details';e={($_.Message -replace '\\s+',' ').Trim()}} |\n            Sort-Object TimeCreated -Descending | Format-List\n        Write-Host \"Anzahl 411: $($e411.Count)\" -ForegroundColor Red\n    } else {\n        Write-Host \"Keine 411er gefunden.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`n=== PnP-Konfigurationsereignisse (400/410/420/430) ===\" -ForegroundColor Cyan\n    $cfg = @(Get-WinEvent -FilterHashtable @{LogName=$L;Id=400,410,420,430} -ErrorAction SilentlyContinue |\n        ForEach-Object { [PSCustomObject]@{ Zeit=$_.TimeCreated; EID=$_.Id; Geraet=(Get-DevId $_) } })\n    if ($cfg.Count -gt 0) {\n        $cfg | Sort-Object Zeit | Format-Table -AutoSize -Wrap\n        Write-Host \"Gesamt: $($cfg.Count) Ereignisse\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"Keine Konfigurationsereignisse.\" -ForegroundColor Yellow\n    }\n}\n\n# ============================================================\n#  2 - Log-Integritaet und System-Eckdaten\n# ============================================================\nfunction Invoke-LogIntegrity {\n    Write-Host \"`n=== Geleerte Ereignisprotokolle (System EID 104) ===\" -ForegroundColor Cyan\n    $clr = @(Get-WinEvent -FilterHashtable @{LogName='System';Id=104} -MaxEvents 50 -ErrorAction SilentlyContinue)\n    if ($clr.Count -gt 0) {\n        $clr | ForEach-Object {\n            [PSCustomObject]@{\n                Zeit     = $_.TimeCreated\n                Benutzer = $_.Properties[0].Value\n                Computer = $_.Properties[1].Value\n                Log      = $_.Properties[2].Value\n            }\n        } | Format-Table -AutoSize -Wrap\n        Write-Host \"ACHTUNG: Protokolle wurden geleert.\" -ForegroundColor Red\n    } else {\n        Write-Host \"Keine Loeschvorgaenge protokolliert.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`n=== Security-Log geleert (EID 1102) ===\" -ForegroundColor Cyan\n    $s1102 = @(Get-WinEvent -FilterHashtable @{LogName='Security';Id=1102} -MaxEvents 20 -ErrorAction SilentlyContinue)\n    if ($s1102.Count -gt 0) {\n        $s1102 | Select-Object TimeCreated | Format-Table -AutoSize\n        Write-Host \"ACHTUNG: Security-Log wurde geleert.\" -ForegroundColor Red\n    } else {\n        Write-Host \"Keine Loeschung des Security-Logs.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`n=== System ===\" -ForegroundColor Cyan\n    $os = Get-CimInstance Win32_OperatingSystem\n    Write-Host \"Installiert:  $($os.InstallDate)\"\n    Write-Host \"Letzter Boot: $($os.LastBootUpTime)\"\n    Write-Host \"Computer:     $env:COMPUTERNAME\"\n    Write-Host \"Benutzer:     $env:USERNAME\"\n\n    Write-Host \"`n=== Log-Status ===\" -ForegroundColor Cyan\n    Get-WinEvent -ListLog $L,'System','Security','Application',\n        'Microsoft-Windows-Partition/Diagnostic' -ErrorAction SilentlyContinue |\n        Select-Object LogName, IsEnabled, RecordCount, LogMode | Format-Table -AutoSize\n\n    Write-Host \"=== Zeitaenderungen (Kernel-General EID 1) ===\" -ForegroundColor Cyan\n    Write-Host \"(NTP-Korrekturen im ms-Bereich durch svchost = normal; grosse Spruenge durch andere Prozesse = Befund)\" -ForegroundColor DarkGray\n    $zt = @(Get-WinEvent -FilterHashtable @{LogName='System';Id=1;ProviderName='Microsoft-Windows-Kernel-General'} -MaxEvents 100 -ErrorAction SilentlyContinue)\n    if ($zt.Count -gt 0) {\n        $ntpKorrekturen = 0\n        $echteSpruenge  = @()\n        $ausZeiten      = @()\n        foreach ($e in $zt) {\n            $x = [xml]$e.ToXml()\n            $alt  = ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'OldTime' }).'#text'\n            $neu  = ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'NewTime' }).'#text'\n            $proc = ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'ProcessName' }).'#text'\n            $grund= ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'Reason' }).'#text'\n            $sekunden = $null\n            try { $sekunden = ([DateTime]$neu - [DateTime]$alt).TotalSeconds } catch {}\n\n            $istSvchost = $proc -match '(?i)\\\\svchost\\.exe$'\n            $istKlein   = ($null -ne $sekunden) -and ([Math]::Abs($sekunden) -lt 60)\n\n            # Grund 2 = Hardware-Uhr beim Start/Aufwachen, Grund 3 = Zeitzone. Vorwaerts = PC war aus - normal.\n            if (($grund -eq '2' -or $grund -eq '3') -and ($null -ne $sekunden) -and $sekunden -ge 0) {\n                $ausZeiten += [PSCustomObject]@{ Aus=$alt; An=$neu; Stunden=[Math]::Round($sekunden / 3600, 1); Grund=$grund }\n                continue\n            }\n            if ($istSvchost -and $istKlein) {\n                $ntpKorrekturen++\n            } else {\n                $echteSpruenge += [PSCustomObject]@{\n                    Zeit     = $e.TimeCreated\n                    Sprung   = if ($null -ne $sekunden) { [Math]::Round($sekunden, 1) } else { '?' }\n                    Prozess  = if ($proc) { Split-Path $proc -Leaf } else { '?' }\n                    Grund    = $grund\n                    Von      = $alt\n                    Nach     = $neu\n                }\n            }\n        }\n\n        if ($ntpKorrekturen -gt 0) {\n            Write-Host \"  $ntpKorrekturen NTP-Korrektur(en) durch svchost (unter 60 s) - normal.\" -ForegroundColor Green\n        }\n        if ($ausZeiten.Count -gt 0) {\n            Write-Host (\"  {0} Systemstart(s)/Aufwachen - Uhr aus der Hardware-Uhr uebernommen (normal). Zeiten, in denen der PC aus war:\" -f $ausZeiten.Count) -ForegroundColor Green\n            foreach ($a in ($ausZeiten | Sort-Object { try { [DateTime]$_.An } catch { [DateTime]::MinValue } } -Descending | Select-Object -First 10)) {\n                $vonL = try { ([DateTime]$a.Aus).ToString('dd.MM.yyyy HH:mm') } catch { $a.Aus }\n                $bisL = try { ([DateTime]$a.An).ToString('dd.MM.yyyy HH:mm') } catch { $a.An }\n                Write-Host (\"    aus {0}  -&gt;  an {1}   ({2} h){3}\" -f $vonL, $bisL, $a.Stunden, $(if ($a.Grund -eq '3') { '  [Zeitzone]' } else { '' })) -ForegroundColor DarkGray\n            }\n        }\n        if ($echteSpruenge.Count -gt 0) {\n            Write-Host \"`n  [!] $($echteSpruenge.Count) auffaellige Zeitaenderung(en):\" -ForegroundColor Red\n            $echteSpruenge | Sort-Object Zeit -Descending | ForEach-Object {\n                $richtung = if ($_.Sprung -is [double] -and $_.Sprung -lt 0) { if ($_.Grund -eq '2') { ' RUECKWAERTS (Hardware-/BIOS-Uhr verstellt!)' } else { ' RUECKWAERTS' } } else { '' }\n                $col = if ($_.Sprung -is [double] -and [Math]::Abs($_.Sprung) -ge 3600) { 'Red' } else { 'Yellow' }\n                Write-Host (\"`n  [{0}] Sprung: {1} s{2}\" -f $_.Zeit, $_.Sprung, $richtung) -ForegroundColor $col\n                Write-Host (\"  Prozess : {0}\" -f $_.Prozess) -ForegroundColor $col\n                Write-Host (\"  Grund   : {0}\" -f $_.Grund) -ForegroundColor DarkGray\n                Write-Host (\"  Von/Nach: {0} -&gt; {1}\" -f $_.Von, $_.Nach) -ForegroundColor DarkGray\n            }\n            Write-Host \"`n  Rueckwaerts + Nicht-svchost = klassische Zeitstempel-Manipulation.\" -ForegroundColor DarkGray\n        } elseif ($ntpKorrekturen -eq 0) {\n            Write-Host \"  Keine Zeitaenderungen protokolliert.\" -ForegroundColor Green\n        }\n    } else {\n        Write-Host \"  Keine Zeitaenderungen protokolliert.\" -ForegroundColor Green\n    }\n\n    # --- Log-Groessen-Manipulation (stille Spurverwischung ohne 104/1102) ---\n    Write-Host \"`n=== Log-Groessen: Manipulation ===\" -ForegroundColor Cyan\n    Write-Host \"(Verkleinerte Logs ueberschreiben Eintraege sofort - kein Loesch-Event)\" -ForegroundColor DarkGray\n\n    # Windows-Standardgroessen\n    $logStandard = [ordered]@{\n        'Windows PowerShell'                          = 15728640   # 15 MB\n        'Microsoft-Windows-PowerShell/Operational'    = 15728640   # 15 MB\n        'Security'                                    = 20971520   # 20 MB\n        'System'                                      = 20971520   # 20 MB\n        'Application'                                 = 20971520   # 20 MB\n        'Microsoft-Windows-Kernel-PnP/Configuration'  = 1052672    # 1 MB\n        'Microsoft-Windows-CodeIntegrity/Operational' = 1052672    # 1 MB\n        'Microsoft-Windows-DeviceSetupManager/Admin'  = 1052672    # 1 MB\n        'Microsoft-Windows-Partition/Diagnostic'      = 1052672    # 1 MB\n    }\n\n    # Helfer fuer Registry-Key-Zeitstempel\n    $sigRQ = '[DllImport(\"advapi32.dll\")]public static extern int RegQueryInfoKey(Microsoft.Win32.SafeHandles.SafeRegistryHandle h,System.Text.StringBuilder a,ref int b,int c,ref int d,ref int e,ref int f,ref int g,ref int i,ref int j,ref int k,ref long l);'\n    Add-Type -MemberDefinition $sigRQ -Name RK2 -Namespace W2 -ErrorAction SilentlyContinue\n\n    $manipuliert = @()\n    foreach ($logName in $logStandard.Keys) {\n        $erwartet = $logStandard[$logName]\n        $log = Get-WinEvent -ListLog $logName -ErrorAction SilentlyContinue\n        if (-not $log) { continue }\n\n        $aktuell = $log.MaximumSizeInBytes\n        $prozent = [Math]::Round(($aktuell / $erwartet) * 100)\n\n        # Registry-Zeitstempel: wann wurde die Log-Konfiguration zuletzt geaendert?\n        $chanKey = \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Channels\\$logName\"\n        $legacyKey = \"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\EventLog\\$logName\"\n        $regKey = if (Test-Path $chanKey) { $chanKey } elseif (Test-Path $legacyKey) { $legacyKey } else { $null }\n        $geaendert = $null\n        if ($regKey) {\n            try {\n                $k = Get-Item $regKey -ErrorAction Stop\n                $t = 0L; $z = 0; $n = New-Object Text.StringBuilder 1024\n                [void][W2.RK2]::RegQueryInfoKey($k.Handle,$n,[ref]$z,0,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$t)\n                $geaendert = [DateTime]::FromFileTime($t)\n            } catch {}\n        }\n\n        $col = 'Green'; $flag = ''\n        if ($prozent -lt 25) {\n            $col = 'Red';    $flag = ' [!!!] STARK VERKLEINERT'\n        } elseif ($prozent -lt 75) {\n            $col = 'Yellow'; $flag = ' [!] verkleinert'\n        }\n\n        $prozentAnzeige = if ($prozent -gt 100) { '&gt;100' } else { $prozent }\n        $zeile = \"  {0,-48} {1,6} KB ({2,4}% vom Standard){3}\" -f $logName, [Math]::Round($aktuell/1024), $prozentAnzeige, $flag\n        Write-Host $zeile -ForegroundColor $col\n        if ($flag -and $geaendert) {\n            Write-Host (\"      Konfiguration geaendert: {0}\" -f $geaendert) -ForegroundColor $col\n            $manipuliert += [PSCustomObject]@{ Log=$logName; Groesse=$aktuell; Geaendert=$geaendert }\n        }\n\n        # Modus: Retain/AutoBackup statt Circular kann auch Manipulation sein\n        if ($log.LogMode -ne 'Circular') {\n            Write-Host (\"      LogMode: {0} (Standard: Circular)\" -f $log.LogMode) -ForegroundColor Yellow\n        }\n    }\n\n    if ($manipuliert.Count -gt 0) {\n        Write-Host \"`n  [!] $($manipuliert.Count) Log(s) verkleinert. Zeitpunkt der Aenderung mit Bypass-Verdacht abgleichen.\" -ForegroundColor Red\n        Write-Host \"      Typischer Ablauf: Bypass laden -&gt; Log verkleinern -&gt; Eintraege werden sofort ueberschrieben.\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"`n  Alle Log-Groessen im Normalbereich.\" -ForegroundColor Green\n    }\n\n    # Wurde wevtutil / Limit-EventLog ausgefuehrt? (das Werkzeug fuer Log-Manipulation)\n    Write-Host \"`n--- Log-Manipulations-Befehle in der PowerShell-Historie ---\" -ForegroundColor DarkGray\n    # Nur Befehle, die Logs leeren, verkleinern oder abschalten.\n    # 'wevtutil um/im' (Manifest ab-/anmelden) nutzen Treiber wie Realtek bei jedem Start - harmlos.\n    $manipMuster = '(?i)wevtutil(\\.exe)?\\s+(cl|clear-log)\\b|wevtutil(\\.exe)?\\s+(sl|set-log)\\b.*(/ms:|/e:false|/enabled:false|/rt:)|Limit-EventLog|Clear-EventLog|Remove-EventLog|MaximumSizeInBytes\\s*=|Set-ItemProperty.*(WINEVT|\\\\EventLog\\\\).*(MaxSize|Enabled)'\n    $manipTreffer = @()\n    Get-ChildItem 'C:\\Users' -Directory -ErrorAction SilentlyContinue | ForEach-Object {\n        $hf = Join-Path $_.FullName 'AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadline\\ConsoleHost_history.txt'\n        if (Test-Path $hf) {\n            $h = @(Select-String -Path $hf -Pattern $manipMuster -ErrorAction SilentlyContinue |\n                Where-Object { $_.Line -notmatch 'CTC_by_Dark|pnpcheck\\.ps1|ctcbydark|analystdark' })\n            foreach ($z in $h) { $manipTreffer += [PSCustomObject]@{ Benutzer=$_.Name; Befehl=$z.Line.Trim() } }\n        }\n    }\n    # Eigene Skriptbloecke ausschliessen - das Tool enthaelt die Suchbegriffe selbst\n    $eigenerCode = 'CTC by Dark|CatchTheCheat|CTC_by_Dark|pnpcheck\\.ps1|ctcbydark|\\$manipMuster|\\$logStandard|Log-Groessen: Manipulation'\n    # 4104: grosse Skripte werden in Teile zerlegt - Teile ueber ScriptBlockId zusammenhalten,\n    # damit ALLE Teile eines als CTC erkannten Skripts wegfallen (nicht nur Teil 1 mit dem Kopf)\n    $sbAlle  = @(Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational';Id=4104} -MaxEvents 1000 -ErrorAction SilentlyContinue)\n    $sbTeile = @(foreach ($e in $sbAlle) {\n        $d = ([xml]$e.ToXml()).Event.EventData.Data\n        [PSCustomObject]@{\n            Zeit = $e.TimeCreated\n            Id   = ($d | Where-Object { $_.Name -eq 'ScriptBlockId' }).'#text'\n            Text = ($d | Where-Object { $_.Name -eq 'ScriptBlockText' }).'#text'\n        }\n    })\n    $eigeneIds = @{}\n    foreach ($sbT in $sbTeile) { if ($sbT.Id -and $sbT.Text -match $eigenerCode) { $eigeneIds[$sbT.Id] = $true } }\n    $sbManip = @($sbTeile | Where-Object { -not $eigeneIds.ContainsKey([string]$_.Id) -and $_.Text -match $manipMuster })\n\n    # 400/600: Startbefehle deduplizieren (ein Start erzeugt mehrere Eintraege)\n    $klassikCmd = @(Get-WinEvent -FilterHashtable @{LogName='Windows PowerShell';Id=400,600} -MaxEvents 2000 -ErrorAction SilentlyContinue | ForEach-Object {\n        if ($_.Message -match 'HostApplication=(.+?)(\\r?\\n|$)') { [PSCustomObject]@{ Zeit=$_.TimeCreated; Cmd=$matches[1].Trim() } }\n    })\n    $manifestN = @($klassikCmd | Where-Object { $_.Cmd -match '(?i)wevtutil(\\.exe)?\\s+(um|im|uninstall-manifest|install-manifest)\\b' }).Count\n    $clManip = @($klassikCmd | Where-Object { $_.Cmd -match $manipMuster -and $_.Cmd -notmatch $eigenerCode } | Group-Object Cmd | ForEach-Object {\n        $g = @($_.Group | Sort-Object Zeit)\n        [PSCustomObject]@{ Cmd=$_.Name; Anzahl=$_.Count; Erst=$g[0].Zeit; Letzt=$g[-1].Zeit }\n    })\n\n    if ($manipTreffer.Count -gt 0 -or $sbManip.Count -gt 0 -or $clManip.Count -gt 0) {\n        Write-Host \"  [!!!] Log-Manipulationsbefehle gefunden:\" -ForegroundColor Red\n        $manipTreffer | ForEach-Object { Write-Host (\"    [History/{0}] {1}\" -f $_.Benutzer, $_.Befehl) -ForegroundColor Red }\n        $clManip | Sort-Object Letzt -Descending | ForEach-Object {\n            Write-Host (\"    [{0} bis {1}, {2}x] {3}\" -f $_.Erst, $_.Letzt, $_.Anzahl, $_.Cmd) -ForegroundColor Red\n        }\n        $sbManip | Sort-Object Zeit -Descending | Select-Object -First 15 | ForEach-Object {\n            $c = ([string]$_.Text -replace '\\s+',' ')\n            Write-Host (\"    [{0}] {1}\" -f $_.Zeit, $c.Substring(0,[Math]::Min(150,$c.Length))) -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"  Keine Log-Manipulationsbefehle in PowerShell-Spuren.\" -ForegroundColor Green\n        Write-Host \"  (Hinweis: wer die History loescht, versteckt auch das - Log-Groesse oben zaehlt trotzdem)\" -ForegroundColor DarkGray\n    }\n    if ($manifestN -gt 0) {\n        Write-Host (\"  ({0}x 'wevtutil um/im' ausgeblendet - Treiber melden ihr Log-Manifest an/ab, z. B. Realtek. Harmlos.)\" -f $manifestN) -ForegroundColor DarkGray\n    }\n\n    # --- Ausfuehrungsartefakte: Zustand und Auffaelligkeiten ---\n    Write-Host \"`n=== Ausfuehrungsartefakte ===\" -ForegroundColor Cyan\n    Write-Host \"(Zeigt Zustand, KEIN kryptografischer Manipulationsbeweis.\" -ForegroundColor DarkGray\n    Write-Host \" Tiefenauswertung: Zimmerman-Tools AmcacheParser / AppCompatCacheParser / MFTECmd)\" -ForegroundColor DarkGray\n\n    # Amcache.hve\n    Write-Host \"`n--- Amcache.hve ---\" -ForegroundColor DarkGray\n    $am = \"$env:SystemRoot\\AppCompat\\Programs\\Amcache.hve\"\n    if (Test-Path $am) {\n        $f = Get-Item $am -Force\n        Write-Host (\"Groesse: {0:N0} Bytes | Erstellt: {1} | Geaendert: {2}\" -f $f.Length,$f.CreationTime,$f.LastWriteTime)\n        if ($f.Length -lt 100KB) {\n            Write-Host \"AUFFAELLIG: Datei sehr klein - koennte geleert/zurueckgesetzt sein.\" -ForegroundColor Red\n        }\n        $os2 = Get-CimInstance Win32_OperatingSystem\n        if ($f.CreationTime -gt $os2.InstallDate.AddDays(1)) {\n            Write-Host \"AUFFAELLIG: Erstellt deutlich nach Windows-Installation - moeglw. neu angelegt.\" -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"FEHLT - Amcache.hve nicht vorhanden (regeneriert sich normalerweise).\" -ForegroundColor Red\n    }\n\n    # USN-Journal (NTFS-Aenderungsjournal)\n    Write-Host \"`n--- USN-Journal (Laufwerk C:) ---\" -ForegroundColor DarkGray\n    $usn = &amp; fsutil usn queryjournal C: 2&gt;&amp;1\n    if ($LASTEXITCODE -eq 0 -and $usn) {\n        $usn | ForEach-Object { Write-Host \"   $_\" }\n        $first = ($usn | Select-String 'Erste USN|First USN' | Select-Object -First 1) -replace '[^0-9x]',''\n        if ($first -match '^0x0+$' -or $first -eq '0') {\n            Write-Host \"AUFFAELLIG: Erste USN = 0 - Journal wurde geloescht und neu angelegt.\" -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"Journal nicht abfragbar oder deaktiviert.\" -ForegroundColor Yellow\n        Write-Host \"Ein DEAKTIVIERTES USN-Journal ist auf einem Gaming-PC ungewoehnlich.\" -ForegroundColor Red\n    }\n\n    # ShimCache / AppCompatCache\n    Write-Host \"`n--- ShimCache (AppCompatCache) ---\" -ForegroundColor DarkGray\n    $shim = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCompatCache'\n    if (Test-Path $shim) {\n        $val = (Get-ItemProperty $shim -Name AppCompatCache -ErrorAction SilentlyContinue).AppCompatCache\n        if ($val) {\n            Write-Host (\"Vorhanden, {0:N0} Bytes. Binaer - Auswertung nur mit AppCompatCacheParser.\" -f $val.Length)\n        } else {\n            Write-Host \"AUFFAELLIG: Schluessel vorhanden, aber leer.\" -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"AUFFAELLIG: AppCompatCache nicht vorhanden.\" -ForegroundColor Red\n    }\n\n    # Prefetch\n    Write-Host \"`n--- Prefetch ---\" -ForegroundColor DarkGray\n    $pfE = (Get-ItemProperty 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters' -Name EnablePrefetcher -ErrorAction SilentlyContinue).EnablePrefetcher\n    $pfDir = \"$env:SystemRoot\\Prefetch\"\n    $pfCount = if (Test-Path $pfDir) { @(Get-ChildItem \"$pfDir\\*.pf\" -ErrorAction SilentlyContinue).Count } else { 0 }\n    Write-Host (\"EnablePrefetcher: {0} | .pf-Dateien: {1}\" -f $pfE, $pfCount)\n    if ($pfE -eq 0) {\n        Write-Host \"AUFFAELLIG: Prefetch deaktiviert - haeufige Anti-Forensik-Massnahme.\" -ForegroundColor Red\n    } elseif ($pfCount -lt 20) {\n        Write-Host \"AUFFAELLIG: Sehr wenige .pf-Dateien - Prefetch koennte geleert worden sein.\" -ForegroundColor Red\n    }\n\n    # SRUM\n    Write-Host \"`n--- SRUM ---\" -ForegroundColor DarkGray\n    $srum = \"$env:SystemRoot\\System32\\sru\\SRUDB.dat\"\n    if (Test-Path $srum) {\n        $f = Get-Item $srum -Force\n        Write-Host (\"SRUDB.dat: {0:N0} Bytes | Geaendert: {1}\" -f $f.Length,$f.LastWriteTime)\n    } else {\n        Write-Host \"SRUDB.dat nicht vorhanden.\" -ForegroundColor Yellow\n    }\n\n    # ------------------------------------------------------------\n    # Geloeschte / neu angelegte Ereignisprotokoll-Dateien\n    # ------------------------------------------------------------\n    Write-Host \"`n--- Ereignisprotokoll-Dateien: geloescht und neu angelegt? ---\" -ForegroundColor DarkGray\n    Write-Host \"(Eine .evtx-Datei, die deutlich juenger ist als Windows, wurde geloescht oder ersetzt)\" -ForegroundColor DarkGray\n    $osInstLog = (Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue).InstallDate\n    # Kernprotokolle werden ab der Installation geschrieben - spaeter angelegt = geloescht/ersetzt\n    $kernLogs = @('System','Application','Security','Windows PowerShell','Microsoft-Windows-PowerShell%4Operational',\n                  'Microsoft-Windows-Kernel-PnP%4Configuration','Microsoft-Windows-Partition%4Diagnostic',\n                  'Microsoft-Windows-Windows Defender%4Operational','Microsoft-Windows-CodeIntegrity%4Operational',\n                  'Microsoft-Windows-Windows Firewall With Advanced Security%4Firewall','Microsoft-Windows-Kernel-Boot%4Operational',\n                  'Microsoft-Windows-Shell-Core%4Operational')\n    # Diese legt Windows oft erst beim ersten Eintrag oder beim Einschalten an - nur Hinweis\n    $bedarfLogs = @('Microsoft-Windows-AppID%4Operational','Microsoft-Windows-TaskScheduler%4Operational','Microsoft-Windows-Bits-Client%4Operational',\n                    'Microsoft-Windows-Storage-ClassPnP%4Operational','Microsoft-Windows-DeviceSetupManager%4Admin','Microsoft-Windows-WMI-Activity%4Operational')\n    $wichtigeLogs = $kernLogs + $bedarfLogs\n    $logOrdner = \"$env:SystemRoot\\System32\\winevt\\Logs\"\n    $neuAngelegt = 0\n    if ($osInstLog) {\n        foreach ($ln in $wichtigeLogs) {\n            $lf = Get-Item -LiteralPath (Join-Path $logOrdner \"$ln.evtx\") -Force -ErrorAction SilentlyContinue\n            if (-not $lf) { continue }\n            if ($lf.CreationTime -gt $osInstLog.AddDays(1)) {\n                $neuAngelegt++\n                if ($kernLogs -contains $ln) {\n                    Write-Host (\"  [!] {0}.evtx  angelegt {1}  (Windows installiert {2}) - KERNPROTOKOLL\" -f $ln, $lf.CreationTime, $osInstLog) -ForegroundColor Red\n                } else {\n                    Write-Host (\"  [?] {0}.evtx  angelegt {1}  - Windows legt diese Datei oft erst beim ersten Eintrag an; nur mit Dienststopp zur selben Zeit ein Beweis\" -f $ln, $lf.CreationTime) -ForegroundColor Yellow\n                }\n            }\n        }\n        if ($neuAngelegt -eq 0) { Write-Host \"  Alle wichtigen Protokolldateien stammen aus der Windows-Installation - keine geloescht/ersetzt.\" -ForegroundColor Green }\n        else { Write-Host \"  Neu angelegt = die alte Datei wurde geloescht. Dafuer muss der Ereignisprotokoll-Dienst gestoppt werden (siehe unten).\" -ForegroundColor DarkGray }\n    }\n\n    # Dienststopps des Ereignisprotokolls (Voraussetzung zum Loeschen einer .evtx)\n    $evSvc = @()\n    $evSvc += @(Get-WinEvent -FilterHashtable @{ LogName='System'; Id=7036,7040 } -MaxEvents 3000 -ErrorAction SilentlyContinue |\n        Where-Object { $_.Message -match '(?i)Windows Event Log|Windows-Ereignisprotokoll|EventLog' -and $_.Message -match '(?i)beendet|stopped|deaktiviert|disabled|manuell|demand' })\n    $evSvc += @(Get-WinEvent -FilterHashtable @{ LogName='Security'; Id=1100 } -MaxEvents 200 -ErrorAction SilentlyContinue)\n    if ($evSvc.Count -gt 0) {\n        Write-Host \"  Ereignisprotokoll-Dienst beendet / umgestellt (bei Herunterfahren normal - auf Zeitpunkte ohne Neustart achten):\" -ForegroundColor Yellow\n        $evSvc | Sort-Object TimeCreated -Descending | Select-Object -First 15 | ForEach-Object {\n            $m = ($_.Message -replace '\\s+',' ').Trim()\n            Write-Host (\"    [{0}] EID {1}  {2}\" -f $_.TimeCreated, $_.Id, $m.Substring(0,[Math]::Min(110,$m.Length))) -ForegroundColor DarkYellow\n        }\n    }\n\n    # ------------------------------------------------------------\n    # Microsoft Defender: Erkennungen, geloeschte Historie, Abschaltungen, Ausnahmen\n    # ------------------------------------------------------------\n    Write-Host \"`n--- Microsoft Defender: Erkennungen, Historie, Abschaltungen ---\" -ForegroundColor DarkGray\n    $defLog = 'Microsoft-Windows-Windows Defender/Operational'\n    $defEv = @(Get-WinEvent -FilterHashtable @{ LogName=$defLog; Id=1013,1116,1117,1118,1119,5000,5001,5007,5010,5012 } -MaxEvents 3000 -ErrorAction SilentlyContinue)\n    $histDel = @($defEv | Where-Object Id -eq 1013)\n    if ($histDel.Count -gt 0) {\n        Write-Host \"  [!] Erkennungs-Historie GELOESCHT (EID 1013) - von Hand oder automatische Bereinigung:\" -ForegroundColor Red\n        $histDel | Sort-Object TimeCreated -Descending | Select-Object -First 10 | ForEach-Object { Write-Host (\"    [{0}]\" -f $_.TimeCreated) -ForegroundColor Red }\n        Write-Host \"    Die Erkennungen selbst stehen trotzdem weiter unten (Ereignisse 1116/1117 und MPLog).\" -ForegroundColor DarkGray\n    }\n    $erk = @($defEv | Where-Object { $_.Id -in 1116,1117,1118,1119 })\n    if ($erk.Count -gt 0) {\n        Write-Host (\"  {0} Defender-Erkennungen/-Massnahmen:\" -f $erk.Count) -ForegroundColor Yellow\n        foreach ($e in ($erk | Sort-Object TimeCreated -Descending | Select-Object -First 25)) {\n            $d = @{}; ([xml]$e.ToXml()).Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_.'#text' }\n            $name = $d['Threat Name']; $pfad = $d['Path']; $akt = $d['Action Name']\n            $cn = Get-CheatName (\"{0} {1}\" -f $name, $pfad)\n            Write-Host (\"    [{0}] EID {1}  {2}{3}\" -f $e.TimeCreated, $e.Id, $name, $(if ($cn) { \"   &lt;-- BEKANNTER CHEAT-NAME: $cn\" } else { '' })) -ForegroundColor $(if ($e.Id -eq 1116) { 'Red' } else { 'Yellow' })\n            if ($pfad) { Write-Host (\"        {0}\" -f ($pfad -replace '^(file|containerfile|process|regkey|webfile):_', '')) -ForegroundColor DarkGray }\n            if ($akt)  { Write-Host (\"        Massnahme: {0}\" -f $akt) -ForegroundColor DarkGray }\n            if ($pfad -match '(?i)Invoke-RestMethod|Invoke-WebRequest|\\birm\\b|\\biwr\\b|DownloadString|raw\\.githubusercontent|gist\\.github') {\n                $url = if ($pfad -match \"(https?://[^'`\"\\s\\)]+)\") { $matches[1] } else { '' }\n                Write-Host (\"        Hinweis: Skript direkt aus dem Netz ausgefuehrt{0} - Adresse pruefen; auch Pruef-Tools (und CTC) werden so erkannt.\" -f $(if ($url) { \": $url\" } else { '' })) -ForegroundColor Yellow\n            }\n        }\n    } else {\n        Write-Host \"  Keine Defender-Erkennungen im Protokoll.\" -ForegroundColor Green\n    }\n    $aus = @($defEv | Where-Object { $_.Id -in 5001,5010,5012 })\n    $an  = @($defEv | Where-Object { $_.Id -eq 5000 } | Sort-Object TimeCreated)\n    if ($aus.Count -gt 0) {\n        Write-Host \"  [!] Schutz abgeschaltet (5001 Echtzeitschutz, 5010 Spyware-Scan, 5012 Virenscan) - mit Dauer bis zum Wiedereinschalten:\" -ForegroundColor Red\n        foreach ($a in ($aus | Sort-Object TimeCreated -Descending | Select-Object -First 15)) {\n            $wieder = $an | Where-Object { $_.TimeCreated -gt $a.TimeCreated } | Select-Object -First 1\n            $dauer  = if ($wieder) { $min = ($wieder.TimeCreated - $a.TimeCreated).TotalMinutes; if ($min -lt 120) { \"{0:N0} Min. aus\" -f $min } else { \"{0:N1} Std. aus\" -f ($min / 60) } } else { 'nicht wieder eingeschaltet (oder Neustart)' }\n            Write-Host (\"    [{0}] EID {1}  {2}\" -f $a.TimeCreated, $a.Id, $dauer) -ForegroundColor Red\n        }\n        # Muster: Schutz aus und innerhalb von 30 Minuten Erkennungs-Historie geloescht\n        $muster = @()\n        foreach ($h in $histDel) {\n            $vorher = $aus | Where-Object { $_.TimeCreated -lt $h.TimeCreated -and ($h.TimeCreated - $_.TimeCreated).TotalMinutes -le 30 } | Sort-Object TimeCreated -Descending | Select-Object -First 1\n            if ($vorher) { $muster += \"Schutz aus {0:dd.MM. HH:mm} -&gt; Historie geloescht {1:HH:mm}\" -f $vorher.TimeCreated, $h.TimeCreated }\n        }\n        if ($muster.Count -gt 0) {\n            Write-Host (\"  [!!!] MUSTER ({0}x): Echtzeitschutz abgeschaltet und kurz danach Erkennungs-Historie geloescht\" -f $muster.Count) -ForegroundColor Red\n            $muster | ForEach-Object { Write-Host \"        $_\" -ForegroundColor Red }\n            Write-Host \"        Typischer Ablauf: Schutz aus -&gt; etwas starten, das Defender meldet -&gt; Spuren entfernen.\" -ForegroundColor DarkGray\n        }\n    }\n    $konf = @($defEv | Where-Object { $_.Id -eq 5007 -and $_.Message -match '(?i)Exclusions|Ausschl|DisableRealtimeMonitoring|DisableAntiSpyware|TamperProtection' })\n    if ($konf.Count -gt 0) {\n        Write-Host \"  [!] Defender-Einstellungen geaendert (Ausnahmen / Abschaltung / Manipulationsschutz):\" -ForegroundColor Red\n        $konf | Sort-Object TimeCreated -Descending | Select-Object -First 15 | ForEach-Object {\n            $m = ($_.Message -replace '\\s+',' ')\n            $neu = if ($m -match '(?i)(Neuer Wert|New value):\\s*(.*?)\\s*(Alter Wert|Old value):') { $matches[2].Trim() } elseif ($m -match '(?i)(Neuer Wert|New value):\\s*(.+)$') { $matches[2].Trim() } else { '' }\n            $alt = if ($m -match '(?i)(Alter Wert|Old value):\\s*(.+?)\\s*((Neuer Wert|New value):|$)') { $matches[2].Trim() } else { '' }\n            $wert = if ($neu) { $neu } else { $alt }\n            $ausnahme = if ($wert -match '(?i)\\\\Exclusions\\\\(Paths|Extensions|Processes|IpAddresses)\\\\(.+?)\\s*=') { \"{0}: {1}\" -f $matches[1], $matches[2] } else { $null }\n            if ($ausnahme) {\n                if ($neu) { Write-Host (\"    [{0}] AUSNAHME HINZUGEFUEGT  {1}\" -f $_.TimeCreated, $ausnahme) -ForegroundColor Red }\n                else      { Write-Host (\"    [{0}] Ausnahme entfernt      {1}\" -f $_.TimeCreated, $ausnahme) -ForegroundColor DarkYellow }\n            } else {\n                $txt = if ($wert) { $wert } else { $m.Substring(0,[Math]::Min(140,$m.Length)) }\n                Write-Host (\"    [{0}] {1}\" -f $_.TimeCreated, $txt) -ForegroundColor DarkYellow\n            }\n        }\n        $aktuell = @()\n        try { $mp = Get-MpPreference -ErrorAction Stop; $aktuell = @($mp.ExclusionPath) + @($mp.ExclusionProcess) + @($mp.ExclusionExtension) | Where-Object { $_ } } catch {}\n        if ($aktuell.Count -gt 0) { Write-Host (\"    Aktuell aktive Ausnahmen: {0}\" -f ($aktuell -join ', ')) -ForegroundColor Red }\n    }\n    # MPLog: Defender-eigene Textprotokolle, enthalten Erkennungen auch nach geloeschter Historie\n    $mpl = @(Get-ChildItem \"$env:ProgramData\\Microsoft\\Windows Defender\\Support\\MPLog-*.log\" -ErrorAction SilentlyContinue)\n    if ($mpl.Count -gt 0) {\n        $mpTreffer = @()\n        foreach ($f in $mpl) {\n            try {\n                $muster = 'DETECTIONEVENT|DETECTION_?ADD|Threat\\s*name|ThreatName'\n                $z = @(Select-String -LiteralPath $f.FullName -Pattern $muster -ErrorAction Stop)\n                if ($z.Count -eq 0) { $z = @(Select-String -LiteralPath $f.FullName -Pattern $muster -Encoding Unicode -ErrorAction Stop) }\n                $mpTreffer += @($z | ForEach-Object { $_.Line.Trim() })\n            } catch {}\n        }\n        $mpTreffer = @($mpTreffer | Select-Object -Unique)\n        if ($mpTreffer.Count -gt 0) {\n            Write-Host (\"  MPLog: {0} Erkennungszeilen (bleiben auch nach geloeschter Historie):\" -f $mpTreffer.Count) -ForegroundColor Yellow\n            $mpTreffer | Select-Object -Last 15 | ForEach-Object { Write-Host (\"    {0}\" -f $_.Substring(0,[Math]::Min(170,$_.Length))) -ForegroundColor DarkYellow }\n        } else {\n            Write-Host \"  MPLog: keine Erkennungszeilen.\" -ForegroundColor DarkGray\n        }\n    }\n}\n\n# ============================================================\n#  3 - PCI/PCIe-Geraete\n# ============================================================\nfunction Invoke-PciDevices {\n    Write-Host \"`n=== PCI/PCIe-Geraete (aktuell) ===\" -ForegroundColor Cyan\n    Write-Host (\"{0,-6} {1,-6} {2,-10} {3,-18} {4}\" -f 'VEN','DEV','STATUS','KLASSE','NAME') -ForegroundColor Cyan\n    Get-PnpDevice | Where-Object { $_.InstanceId -like 'PCI*' } | Sort-Object Class | ForEach-Object {\n        $v = [regex]::Match($_.InstanceId,'VEN_([0-9A-Fa-f]{4})').Groups[1].Value.ToUpper()\n        $d = [regex]::Match($_.InstanceId,'DEV_([0-9A-Fa-f]{4})').Groups[1].Value.ToUpper()\n        $c = if ($OKVEN -contains $v) { 'Green' } else { 'Red' }\n        Write-Host (\"{0,-6} {1,-6} {2,-10} {3,-18} {4}\" -f $v,$d,$_.Status,$_.Class,$_.FriendlyName) -ForegroundColor $c\n    }\n\n    # ------------------------------------------------------------\n    # PCIe-Verbindung: Geschwindigkeit/Lanes passen zum Chip? (gefaelschte IDs fallen hier auf)\n    # ------------------------------------------------------------\n    Write-Host \"`n=== PCIe-Verbindung der Geraete (Geschwindigkeit/Lanes) ===\" -ForegroundColor Cyan\n    Write-Host \"(Eine DMA-Karte kann die ID eines echten Geraets faelschen - nicht aber die ausgehandelte PCIe-Geschwindigkeit)\" -ForegroundColor DarkGray\n    # Hoechste PCIe-Generation, die der ECHTE Chip beherrscht (1 = 2,5 GT/s, 2 = 5 GT/s, 3 = 8 GT/s, 4 = 16 GT/s)\n    $maxGen = @{\n        '10EC:8168' = 1; '10EC:8136' = 1; '10EC:8161' = 1; '10EC:8167' = 1; '10EC:8169' = 1   # Realtek RTL8111/8168/8101 Gigabit\n        '10EC:8125' = 2; '10EC:3000' = 2                                                     # Realtek 2,5G\n        '8086:1539' = 1; '8086:1533' = 1; '8086:157B' = 1                                    # Intel I211 / I210\n        '8086:15F3' = 2; '8086:125B' = 2; '8086:125C' = 2                                    # Intel I225 / I226\n        '1102:0012' = 1; '1102:0011' = 1                                                     # Creative Sound Blaster PCIe\n        '12AB:0380' = 1                                                                      # YUAN / Elgato HD60 Pro\n    }\n    $genTxt = @{ 1='Gen1 2,5 GT/s'; 2='Gen2 5 GT/s'; 3='Gen3 8 GT/s'; 4='Gen4 16 GT/s'; 5='Gen5 32 GT/s' }\n    $netz = @{}\n    Get-NetAdapter -IncludeHidden -ErrorAction SilentlyContinue | ForEach-Object { if ($_.PnPDeviceID) { $netz[$_.PnPDeviceID.ToUpper()] = $_ } }\n\n    $pciAlle = @(Get-PnpDevice -PresentOnly -ErrorAction SilentlyContinue | Where-Object { $_.InstanceId -like 'PCI\\VEN_*' -and $_.Class -notin @('System','USB','SecurityDevices') -and $_.Class })\n    foreach ($d in $pciAlle) {\n        $ven = [regex]::Match($d.InstanceId, 'VEN_([0-9A-F]{4})').Groups[1].Value\n        $dev = [regex]::Match($d.InstanceId, 'DEV_([0-9A-F]{4})').Groups[1].Value\n        $key = \"$($ven):$($dev)\"\n        $p = @{}\n        foreach ($kn in 'DEVPKEY_PciDevice_CurrentLinkSpeed','DEVPKEY_PciDevice_CurrentLinkWidth','DEVPKEY_PciDevice_MaxLinkSpeed','DEVPKEY_PciDevice_MaxLinkWidth') {\n            try { $v = (Get-PnpDeviceProperty -InstanceId $d.InstanceId -KeyName $kn -ErrorAction Stop).Data; if ($null -ne $v) { $p[$kn] = [int]$v } } catch {}\n        }\n        $cs = $p['DEVPKEY_PciDevice_CurrentLinkSpeed']; $cw = $p['DEVPKEY_PciDevice_CurrentLinkWidth']\n        $ms = $p['DEVPKEY_PciDevice_MaxLinkSpeed'];     $mw = $p['DEVPKEY_PciDevice_MaxLinkWidth']\n        $lauf = if ($cs) { \"{0} x{1}\" -f $(if ($genTxt.ContainsKey($cs)) { $genTxt[$cs] } else { \"Gen$cs\" }), $cw } else { 'nicht abfragbar' }\n        $kann = if ($ms) { \"{0} x{1}\" -f $(if ($genTxt.ContainsKey($ms)) { $genTxt[$ms] } else { \"Gen$ms\" }), $mw } else { '-' }\n\n        $befund = ''; $col = 'DarkGray'\n        if ($maxGen.ContainsKey($key) -and (($ms -and $ms -gt $maxGen[$key]) -or ($cs -and $cs -gt $maxGen[$key]))) {\n            $befund = \"[!!!] Dieser Chip kann hoechstens $($genTxt[$maxGen[$key]]) - das Geraet meldet mehr. ID GEFAELSCHT (DMA-Karte?)\"\n            $col = 'Red'\n        } elseif ($ven -eq '10EE' -or $ven -eq '1172' -or $ven -eq '1204') {\n            $befund = '[!!!] FPGA-Hersteller (Xilinx/Altera/Lattice) - typische DMA-Hardware'; $col = 'Red'\n        }\n        Write-Host (\"  {0,-9} {1,-45} laeuft: {2,-18} kann: {3}\" -f $key, ($d.FriendlyName -replace '\\s+',' ').Substring(0, [Math]::Min(45, ($d.FriendlyName -replace '\\s+',' ').Length)), $lauf, $kann) -ForegroundColor $(if ($col -eq 'Red') { 'Red' } else { 'White' })\n        if ($befund) { Write-Host \"            $befund\" -ForegroundColor $col }\n\n        # Netzwerkkarten: arbeitet sie wirklich?\n        if ($d.Class -eq 'Net') {\n            $na = $netz[$d.InstanceId.ToUpper()]\n            if ($na) {\n                $mac = [string]$na.MacAddress\n                $macVerd = (-not $mac) -or $mac -match '^(00-){5}00$' -or $mac -match '^(FF-){5}FF$'\n                $ip = @(Get-NetIPAddress -InterfaceIndex $na.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue | Where-Object { $_.IPAddress -notmatch '^169\\.254\\.' }).Count -gt 0\n                $txt = \"            Netzwerk: Status {0} | MAC {1} | {2}\" -f $na.Status, $(if ($mac) { $mac } else { 'KEINE' }), $(if ($ip) { 'hat IP-Adresse' } else { 'keine IP-Adresse' })\n                Write-Host $txt -ForegroundColor $(if ($macVerd) { 'Red' } elseif ($na.Status -ne 'Up') { 'Yellow' } else { 'DarkGray' })\n                if ($macVerd) { Write-Host \"            [!!!] Netzwerkkarte ohne gueltige MAC-Adresse - bei echter Hardware kaum moeglich\" -ForegroundColor Red }\n                elseif ($na.Status -ne 'Up') { Write-Host \"            Hinweis: Karte nicht verbunden. Wird sie ueberhaupt genutzt? Bei Tarnung als Netzwerkkarte typisch - physisch pruefen (Kabel? LED?).\" -ForegroundColor Yellow }\n            } else {\n                Write-Host \"            [!] Als Netzwerkkarte gemeldet, aber Windows fuehrt sie nicht als Netzwerkadapter - verdaechtig\" -ForegroundColor Red\n            }\n        }\n    }\n    Write-Host \"  Tipp: Onboard-Chips laufen meist mit der Geschwindigkeit, die der Chip kann. Eine 'Realtek' mit Gen2 oder x4 ist keine Realtek.\" -ForegroundColor DarkGray\n\n    Write-Host \"`n=== Nicht mehr vorhandene PCI-Geraete ===\" -ForegroundColor Cyan\n    $reg = @(Get-ChildItem 'HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\PCI' -ErrorAction SilentlyContinue |\n        Select-Object -ExpandProperty PSChildName)\n    $da  = @(Get-PnpDevice -PresentOnly -ErrorAction SilentlyContinue |\n        Where-Object { $_.InstanceId -like 'PCI*' } |\n        ForEach-Object { ($_.InstanceId -split '\\\\')[1] })\n    $weg = @($reg | Where-Object { $da -notcontains $_ })\n    if ($weg.Count -gt 0) {\n        $weg | ForEach-Object { Write-Host \"FEHLT: $_\" -ForegroundColor Red }\n    } else {\n        Write-Host \"Keine Abweichung.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`n=== setupapi.dev.log ===\" -ForegroundColor Cyan\n    $sp = 'C:\\Windows\\INF\\setupapi.dev.log'\n    if (Test-Path $sp) {\n        $fi = Get-Item $sp\n        Write-Host (\"Groesse: {0:N0} Bytes | Erstellt: {1} | Geaendert: {2}\" -f $fi.Length,$fi.CreationTime,$fi.LastWriteTime)\n    } else {\n        Write-Host \"Datei nicht vorhanden - wurde sie geloescht?\" -ForegroundColor Red\n    }\n\n    # Echte PCI-Installationen aus setupapi (inkl. rotierter Alt-Logs) - NICHT die Treiber-Kataloglisten\n    Write-Host \"`n--- PCI-Geraete, die je installiert wurden (setupapi, echte Installationen) ---\" -ForegroundColor DarkGray\n    Write-Host \"(Nur '[Device Install ... - PCI\\...]'-Abschnitte mit Instanzpfad; Treiberpaket-ID-Listen werden ignoriert)\" -ForegroundColor DarkGray\n    $fpgaVen   = '(?i)VEN_(10EE|1172|1204|1D0F|1556)'\n    $vorhanden = @{}\n    Get-PnpDevice -PresentOnly -ErrorAction SilentlyContinue | Where-Object { $_.InstanceId -like 'PCI*' } | ForEach-Object { $vorhanden[$_.InstanceId.ToUpper()] = $true }\n    $install = @{}\n    foreach ($logDatei in @(Get-ChildItem 'C:\\Windows\\INF\\setupapi*.log' -ErrorAction SilentlyContinue | Where-Object { $_.Name -match '(?i)^setupapi\\.(dev|setup|offline)' })) {\n        $aktId = $null\n        try {\n            $fs = [System.IO.File]::Open($logDatei.FullName, 'Open', 'Read', 'ReadWrite')\n            $sr = New-Object System.IO.StreamReader($fs)\n        } catch { Write-Host \"  $($logDatei.Name) nicht lesbar.\" -ForegroundColor DarkGray; continue }\n        while ($null -ne ($zeile = $sr.ReadLine())) {\n            if ($zeile -match '^&gt;&gt;&gt;\\s+\\[.*Device Install.*? - (PCI\\\\VEN_[0-9A-Fa-f]{4}&amp;DEV_[0-9A-Fa-f]{4}[^\\\\\\]]*\\\\[^\\]]+)\\]') {\n                $aktId = $matches[1].ToUpper()\n                continue\n            }\n            if ($aktId -and $zeile -match '^&gt;&gt;&gt;\\s+Section start (\\d{4}/\\d{2}/\\d{2} \\d{2}:\\d{2}:\\d{2})') {\n                $zt = [DateTime]::ParseExact($matches[1], 'yyyy/MM/dd HH:mm:ss', [Globalization.CultureInfo]::InvariantCulture)\n                if (-not $install.ContainsKey($aktId) -or $zt -lt $install[$aktId]) { $install[$aktId] = $zt }\n                $aktId = $null\n            }\n        }\n        $sr.Close()\n    }\n    if ($install.Count -eq 0) {\n        Write-Host \"  Keine PCI-Installationsabschnitte gefunden (Log leer oder bereinigt?).\" -ForegroundColor Yellow\n    } else {\n        $fehltN = 0\n        foreach ($id in ($install.Keys | Sort-Object { $install[$_] })) {\n            $ven = [regex]::Match($id,'VEN_([0-9A-F]{4})').Groups[1].Value\n            $dev = [regex]::Match($id,'DEV_([0-9A-F]{4})').Groups[1].Value\n            $da  = $vorhanden.ContainsKey($id)\n            $flag = ''; $col = 'DarkGray'\n            if ($id -match $fpgaVen) { $flag += ' [FPGA-HERSTELLER]'; $col = 'Red' }\n            if (-not $da) { $flag += ' [FEHLT HEUTE]'; $fehltN++; if ($col -ne 'Red') { $col = 'Yellow' } }\n            Write-Host (\"  {0}  VEN {1} DEV {2}  {3}{4}\" -f $install[$id].ToString('dd.MM.yyyy HH:mm'), $ven, $dev, $id, $flag) -ForegroundColor $col\n        }\n        Write-Host (\"`n  {0} PCI-Instanzen je installiert, davon {1} heute nicht mehr vorhanden.\" -f $install.Count, $fehltN) -ForegroundColor $(if ($fehltN -gt 0) { 'Yellow' } else { 'Green' })\n        Write-Host \"  FEHLT HEUTE bei einer Steckkarte = sie steckte einmal und wurde entfernt (Datum = erste Installation).\" -ForegroundColor DarkGray\n        Write-Host \"  Normal sind FEHLT-Eintraege nach GPU-Tausch oder Board-/BIOS-Wechsel - Zeitpunkt pruefen.\" -ForegroundColor DarkGray\n    }\n}\n\n# ============================================================\n#  4 - Entfernte Geraete im Zeitfenster\n# ============================================================\nfunction Invoke-RemovedDevices {\n    param([int]$Stunden = 1)\n\n    $seit = (Get-Date).AddHours(-$Stunden)\n    Write-Host \"`n=== Entfernte Geraete seit $($seit.ToString('dd.MM.yyyy HH:mm')) ===\" -ForegroundColor Cyan\n\n    $rem = @(Get-WinEvent -FilterHashtable @{LogName=$L;Id=420;StartTime=$seit} -ErrorAction SilentlyContinue |\n        ForEach-Object { [PSCustomObject]@{ Zeit=$_.TimeCreated; Geraet=(Get-DevId $_) } })\n    if ($rem.Count -gt 0) {\n        Write-Host \"--- Abgezogen (Ereignisprotokoll) ---\" -ForegroundColor Red\n        $rem | Sort-Object Zeit | Format-Table -AutoSize -Wrap\n    } else {\n        Write-Host \"Keine 420-Ereignisse im Zeitfenster.\" -ForegroundColor Green\n    }\n\n    $sig = '[DllImport(\"advapi32.dll\")]public static extern int RegQueryInfoKey(Microsoft.Win32.SafeHandles.SafeRegistryHandle h,System.Text.StringBuilder a,ref int b,int c,ref int d,ref int e,ref int f,ref int g,ref int i,ref int j,ref int k,ref long l);'\n    Add-Type -MemberDefinition $sig -Name RK -Namespace W -ErrorAction SilentlyContinue\n\n    $da = @(Get-PnpDevice -PresentOnly -ErrorAction SilentlyContinue | ForEach-Object { $_.InstanceId })\n    $treffer = @()\n    foreach ($zweig in @('PCI','USB','USBSTOR','HID')) {\n        $pfad = \"HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\$zweig\"\n        if (-not (Test-Path $pfad)) { continue }\n        Get-ChildItem $pfad -ErrorAction SilentlyContinue | ForEach-Object {\n            $el = $_\n            Get-ChildItem $el.PSPath -ErrorAction SilentlyContinue | ForEach-Object {\n                $t = 0L; $z = 0; $n = New-Object Text.StringBuilder 1024\n                [void][W.RK]::RegQueryInfoKey($_.Handle,$n,[ref]$z,0,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$t)\n                $zeit = [DateTime]::FromFileTime($t)\n                $iid  = \"$zweig\\$($el.PSChildName)\\$($_.PSChildName)\"\n                if ($zeit -ge $seit -and ($da -notcontains $iid)) {\n                    $treffer += [PSCustomObject]@{\n                        Zuletzt = $zeit\n                        Geraet  = $iid\n                        Name    = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue).FriendlyName\n                    }\n                }\n            }\n        }\n    }\n    if ($treffer.Count -gt 0) {\n        Write-Host \"--- Registry frisch angefasst, Geraet nicht mehr vorhanden ---\" -ForegroundColor Red\n        $treffer | Sort-Object Zuletzt -Descending | Format-Table -AutoSize -Wrap\n    } else {\n        Write-Host \"Keine Registry-Auffaelligkeiten im Zeitfenster.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`nHinweis: Bei ausgeschaltetem Rechner entfernte Hardware\" -ForegroundColor DarkGray\n    Write-Host \"erzeugt KEINE Spur. Leeres Ergebnis ist keine Entlastung.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  5 - Datentraeger-Historie\n# ============================================================\nfunction Invoke-DiskHistory {\n    Write-Host \"`n=== Datentraeger-Historie (Partition/Diagnostic) ===\" -ForegroundColor Cyan\n\n    $plog = @(Get-WinEvent -LogName 'Microsoft-Windows-Partition/Diagnostic' -ErrorAction SilentlyContinue |\n        ForEach-Object {\n            $dat = ([xml]$_.ToXml()).Event.EventData.Data\n            [PSCustomObject]@{\n                Zeit   = $_.TimeCreated\n                EID    = $_.Id\n                Modell = ($dat | Where-Object { $_.Name -eq 'Model' }).'#text'\n                Serie  = ($dat | Where-Object { $_.Name -eq 'SerialNumber' }).'#text'\n            }\n        })\n\n    if ($plog.Count -eq 0) {\n        Write-Host \"Log leer oder nicht lesbar.\" -ForegroundColor Yellow\n        return\n    }\n\n    $s = $plog | Sort-Object Zeit\n    Write-Host (\"Zeitraum: {0} bis {1}  ({2} Eintraege)\" -f $s[0].Zeit, $s[-1].Zeit, $plog.Count) -ForegroundColor DarkGray\n\n    Write-Host \"`n--- Alle jemals erfassten Datentraeger ---\" -ForegroundColor DarkGray\n    $plog | Group-Object Serie | ForEach-Object {\n        $e = $_.Group | Sort-Object Zeit\n        [PSCustomObject]@{\n            Modell   = $e[0].Modell\n            Serie    = $_.Name\n            Erstmals = $e[0].Zeit\n            Zuletzt  = $e[-1].Zeit\n            Anzahl   = $_.Count\n        }\n    } | Sort-Object Zuletzt -Descending | Format-Table -AutoSize\n\n    Write-Host \"--- Im Log erfasst, aktuell NICHT angeschlossen ---\" -ForegroundColor DarkGray\n    $jetzt = @(Get-Disk -ErrorAction SilentlyContinue | ForEach-Object { $_.SerialNumber -replace '\\s','' })\n    $fehlt = @($plog | Group-Object Serie | Where-Object {\n        $sn = $_.Name -replace '[\\s\\.]',''\n        -not ($jetzt | Where-Object { $_ -and ($_ -replace '[\\s\\.]','') -like \"*$sn*\" })\n    })\n    if ($fehlt.Count -gt 0) {\n        $fehlt | ForEach-Object {\n            $e = $_.Group | Sort-Object Zeit\n            Write-Host (\"FEHLT: {0} | Serie {1} | zuletzt {2}\" -f $e[0].Modell, $_.Name, $e[-1].Zeit) -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"Alle erfassten Datentraeger sind angeschlossen.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`n--- Letzte 30 Ereignisse ---\" -ForegroundColor DarkGray\n    $plog | Sort-Object Zeit -Descending | Select-Object -First 30 | Format-Table -AutoSize\n\n    # ------------------------------------------------------------\n    # Spuren von Laufwerken, die heute NICHT vorhanden sind\n    # ------------------------------------------------------------\n    Write-Host \"`n--- Spuren von Laufwerken, die heute NICHT vorhanden sind (USB-Stick, geloeschte Partition, Container) ---\" -ForegroundColor DarkGray\n    Write-Host \"(Ein Cheat vom abgezogenen Stick hinterlaesst keine Datei auf C: - aber diese Verweise)\" -ForegroundColor DarkGray\n\n    Add-Type -ErrorAction SilentlyContinue -TypeDefinition @\"\nusing System;\nusing System.Text;\nusing System.Runtime.InteropServices;\npublic static class CtcDos {\n    [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)]\n    public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);\n}\n\"@\n    $vorhanden = @([System.IO.DriveInfo]::GetDrives() | Where-Object { $_.IsReady } | ForEach-Object { $_.Name.Substring(0,1).ToUpper() })\n    $volAktuell = @{}\n    foreach ($cc in 67..90) {\n        $sbD = New-Object System.Text.StringBuilder 260\n        try { if ([CtcDos]::QueryDosDevice(([string][char]$cc) + ':', $sbD, 260) -gt 0) { $volAktuell[$sbD.ToString().ToLower()] = [string][char]$cc } } catch {}\n    }\n    $spuren = New-Object System.Collections.ArrayList\n    $merke = {\n        param([string]$quelle, [string]$pfad, $zeit, [string]$extra)\n        $p = $pfad.Trim('\"', ' ')\n        if ($p -match '^([A-Za-z]):\\\\') {\n            $lw = $matches[1].ToUpper()\n            if ($vorhanden -notcontains $lw) { [void]$spuren.Add([PSCustomObject]@{ LW=\"$($lw):\"; Quelle=$quelle; Pfad=$p; Zeit=$zeit; Extra=$extra }) }\n        }\n    }\n    $rot13 = { param([string]$s) -join ($s.ToCharArray() | ForEach-Object { $c = [int]$_; if ($c -ge 65 -and $c -le 90) { [char](65 + ($c - 65 + 13) % 26) } elseif ($c -ge 97 -and $c -le 122) { [char](97 + ($c - 97 + 13) % 26) } else { $_ } }) }\n\n    $sids = @(Get-ChildItem 'Registry::HKEY_USERS' -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -match '^S-1-5-21-[\\d-]+$' } | ForEach-Object { $_.PSChildName })\n    foreach ($sid in $sids) {\n        $basis = \"Registry::HKEY_USERS\\$sid\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\"\n        # UserAssist: Programmstarts mit Zaehler und letzter Ausfuehrung (Namen ROT13-kodiert)\n        Get-ChildItem \"$basis\\UserAssist\" -ErrorAction SilentlyContinue | ForEach-Object {\n            $cnt = Join-Path $_.PSPath 'Count'\n            $k = Get-Item $cnt -ErrorAction SilentlyContinue\n            if (-not $k) { return }\n            foreach ($n in $k.GetValueNames()) {\n                $name = &amp; $rot13 $n\n                if ($name -notmatch '^[A-Za-z]:\\\\') { continue }\n                $b = $k.GetValue($n); $zeit = $null; $anz = ''\n                if ($b -is [byte[]] -and $b.Length -ge 68) {\n                    $ft = [BitConverter]::ToInt64($b, 60); if ($ft -gt 0) { try { $zeit = [DateTime]::FromFileTime($ft) } catch {} }\n                    $anz = \"{0}x gestartet\" -f [BitConverter]::ToInt32($b, 4)\n                }\n                &amp; $merke 'UserAssist (Programmstart)' $name $zeit $anz\n            }\n        }\n        # Ausfuehren-Dialog und eingegebene Pfade\n        foreach ($sub in @('RunMRU','TypedPaths')) {\n            $k = Get-Item \"$basis\\$sub\" -ErrorAction SilentlyContinue\n            if (-not $k) { continue }\n            $zt = $null\n            foreach ($n in $k.GetValueNames()) {\n                if ($n -eq 'MRUList') { continue }\n                &amp; $merke $(if ($sub -eq 'RunMRU') { 'Win+R (Ausfuehren)' } else { 'Explorer-Adresszeile' }) (([string]$k.GetValue($n)) -replace '\\\\1$','') $zt ''\n            }\n        }\n    }\n    # BAM: Programmstarts mit Zeit - auch von Datentraegern, die als HarddiskVolumeN nicht mehr existieren\n    Get-ChildItem 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\bam\\State\\UserSettings' -ErrorAction SilentlyContinue | ForEach-Object {\n        $k = $_\n        foreach ($n in $k.GetValueNames()) {\n            if ($n -notmatch '^\\\\Device\\\\HarddiskVolume\\d+\\\\') { continue }\n            $b = $k.GetValue($n); $zeit = $null\n            if ($b -is [byte[]] -and $b.Length -ge 8) { try { $zeit = [DateTime]::FromFileTime([BitConverter]::ToInt64($b, 0)) } catch {} }\n            $dev = ([regex]::Match($n, '^\\\\Device\\\\HarddiskVolume\\d+')).Value.ToLower()\n            if ($volAktuell.ContainsKey($dev)) {\n                &amp; $merke 'BAM (Programmstart)' ($volAktuell[$dev] + ':' + $n.Substring($dev.Length)) $zeit ''\n            } else {\n                [void]$spuren.Add([PSCustomObject]@{ LW=($dev -replace '^\\\\device\\\\','') ; Quelle='BAM (Programmstart)'; Pfad=$n; Zeit=$zeit; Extra='Datentraeger existiert nicht mehr' })\n            }\n        }\n    }\n    # Zuletzt geoeffnete Dateien (Verknuepfungen im Recent-Ordner)\n    try {\n        $sh = New-Object -ComObject WScript.Shell\n        Get-ChildItem 'C:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\*.lnk' -ErrorAction SilentlyContinue | ForEach-Object {\n            try { $ziel = $sh.CreateShortcut($_.FullName).TargetPath } catch { $ziel = '' }\n            if ($ziel) { &amp; $merke 'Zuletzt geoeffnet (LNK)' $ziel $_.LastWriteTime '' }\n        }\n    } catch {}\n\n    # Welches Geraet hatte den Buchstaben zuletzt? (MountedDevices)\n    $geraet = @{}\n    $md = Get-Item 'HKLM:\\SYSTEM\\MountedDevices' -ErrorAction SilentlyContinue\n    if ($md) {\n        foreach ($n in $md.GetValueNames()) {\n            if ($n -notmatch '^\\\\DosDevices\\\\([A-Z]):$') { continue }\n            $lw = $matches[1] + ':'\n            $b = $md.GetValue($n); $txt = 'unbekannt'\n            if ($b -is [byte[]]) {\n                if ($b.Length -eq 12) { $txt = 'MBR-Partition (Festplatte oder Stick)' }\n                elseif ($b.Length -ge 8 -and [Text.Encoding]::ASCII.GetString($b, 0, 8) -eq 'DMIO:ID:') { $txt = 'GPT-Partition (interne oder externe Platte)' }\n                else {\n                    $s = [Text.Encoding]::Unicode.GetString($b)\n                    if ($s -match '(?i)USBSTOR#Disk&amp;Ven_([^&amp;#]*)&amp;Prod_([^&amp;#]*)') { $txt = \"USB-STICK/USB-PLATTE: {0} {1}\" -f $matches[1], $matches[2] }\n                    elseif ($s -match '(?i)SCSI#(Disk|CdRom)&amp;Ven_([^&amp;#]*)&amp;Prod_([^&amp;#]*)') { $txt = \"{0} {1} {2}\" -f $matches[1], $matches[2], $matches[3] }\n                    elseif ($s -match '(?i)Virtual_DVD|VHD|Msft') { $txt = 'virtuelles Laufwerk (ISO/VHD eingebunden)' }\n                    elseif ($s -match '(?i)STORAGE#Volume|veracrypt|truecrypt') { $txt = 'Software-Volume (z. B. verschluesselter Container)' }\n                    elseif ($s -match '(?i)#([^#]+)#') { $txt = $matches[1] }\n                }\n            }\n            $geraet[$lw] = $txt\n        }\n    }\n\n    if ($spuren.Count -eq 0) {\n        Write-Host \"  Keine Verweise auf Laufwerke, die heute fehlen.\" -ForegroundColor Green\n    } else {\n        $ausfuehrbar = '(?i)\\.(exe|dll|sys|bat|cmd|ps1|vbs|js|hta|msi|scr|com)$'\n        foreach ($g in ($spuren | Group-Object LW | Sort-Object Name)) {\n            $dev = if ($geraet.ContainsKey($g.Name)) { $geraet[$g.Name] } else { 'kein Eintrag in MountedDevices (Netzlaufwerk, Container oder geloeschte Zuordnung)' }\n            $exeN = @($g.Group | Where-Object { $_.Pfad -match $ausfuehrbar }).Count\n            Write-Host (\"`n  [!] Laufwerk {0} - heute NICHT vorhanden | zuletzt: {1} | {2} Verweise, davon {3} Programme/Skripte\" -f $g.Name, $dev, $g.Count, $exeN) -ForegroundColor $(if ($exeN) { 'Red' } else { 'Yellow' })\n            $eindeutig = $g.Group | Sort-Object { if ($_.Zeit) { $_.Zeit } else { [datetime]::MinValue } } -Descending | Group-Object Pfad | ForEach-Object { $_.Group[0] }\n            foreach ($s in ($eindeutig | Select-Object -First 25)) {\n                $cn  = Get-CheatName $s.Pfad\n                $col = if ($cn -or $s.Pfad -match $ausfuehrbar) { 'Red' } else { 'DarkYellow' }\n                $zt  = if ($s.Zeit) { ([datetime]$s.Zeit).ToString('dd.MM.yyyy HH:mm') } else { '      -         ' }\n                Write-Host (\"    [{0}] {1,-28} {2}{3}{4}\" -f $zt, $s.Quelle, $s.Pfad, $(if ($s.Extra) { \"  ($($s.Extra))\" } else { '' }), $(if ($cn) { \"   &lt;-- BEKANNTER CHEAT-NAME: $cn\" } else { '' })) -ForegroundColor $col\n            }\n        }\n        Write-Host \"`n  Programme von einem fehlenden Laufwerk = vom Stick/Container gestartet. Zeitpunkt in Punkt 19, Geraet in Punkt 6 pruefen.\" -ForegroundColor DarkGray\n        Write-Host \"  Harmlos sind z. B. alte Spiele-Bibliotheken auf einer ausgebauten Platte oder Installations-Sticks - Pfad und Name entscheiden.\" -ForegroundColor DarkGray\n    }\n}\n\n# ============================================================\n#  6 - USB-Geraetehistorie\n# ============================================================\nfunction Invoke-UsbHistory {\n    Write-Host \"`n=== USB-Geraetehistorie ===\" -ForegroundColor Cyan\n    $da = @(Get-PnpDevice -PresentOnly -ErrorAction SilentlyContinue | ForEach-Object { $_.InstanceId })\n    foreach ($zweig in @('USBSTOR','USB')) {\n        $pfad = \"HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\$zweig\"\n        if (-not (Test-Path $pfad)) { continue }\n        Write-Host \"`n--- $zweig ---\" -ForegroundColor DarkGray\n        Get-ChildItem $pfad -ErrorAction SilentlyContinue | ForEach-Object {\n            $el = $_\n            Get-ChildItem $el.PSPath -ErrorAction SilentlyContinue | ForEach-Object {\n                $p = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue\n                $iid = \"$zweig\\$($el.PSChildName)\\$($_.PSChildName)\"\n                [PSCustomObject]@{\n                    Status = if ($da -contains $iid) { 'vorhanden' } else { 'FEHLT' }\n                    Name   = $p.FriendlyName\n                    Klasse = $p.Class\n                    Geraet = $el.PSChildName\n                    Serie  = $_.PSChildName\n                }\n            }\n        } | Sort-Object Status, Name | Format-Table -AutoSize -Wrap\n    }\n    Write-Host \"Hinweis: Viele FEHLT-Eintraege unter USB sind normal (Ports, Hubs, Kabel).\" -ForegroundColor DarkGray\n\n    # --- DeviceSetupManager: MAKCU / Arduino / Input-Emulator Spuren ---\n    Write-Host \"`n--- DeviceSetupManager: MAKCU / Arduino / Input-Emulator ---\" -ForegroundColor Cyan\n    Write-Host \"(CH343/CH340/CH341 = Arduino-Klon | ESP32-S3 = MAKCU | COM-Port = serielles Geraet)\" -ForegroundColor DarkGray\n\n    $dsmLog   = 'Microsoft-Windows-DeviceSetupManager/Admin'\n    $dsmOper  = 'Microsoft-Windows-DeviceSetupManager/Operational'\n    $dsmMuster = 'CH34|CH340|CH341|CH343|ESP32|ESP8266|MAKCU|Arduino|CP2102|CP210|PL2303|FT232|FTDI|silabser|usbser'\n    $comMuster = 'COM\\d+'\n\n    $dsmTreffer = @()\n    foreach ($log in @($dsmLog, $dsmOper)) {\n        $events = @(Get-WinEvent -LogName $log -MaxEvents 500 -ErrorAction SilentlyContinue)\n        foreach ($e in $events) {\n            if ($e.Message -match $dsmMuster -or $e.Message -match 'COM[3-9]|COM[1-9][0-9]') {\n                $comPort = if ($e.Message -match '(COM\\d+)') { $matches[1] } else { '' }\n                $chip    = ''\n                foreach ($m in @('CH343','CH340','CH341','CH34','ESP32-S3','ESP32','ESP8266','CP2102','CP210','PL2303','FT232','FTDI','silabser','usbser','MAKCU','Arduino')) {\n                    if ($e.Message -match [regex]::Escape($m)) { $chip = $m; break }\n                }\n                $dsmTreffer += [PSCustomObject]@{\n                    Zeit    = $e.TimeCreated\n                    EID     = $e.Id\n                    Chip    = $chip\n                    COM     = $comPort\n                    Meldung = ($e.Message -replace '\\s+',' ').Substring(0, [Math]::Min(120, $e.Message.Length))\n                }\n            }\n        }\n    }\n\n    if ($dsmTreffer.Count -gt 0) {\n        Write-Host \"`n  [!] TREFFER: Serielle/Arduino/MAKCU-Geraete im DeviceSetupManager-Log!\" -ForegroundColor Red\n        $dsmTreffer | Sort-Object Zeit -Descending | Select-Object -First 20 | ForEach-Object {\n            $col = if ($_.Chip -match 'ESP32|MAKCU') { 'Red' } else { 'Yellow' }\n            Write-Host (\"`n  [{0}] EID {1}\" -f $_.Zeit, $_.EID) -ForegroundColor $col\n            if ($_.Chip) { Write-Host (\"  Chip/Typ : {0}\" -f $_.Chip) -ForegroundColor $col }\n            if ($_.COM)  { Write-Host (\"  COM-Port : {0}\" -f $_.COM)  -ForegroundColor $col }\n            Write-Host (\"  Meldung  : {0}...\" -f $_.Meldung) -ForegroundColor DarkGray\n        }\n        Write-Host \"`n  Bedeutung: CH34x = Arduino-Klon (Input-Emulator Basis)\" -ForegroundColor DarkGray\n        Write-Host \"             ESP32-S3 = MAKCU oder aehnliches Aim-Geraet\" -ForegroundColor DarkGray\n        Write-Host \"             COM-Port-Eintrag = serielles USB-Geraet war angeschlossen\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"  Keine Arduino/MAKCU/ESP32-Spuren im DeviceSetupManager-Log.\" -ForegroundColor Green\n    }\n\n    # --- COM-Port-Registry: jemals registrierte serielle Geraete ---\n    Write-Host \"`n--- COM-Port-Historie (Registry) ---\" -ForegroundColor DarkGray\n    $comKey = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\COM Name Arbiter\\Devices'\n    if (Test-Path $comKey) {\n        $comPorts = Get-ItemProperty $comKey -ErrorAction SilentlyContinue\n        if ($comPorts) {\n            $comPorts.PSObject.Properties | Where-Object { $_.Name -notmatch '^PS' } | ForEach-Object {\n                Write-Host (\"  {0} = {1}\" -f $_.Name, $_.Value)\n            }\n        }\n    } else {\n        Write-Host \"  COM-Arbiter-Key nicht vorhanden.\" -ForegroundColor DarkGray\n    }\n}\n\n# ============================================================\n#  7 - Fernwartungssoftware\n# ============================================================\nfunction Invoke-RemoteTools {\n    Write-Host \"`n=== Fernwartungssoftware ===\" -ForegroundColor Cyan\n    $fund = $false\n\n    Write-Host \"`n--- Installiert (Registry) ---\" -ForegroundColor DarkGray\n    $uninst = @(\n      'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*',\n      'HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*',\n      'HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n    )\n    $tr = @(Get-ItemProperty $uninst -ErrorAction SilentlyContinue |\n        Where-Object { $_.DisplayName -match $MUSTER } |\n        Select-Object DisplayName, DisplayVersion, InstallDate, InstallLocation)\n    if ($tr) { $tr | Format-Table -AutoSize -Wrap; $fund = $true }\n    else { Write-Host \"Nichts gefunden.\" -ForegroundColor Green }\n\n    Write-Host \"`n--- Prefetch (belegt AUSFUEHRUNG) ---\" -ForegroundColor DarkGray\n    $pfEnabled = (Get-ItemProperty 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters' -Name EnablePrefetcher -ErrorAction SilentlyContinue).EnablePrefetcher\n    if ($pfEnabled -eq 0) {\n        Write-Host \"Prefetch ist DEAKTIVIERT - dieser Test ist wertlos.\" -ForegroundColor Yellow\n    }\n    $pf = @(Get-ChildItem 'C:\\Windows\\Prefetch\\*.pf' -ErrorAction SilentlyContinue |\n        Where-Object { $_.Name -match $MUSTER } |\n        Select-Object Name, CreationTime, LastWriteTime)\n    if ($pf) { $pf | Format-Table -AutoSize; $fund = $true }\n    else { Write-Host \"Kein Prefetch-Eintrag.\" -ForegroundColor Green }\n\n    Write-Host \"`n--- Dateien / Ordner ---\" -ForegroundColor DarkGray\n    $pfade = @(\"$env:ProgramFiles\",\"${env:ProgramFiles(x86)}\",\"$env:APPDATA\",\n               \"$env:LOCALAPPDATA\",\"$env:ProgramData\",\"$env:USERPROFILE\\Downloads\",\"$env:USERPROFILE\\Desktop\")\n    $df = @(foreach ($p in $pfade) {\n        if (Test-Path $p) {\n            Get-ChildItem $p -Recurse -Depth 2 -ErrorAction SilentlyContinue |\n                Where-Object { $_.Name -match $MUSTER } |\n                Select-Object FullName, Length, CreationTime, LastWriteTime\n        }\n    })\n    if ($df) { $df | Sort-Object CreationTime | Format-Table -AutoSize -Wrap; $fund = $true }\n    else { Write-Host \"Keine Dateien gefunden.\" -ForegroundColor Green }\n\n    Write-Host \"`n--- Dienste ---\" -ForegroundColor DarkGray\n    $sv = @(Get-CimInstance Win32_Service -ErrorAction SilentlyContinue |\n        Where-Object { $_.Name -match $MUSTER -or $_.DisplayName -match $MUSTER -or $_.PathName -match $MUSTER } |\n        Select-Object Name, DisplayName, State, StartMode, PathName)\n    if ($sv) { $sv | Format-Table -AutoSize -Wrap; $fund = $true }\n    else { Write-Host \"Keine Dienste.\" -ForegroundColor Green }\n\n    Write-Host \"`n--- Programmspuren in der Registry ---\" -ForegroundColor DarkGray\n    $rk = @(\n      'HKCU:\\SOFTWARE\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache',\n      'HKCU:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Compatibility Assistant\\Store',\n      'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Compatibility Assistant\\Store'\n    )\n    $sp = @(foreach ($k in $rk) {\n        if (Test-Path $k) {\n            (Get-Item $k).Property | Where-Object { $_ -match $MUSTER } |\n                ForEach-Object { [PSCustomObject]@{ Quelle=(Split-Path $k -Leaf); Eintrag=$_ } }\n        }\n    })\n    if ($sp) { $sp | Format-Table -AutoSize -Wrap; $fund = $true }\n    else { Write-Host \"Keine Registry-Spuren.\" -ForegroundColor Green }\n\n    Write-Host \"`n--- Firewall-Regeln ---\" -ForegroundColor DarkGray\n    $fw = @(Get-NetFirewallRule -ErrorAction SilentlyContinue |\n        Where-Object { $_.DisplayName -match $MUSTER } |\n        Select-Object DisplayName, Enabled, Direction, Action)\n    if ($fw) { $fw | Format-Table -AutoSize; $fund = $true }\n    else { Write-Host \"Keine Firewall-Regeln.\" -ForegroundColor Green }\n\n    if ($fund) {\n        Write-Host \"`nTREFFER vorhanden - Eintraege einzeln pruefen.\" -ForegroundColor Red\n        Write-Host \"Fernwartung hat viele harmlose Gruende. Der Zeitpunkt entscheidet.\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"`nKeine Hinweise auf Fernwartungssoftware.\" -ForegroundColor Green\n    }\n}\n\n# ============================================================\n#  8 - Fernwartung: Sitzungen und Dateiuebertragungen\n# ============================================================\nfunction Invoke-RemoteSessions {\n    Write-Host \"`n=== Fernwartung: Sitzungen und Dateiuebertragungen ===\" -ForegroundColor Cyan\n\n    # Schluesselwoerter, die auf Dateiuebertragung hindeuten\n    $ftMuster = 'file transfer|filetransfer|Files\\b|Starting file|Download|Upload|transfer of|Dateiuebertragung'\n\n    # --- AnyDesk ---\n    Write-Host \"`n--- AnyDesk ---\" -ForegroundColor DarkGray\n    $adPfade = @(\"$env:ProgramData\\AnyDesk\", \"$env:APPDATA\\AnyDesk\")\n    $adGefunden = $false\n    foreach ($p in $adPfade) {\n        if (-not (Test-Path $p)) { continue }\n        $adGefunden = $true\n        Write-Host \"Ordner: $p\" -ForegroundColor DarkGray\n        Get-ChildItem $p -Filter '*.trace' -ErrorAction SilentlyContinue |\n            Select-Object Name, Length, CreationTime, LastWriteTime | Format-Table -AutoSize\n\n        # connection_trace.txt: eine Zeile pro Sitzung\n        $ct = Join-Path $p 'connection_trace.txt'\n        if (Test-Path $ct) {\n            Write-Host \"-- Sitzungen (connection_trace.txt) --\" -ForegroundColor Yellow\n            Get-Content $ct -ErrorAction SilentlyContinue | Where-Object { $_.Trim() } |\n                ForEach-Object { Write-Host \"   $_\" }\n        }\n\n        # Dateiuebertragungen aus den Trace-Dateien\n        $tf = @(Get-ChildItem $p -Filter '*.trace' -ErrorAction SilentlyContinue)\n        foreach ($f in $tf) {\n            $hits = @(Select-String -Path $f.FullName -Pattern $ftMuster -ErrorAction SilentlyContinue)\n            if ($hits.Count -gt 0) {\n                Write-Host \"-- Moegliche Dateiuebertragung in $($f.Name) --\" -ForegroundColor Red\n                $hits | Select-Object -Last 40 | ForEach-Object { Write-Host \"   $($_.Line.Trim())\" }\n            }\n        }\n    }\n    if (-not $adGefunden) { Write-Host \"Keine AnyDesk-Ordner vorhanden.\" -ForegroundColor Green }\n\n    # --- RustDesk ---\n    Write-Host \"`n--- RustDesk ---\" -ForegroundColor DarkGray\n    $rdPfade = @(\"$env:APPDATA\\RustDesk\", \"$env:ProgramData\\RustDesk\", \"$env:LOCALAPPDATA\\RustDesk\")\n    $rdGefunden = $false\n    foreach ($p in $rdPfade) {\n        if (-not (Test-Path $p)) { continue }\n        $rdGefunden = $true\n        Write-Host \"Ordner: $p\" -ForegroundColor DarkGray\n        Get-ChildItem $p -Recurse -Include '*.log','*.toml' -ErrorAction SilentlyContinue |\n            Select-Object FullName, Length, CreationTime, LastWriteTime | Format-Table -AutoSize -Wrap\n\n        $logs = @(Get-ChildItem $p -Recurse -Filter '*.log' -ErrorAction SilentlyContinue)\n        foreach ($f in $logs) {\n            $hits = @(Select-String -Path $f.FullName -Pattern ($ftMuster + '|remote_id|Connection from|session') -ErrorAction SilentlyContinue)\n            if ($hits.Count -gt 0) {\n                Write-Host \"-- Eintraege in $($f.Name) --\" -ForegroundColor Yellow\n                $hits | Select-Object -Last 40 | ForEach-Object { Write-Host \"   $($_.Line.Trim())\" }\n            }\n        }\n    }\n    if (-not $rdGefunden) { Write-Host \"Keine RustDesk-Ordner vorhanden.\" -ForegroundColor Green }\n\n    # --- TeamViewer ---\n    Write-Host \"`n--- TeamViewer ---\" -ForegroundColor DarkGray\n    $tvPfade = @(\"$env:APPDATA\\TeamViewer\", \"$env:ProgramData\\TeamViewer\",\n                 \"$env:ProgramFiles\\TeamViewer\", \"${env:ProgramFiles(x86)}\\TeamViewer\")\n    $tvGefunden = $false\n    foreach ($p in $tvPfade) {\n        if (-not (Test-Path $p)) { continue }\n        $tvGefunden = $true\n        $conn = @(Get-ChildItem $p -Recurse -Include 'Connections*.txt' -ErrorAction SilentlyContinue)\n        foreach ($f in $conn) {\n            Write-Host \"-- $($f.FullName) --\" -ForegroundColor Yellow\n            Get-Content $f.FullName -ErrorAction SilentlyContinue | Where-Object { $_.Trim() } |\n                Select-Object -Last 40 | ForEach-Object { Write-Host \"   $_\" }\n        }\n        $tvlogs = @(Get-ChildItem $p -Recurse -Filter '*Logfile*.log' -ErrorAction SilentlyContinue)\n        foreach ($f in $tvlogs) {\n            $hits = @(Select-String -Path $f.FullName -Pattern $ftMuster -ErrorAction SilentlyContinue)\n            if ($hits.Count -gt 0) {\n                Write-Host \"-- Moegliche Dateiuebertragung in $($f.Name) --\" -ForegroundColor Red\n                $hits | Select-Object -Last 30 | ForEach-Object { Write-Host \"   $($_.Line.Trim())\" }\n            }\n        }\n    }\n    if (-not $tvGefunden) { Write-Host \"Keine TeamViewer-Ordner vorhanden.\" -ForegroundColor Green }\n\n    # --- Gegenprobe: geloeschte Logs / Ordnerzeiten ---\n    Write-Host \"`n--- Gegenprobe ---\" -ForegroundColor DarkGray\n    foreach ($p in ($adPfade + $rdPfade + $tvPfade)) {\n        if (Test-Path $p) {\n            $d = Get-Item $p\n            $anz = @(Get-ChildItem $p -Recurse -File -ErrorAction SilentlyContinue).Count\n            Write-Host (\"{0} | Erstellt {1} | Geaendert {2} | {3} Dateien\" -f $p, $d.CreationTime, $d.LastWriteTime, $anz)\n        }\n    }\n\n    Write-Host \"`nHinweis: Ordner vorhanden, aber Logdateien fehlen oder sind leer\" -ForegroundColor DarkGray\n    Write-Host \"= Spuren wurden geloescht. Das ist selbst ein Befund.\" -ForegroundColor DarkGray\n    Write-Host \"Zeitangaben in den Logs sind Ortszeit des Rechners.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  9 - Unsignierte Dateien (Treiber / Prozesse / Ablageorte)\n# ============================================================\nfunction Invoke-Unsigned {\n    Write-Host \"`n=== Unsignierte Dateien ===\" -ForegroundColor Cyan\n\n    # Signaturstatus, der als unauffaellig gilt\n    $okStatus = @('Valid')\n\n    # --- 9a: Geladene Kernel-Treiber (wichtigster Teil) ---\n    Write-Host \"`n--- Geladene Kernel-Treiber ---\" -ForegroundColor DarkGray\n    $drv = @(Get-CimInstance Win32_SystemDriver -ErrorAction SilentlyContinue |\n        Where-Object { $_.State -eq 'Running' -and $_.PathName })\n    $drvBad = @()\n    foreach ($d in $drv) {\n        $path = ($d.PathName -replace '\\\\SystemRoot', $env:SystemRoot) -replace '^\\\\\\?\\?\\\\',''\n        if (-not (Test-Path $path)) { continue }\n        $sig = Get-AuthenticodeSignature $path -ErrorAction SilentlyContinue\n        if ($sig.Status -notin $okStatus) {\n            $drvBad += [PSCustomObject]@{\n                Name    = $d.Name\n                Status  = $sig.Status\n                Signierer = if ($sig.SignerCertificate) { $sig.SignerCertificate.Subject -replace '^(?:.*?,\\s*)?CN=(?:\"([^\"]+)\"|([^,]+)).*$','$1$2' } else { '-' }\n                Pfad    = $path\n            }\n        }\n    }\n    if ($drvBad.Count -gt 0) {\n        $drvBad | Format-Table -AutoSize -Wrap\n        Write-Host \"$($drvBad.Count) nicht gueltig signierte Treiber - EINZELN pruefen.\" -ForegroundColor Red\n    } else {\n        Write-Host \"Alle geladenen Treiber gueltig signiert.\" -ForegroundColor Green\n    }\n\n    # --- 9b: Laufende Prozesse ---\n    Write-Host \"`n--- Laufende Prozesse ---\" -ForegroundColor DarkGray\n    $procBad = @()\n    Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Path } |\n        Select-Object -Property Path -Unique | ForEach-Object {\n            $sig = Get-AuthenticodeSignature $_.Path -ErrorAction SilentlyContinue\n            if ($sig.Status -notin $okStatus) {\n                $procBad += [PSCustomObject]@{\n                    Status    = $sig.Status\n                    Signierer = if ($sig.SignerCertificate) { $sig.SignerCertificate.Subject -replace '^(?:.*?,\\s*)?CN=(?:\"([^\"]+)\"|([^,]+)).*$','$1$2' } else { '-' }\n                    Pfad      = $_.Path\n                }\n            }\n        }\n    if ($procBad.Count -gt 0) {\n        $procBad | Sort-Object Pfad | Format-Table -AutoSize -Wrap\n        Write-Host \"$($procBad.Count) nicht gueltig signierte Prozesse.\" -ForegroundColor Red\n    } else {\n        Write-Host \"Alle laufenden Prozesse gueltig signiert.\" -ForegroundColor Green\n    }\n\n    # --- 9c: Ausfuehrbare Dateien in typischen Ablageorten ---\n    Write-Host \"`n--- .exe/.sys/.dll in Ablageorten (Temp, Downloads, AppData) ---\" -ForegroundColor DarkGray\n    $orte = @(\"$env:TEMP\",\"$env:USERPROFILE\\Downloads\",\"$env:APPDATA\",\"$env:LOCALAPPDATA\\Temp\",\"$env:ProgramData\")\n    $fileBad = @()\n    foreach ($o in $orte) {\n        if (-not (Test-Path $o)) { continue }\n        Get-ChildItem $o -Recurse -Depth 2 -Include '*.exe','*.sys','*.dll' -ErrorAction SilentlyContinue |\n            ForEach-Object {\n                $sig = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue\n                if ($sig.Status -eq 'NotSigned') {\n                    $fileBad += [PSCustomObject]@{\n                        Erstellt = $_.CreationTime\n                        Groesse  = $_.Length\n                        Pfad     = $_.FullName\n                    }\n                }\n            }\n    }\n    if ($fileBad.Count -gt 0) {\n        $fileBad | Sort-Object Erstellt -Descending | Select-Object -First 60 | Format-Table -AutoSize -Wrap\n        Write-Host \"$($fileBad.Count) unsignierte Dateien (max. 60 gezeigt).\" -ForegroundColor Yellow\n    } else {\n        Write-Host \"Keine unsignierten Dateien in den Ablageorten.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`nHinweis: 'UnknownError' heisst meist, dass die Datei nicht\" -ForegroundColor DarkGray\n    Write-Host \"signiert ist. Viele legitime Programme sind unsigniert -\" -ForegroundColor DarkGray\n    Write-Host \"ein unsignierter KERNEL-TREIBER ist der relevante Befund,\" -ForegroundColor DarkGray\n    Write-Host \"unsignierte Nutzerprogramme sind es meist nicht.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  10 - PowerShell-History und Ausfuehrungsprotokoll\n# ============================================================\nfunction Invoke-PSHistory {\n    Write-Host \"`n=== PowerShell-History ===\" -ForegroundColor Cyan\n\n    # --- 10a: PSReadline-History aller Benutzer ---\n    Write-Host \"`n--- PSReadline ConsoleHost_history.txt (alle Profile) ---\" -ForegroundColor DarkGray\n    $profile = Get-ChildItem 'C:\\Users' -Directory -ErrorAction SilentlyContinue\n    $gefunden = $false\n    foreach ($u in $profile) {\n        $hf = Join-Path $u.FullName 'AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadline\\ConsoleHost_history.txt'\n        if (Test-Path $hf) {\n            $gefunden = $true\n            $f = Get-Item $hf -Force\n            $zeilen = @(Get-Content $hf -ErrorAction SilentlyContinue)\n            Write-Host \"`nBenutzer: $($u.Name)\" -ForegroundColor Yellow\n            Write-Host (\"  Datei: {0:N0} Bytes | Geaendert: {1} | {2} Zeilen\" -f $f.Length,$f.LastWriteTime,$zeilen.Count)\n            if ($zeilen.Count -eq 0) {\n                Write-Host \"  AUFFAELLIG: History-Datei ist LEER.\" -ForegroundColor Red\n            } else {\n                Write-Host \"  --- Inhalt ---\" -ForegroundColor DarkGray\n                $zeilen | ForEach-Object { Write-Host \"    $_\" }\n            }\n        } else {\n            # Datei fehlt, aber Profil existiert\n            $psDir = Join-Path $u.FullName 'AppData\\Roaming\\Microsoft\\Windows\\PowerShell'\n            if (Test-Path $psDir) {\n                Write-Host \"`nBenutzer: $($u.Name)\" -ForegroundColor Yellow\n                Write-Host \"  AUFFAELLIG: PowerShell genutzt, aber History-Datei fehlt.\" -ForegroundColor Red\n            }\n        }\n    }\n    if (-not $gefunden) {\n        Write-Host \"Keine PSReadline-History gefunden.\" -ForegroundColor Yellow\n    }\n\n    # --- 10b: ScriptBlock-Logging (EID 4104) - ergiebigste Quelle ---\n    Write-Host \"`n--- ScriptBlock-Logging (PowerShell/Operational EID 4104) ---\" -ForegroundColor DarkGray\n    $sb = @(Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational';Id=4104} -MaxEvents 200 -ErrorAction SilentlyContinue)\n    if ($sb.Count -gt 0) {\n        Write-Host \"$($sb.Count) Ereignisse geladen. Zeige zusammengesetzte Skriptbloecke:\" -ForegroundColor Green\n        # Nur den ersten Teil jedes mehrteiligen Blocks nehmen (Teil 1 von N),\n        # damit ein Skript nicht N-fach erscheint; Windows-Eigenaufrufe filtern.\n        $sb | Sort-Object TimeCreated -Descending | ForEach-Object {\n            $x = [xml]$_.ToXml()\n            $data = $x.Event.EventData.Data\n            $teil = ($data | Where-Object { $_.Name -eq 'MessageNumber' }).'#text'\n            $code = ($data | Where-Object { $_.Name -eq 'ScriptBlockText' }).'#text'\n            [PSCustomObject]@{ Zeit=$_.TimeCreated; Teil=$teil; Code=$code }\n        } | Where-Object {\n            $_.Teil -eq '1' -and\n            $_.Code -and\n            $_.Code -notmatch 'prompt|PSConsoleHostReadLine|Set-PSReadLine|__VSCode|Get-Module|CompletionPredictor|IsAzureContextPresent'\n        } | Select-Object -First 25 | ForEach-Object {\n            $c = ($_.Code -replace '\\s+',' ').Trim()\n            if ($c.Length -gt 200) { $c = $c.Substring(0,200) + ' [...]' }\n            Write-Host (\"`n  [{0}]\" -f $_.Zeit) -ForegroundColor Yellow\n            Write-Host (\"  {0}\" -f $c)\n        }\n    } else {\n        Write-Host \"ScriptBlock-Logging nicht aktiv oder keine Eintraege.\" -ForegroundColor Yellow\n        Write-Host \"(Standardmaessig aus - Fehlen ist hier NICHT auffaellig.)\" -ForegroundColor DarkGray\n    }\n\n    # --- 10c: Modul-Logging (EID 4103) ---\n    Write-Host \"`n--- Modul-Logging (EID 4103) ---\" -ForegroundColor DarkGray\n    $ml = @(Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational';Id=4103} -MaxEvents 20 -ErrorAction SilentlyContinue)\n    if ($ml.Count -gt 0) {\n        Write-Host \"$($ml.Count) Ereignisse vorhanden.\" -ForegroundColor Green\n    } else {\n        Write-Host \"Kein Modul-Logging.\" -ForegroundColor Yellow\n    }\n\n    # --- 10e: HostApplication aus Klassik-Log (EID 400/600) ---\n    # Standardmaessig AKTIV - zeigt die Startkommandozeile jeder PS-Sitzung.\n    Write-Host \"`n--- Start-Kommandozeilen (Windows PowerShell EID 400/600) ---\" -ForegroundColor DarkGray\n    $klassik = @(Get-WinEvent -FilterHashtable @{LogName='Windows PowerShell';Id=400,600} -MaxEvents 500 -ErrorAction SilentlyContinue)\n    if ($klassik.Count -gt 0) {\n        $verdacht = '-enc |-encodedcommand|-e [A-Za-z0-9+/]{20}|downloadstring|downloadfile|downloaddata|-w hidden|-windowstyle hidden|invoke-expression| iex |frombase64|webclient|start-bitstransfer|certutil.*-urlcache|bitsadmin|invoke-webrequest|invoke-restmethod|\\bcurl |\\bwget |\\birm |\\biwr |net\\.webclient|system\\.net\\.http|http://|https://|wevtutil(\\.exe)?\\s+(cl|clear-log|sl|set-log)\\b|limit-eventlog|clear-eventlog|remove-eventlog|maximumsizeinbytes\\s*='\n        $cmds = $klassik | ForEach-Object {\n            if ($_.Message -match 'HostApplication=(.+?)(\\r?\\n|$)') {\n                [PSCustomObject]@{ Zeit=$_.TimeCreated; Cmd=$matches[1].Trim() }\n            }\n        } | Where-Object { $_.Cmd } |\n            Group-Object Cmd | ForEach-Object {\n                $g = $_.Group | Sort-Object Zeit\n                [PSCustomObject]@{ Erstmals=$g[0].Zeit; Zuletzt=$g[-1].Zeit; Anzahl=$_.Count; Cmd=$_.Name }\n            } | Sort-Object Zuletzt -Descending\n\n        Write-Host \"$($cmds.Count) unterschiedliche Start-Kommandozeilen:\" -ForegroundColor Green\n        # Bekannt-gute Aufrufe, die trotz Download-Muster NICHT rot sein sollen\n        # (der Lade-Einzeiler des Pruefwerkzeugs selbst).\n        $eigenesTool = 'gist\\.githubusercontent\\.com/analystdark|pnpcheck\\.ps1|ctcbydark'\n        # Muster, die einen Aufruf einordnen helfen (kein Beweis, aber Kontext)\n        $hinweisMuster = [ordered]@{\n            '(?i)ECHO_[A-Z_]+|\\\\echo-[0-9A-F]{6}-'    = 'ECHO - kommerzielles Screenshare-/Pruef-Tool (kein Cheat). Zeitpunkt = eine fruehere Pruefung'\n            'c12a7328-f81f-11d2-ba4b-00a0c93ec93b'  = 'fragt die EFI-Systempartition ab (Bootloader-Bereich - EFI-Cheats ODER Pruef-Tools)'\n            '(?i)mountvol|bcdedit|bcdboot'           = 'greift auf Boot-Konfiguration/EFI zu'\n            '(?i)fivem|gta5|citizenfx'               = 'fragt FiveM/GTA-Prozesse oder -Dateien ab'\n            '(?i)X509Certificate|Get-AuthenticodeSignature' = 'prueft Zertifikate/Signaturen'\n            '^--pid=\\d+$'                            = 'Programm mit eingebetteter PowerShell, an einen anderen Prozess (PID) angehaengt - welches Programm: Punkt 19 zum Zeitpunkt'\n            '(?i)-NonInteractive'                    = 'von einem Programm im Hintergrund gesteuert, nicht von Hand getippt'\n            '(?i)\\s-v(ersion)?\\s+2(\\.0)?\\b'           = 'erzwingt PowerShell 2.0 - umgeht Skript-Protokollierung und AMSI (Verschleierungstechnik; manche alte Installer auch)'\n            '(?i)-InputFormat Text -ExecutionPolicy Unrestricted' = 'Muster der Node.js-Bibliothek \"systeminformation\" (Electron-Apps wie Launcher/Overlays) - Hardware-Abfrage'\n            '(?i)\\.(bat|cmd)\\b.*-Verb\\s+runAs|runAs.*\\.(bat|cmd)\\b' = 'BATCH-DATEI MIT ADMINRECHTEN gestartet - Inhalt pruefen (Dienste stoppen/Logs leeren = Spuren verwischen?)'\n            '(?i)dienst|service|sysmain|pcasvc|\\bdps\\b|eventlog|\\bbam\\b'    = 'bezieht sich auf Windows-Dienste - System-Log 7036/7040 zu diesem Zeitpunkt pruefen'\n        }\n        $echoZeiten = @($cmds | Where-Object { $_.Cmd -match '(?i)ECHO_[A-Z_]+|\\\\echo-[0-9A-F]{6}-' } | ForEach-Object { [datetime]$_.Zuletzt })\n        foreach ($c in $cmds) {\n            $ausg = $c.Cmd\n            if ($ausg.Length -gt 200) { $ausg = $ausg.Substring(0,200) + ' [...]' }\n            $beiEcho = $false\n            if ($echoZeiten.Count -gt 0 -and $c.Cmd -match '(?i)-NonInteractive' -and $c.Cmd -notmatch '(?i)ECHO_[A-Z_]+') {\n                foreach ($ez in $echoZeiten) { if ([Math]::Abs(([datetime]$c.Zuletzt - $ez).TotalMinutes) -le 10) { $beiEcho = $true; break } }\n            }\n\n            # -EncodedCommand automatisch entschluesseln (Base64, UTF-16LE)\n            $klar = $null\n            if ($c.Cmd -match '(?i)\\s-(e|ec|en|enc|enco|encod|encode|encoded|encodedc|encodedco|encodedcom|encodedcomm|encodedcomma|encodedcomman|encodedcommand)\\s+([A-Za-z0-9+/=]{16,})') {\n                $b64 = $matches[2]\n                if ($b64.Length % 4 -ne 0) { $b64 = ($b64 -replace '=+$', ''); $b64 = $b64.Substring(0, $b64.Length - ($b64.Length % 4)) }\n                try { $klar = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($b64)) } catch { $klar = $null }\n                # Nur lesbaren Text akzeptieren (sonst war es kein echtes EncodedCommand)\n                if ($klar) {\n                    $lesbar = ($klar.ToCharArray() | Where-Object { ([int]$_ -ge 32 -and [int]$_ -lt 127) -or $_ -in \"`r\",\"`n\",\"`t\" }).Count\n                    if ($lesbar -lt $klar.Length * 0.9) { $klar = $null }\n                }\n            }\n            $klarKurz = if ($klar) { (($klar -replace '\\s+', ' ').Trim()) } else { $null }\n            if ($klarKurz -and $klarKurz.Length -gt 400) { $klarKurz = $klarKurz.Substring(0, 400) + ' [...]' }\n\n            $pruefText  = if ($klar) { $klar } else { $c.Cmd }\n            $verdMuster = $verdacht -replace '-enc \\|-encodedcommand\\|-e \\[A-Za-z0-9\\+/\\]\\{20\\}\\|', ''\n            $klarVerd   = $klar -and ($klar -match $verdMuster)\n            $istVerd    = ($c.Cmd -match $verdacht -and $c.Cmd -notmatch $eigenesTool) -and (-not $klar -or $klarVerd)\n            $nurKodiert = $klar -and -not $klarVerd -and $c.Cmd -notmatch $eigenesTool\n\n            if ($istVerd) {\n                Write-Host (\"`n  [{0}]  ({1}x)\" -f $c.Zuletzt, $c.Anzahl) -ForegroundColor Red\n                Write-Host (\"  VERDAECHTIG: {0}\" -f $ausg) -ForegroundColor Red\n            } elseif ($nurKodiert) {\n                Write-Host (\"`n  [{0}]  ({1}x)\" -f $c.Zuletzt, $c.Anzahl) -ForegroundColor Yellow\n                Write-Host (\"  VERSCHLUESSELT (Klartext ohne Download-/Verschleierungsmuster): {0}\" -f $ausg) -ForegroundColor Yellow\n            } else {\n                Write-Host (\"`n  [{0}]  ({1}x)\" -f $c.Zuletzt, $c.Anzahl) -ForegroundColor Yellow\n                Write-Host (\"  {0}\" -f $ausg)\n            }\n            if ($klarKurz) {\n                Write-Host (\"    Klartext: {0}\" -f $klarKurz) -ForegroundColor $(if ($klarVerd) { 'Red' } else { 'Cyan' })\n            }\n            if ($beiEcho) { Write-Host \"    Hinweis: zeitlich Teil einer ECHO-Pruefung (innerhalb 10 Min. um einen Echo-Aufruf)\" -ForegroundColor DarkYellow }\n            foreach ($m in $hinweisMuster.Keys) {\n                if ($pruefText -match $m -or $c.Cmd -match $m) {\n                    $col = if ($hinweisMuster[$m] -match '^(BATCH|erzwingt)') { 'Yellow' } else { 'DarkYellow' }\n                    Write-Host (\"    Hinweis: {0}\" -f $hinweisMuster[$m]) -ForegroundColor $col\n                }\n            }\n        }\n        Write-Host \"`nZusammenhang: Mehrere '-NonInteractive'-Aufrufe in derselben Minute stammen meist von EINEM Programm.\" -ForegroundColor DarkGray\n        Write-Host \"Welches Programm das war, zeigt Punkt 19 (BAM/Prefetch) mit diesem Zeitpunkt als Startzeit.\" -ForegroundColor DarkGray\n        Write-Host \"`nRot = Muster wie -enc, hidden, DownloadString, IEX (nicht immer boese,\" -ForegroundColor DarkGray\n        Write-Host \"aber typisch fuer verschleierte Ausfuehrung - einzeln pruefen).\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"Keine 400/600-Ereignisse - Klassik-Log leer oder geleert.\" -ForegroundColor Red\n        Write-Host \"(Dieses Log ist normal AKTIV; ein leeres ist auffaellig.)\" -ForegroundColor DarkGray\n    }\n\n    # --- 10d: Wurde das PowerShell-Log geleert? ---\n    Write-Host \"`n--- PowerShell-Log-Status ---\" -ForegroundColor DarkGray\n    Get-WinEvent -ListLog 'Microsoft-Windows-PowerShell/Operational','Windows PowerShell' -ErrorAction SilentlyContinue |\n        Select-Object LogName, IsEnabled, RecordCount | Format-Table -AutoSize\n\n    Write-Host \"Hinweis: Eine leere/fehlende History bei sonst genutztem PowerShell\" -ForegroundColor DarkGray\n    Write-Host \"deutet auf gezieltes Loeschen hin - selbst ein Befund.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  12 - PE Binary &amp; Driver Heuristics Inspector\n# ============================================================\nfunction Invoke-PEInspector {\n    Write-Host \"`n=== PE Binary &amp; Driver Heuristics Inspector ===\" -ForegroundColor Cyan\n    Write-Host \"(Hashes, BYOVD, Signatur, PE-Header, Pruefsumme, Sektionen, Einstiegspunkt, APIs, Gesamtbewertung)\" -ForegroundColor DarkGray\n    Write-Host \"Tipp: Start-Transcript (P) vorher aktivieren um Ergebnis zu sichern.\" -ForegroundColor DarkGray\n\n    $byovdHashes = @{\n        \"01ee72782b1d4182da0eef7f9859f7aa2f89cc46e9df51ef2807f43db4872121\" = \"RTCore64.sys (Micro-Star CVE-2019-16098)\"\n        \"31f4d725d8d7e01dd582120aa0f23223fa1ac3cb4414f4e5da801db9402ab490\" = \"gdrv.sys (GIGABYTE CVE-2018-19320)\"\n        \"eb601822c9a7da4175345a55018698dc54fe66d11a91d1e434f676ab65d382bb\" = \"Capcom.sys (Root-Exploit / SMEP)\"\n        \"046e8c8959d72215a774136e632831f2ff2cc0bcbc2becc278912efee7e3cf40\" = \"mhyprot2.sys (miHoYo Process/Memory Killer)\"\n        \"a66d92ff488e0402b8813c9fb60cf649372d65ab19aa67a421dff03fc29fc2a2\" = \"AsrDrv103.sys (ASRock Physical Memory R/W)\"\n        \"60c38ea120015ff363fe9d63c5a70ebfb44766b9319de8d98d248b6bb83c509a\" = \"ene.sys (ENE Technology DeviceIoControl)\"\n    }\n    $packerSections = @(\"upx0\",\"upx1\",\"upx2\",\".vmp0\",\".vmp1\",\".vmp2\",\"themida\",\".themida\",\".enigma1\",\".enigma2\",\".aspack\",\".adata\",\"pec1\",\"pec2\",\".mpress1\",\".mpress2\")\n    $dangerousAPIs = @{\n        \"Process Injection\"  = @(\"VirtualAllocEx\",\"WriteProcessMemory\",\"CreateRemoteThread\",\"NtQueueApcThread\",\"RtlCreateUserThread\",\"SetThreadContext\")\n        \"Memory Tampering\"   = @(\"NtMapViewOfSection\",\"ZwMapViewOfSection\",\"VirtualProtectEx\",\"NtWriteVirtualMemory\")\n        \"Kernel Interaction\" = @(\"ZwLoadDriver\",\"NtLoadDriver\",\"DeviceIoControl\",\"ObRegisterCallbacks\",\"MmCopyVirtualMemory\",\"MmMapIoSpace\")\n        \"Anti-Debug/Evasion\" = @(\"IsDebuggerPresent\",\"CheckRemoteDebuggerPresent\",\"NtQueryInformationProcess\",\"NtSetInformationThread\")\n    }\n    $suspiciousStrings = @(\n        # Cheat-Funktionen\n        'aimbot','wallhack','silentaim','triggerbot','cheatengine',\n        'processhacker','kdmapper','blackbone','drvload','kernelhook','minifilter',\n        # Injection-Techniken (aus realem WptsExtensions.dll Fund)\n        'manualmap','manual map','manualmapping',\n        'kernelmap','kernel manual map',\n        'injecthost','injectmonitor','injecttrigger',\n        'trigger=%s','injected ok','inject failed',\n        # Weitere Injection-Indikatoren\n        'reflectiveinject','reflective inject','shellcode',\n        'dllinjection','dll injection','remotethread',\n        'mapviewofsection inject','zwmapviewofsection'\n    )\n    # Wortgrenz-Keywords (kommen auch in legitimen Dateien vor)\n    $suspiciousStringsWB = @('hack','inject')\n\n    # Datei waehlen\n    $ziel = Read-Host \"`nPfad zur Datei (.exe/.dll/.sys) - leer lassen fuer Datei-Dialog\"\n    if ([string]::IsNullOrWhiteSpace($ziel)) {\n        Add-Type -AssemblyName System.Windows.Forms -ErrorAction SilentlyContinue\n        $dlg = New-Object System.Windows.Forms.OpenFileDialog\n        $dlg.Filter = \"Binaries &amp; Treiber (*.exe;*.dll;*.sys)|*.exe;*.dll;*.sys|Alle (*.*)|*.*\"\n        if ($dlg.ShowDialog() -eq 'OK') { $ziel = $dlg.FileName }\n        else { Write-Host \"Abgebrochen.\" -ForegroundColor Yellow; return }\n    }\n    if (-not (Test-Path $ziel)) { Write-Host \"Datei nicht gefunden: $ziel\" -ForegroundColor Red; return }\n    if ((Get-Item $ziel).PSIsContainer) { Write-Host \"Pfad ist ein Ordner, keine Datei: $ziel\" -ForegroundColor Red; return }\n\n    $dateiname = Split-Path $ziel -Leaf\n    Write-Host \"`nZiel: $ziel\" -ForegroundColor White\n    Write-Host (\"=\" * 70) -ForegroundColor DarkGray\n\n    try { $bytes = [System.IO.File]::ReadAllBytes($ziel) }\n    catch { Write-Host \"Lesefehler: $_\" -ForegroundColor Red; return }\n\n    # Befunde fuer die Gesamtbewertung am Ende (Stufe HIGH / MEDIUM / LOW) und entlastender Kontext\n    $befunde = New-Object System.Collections.ArrayList\n    $kontext = New-Object System.Collections.ArrayList\n    $bef = { param($stufe, $bereich, $text) [void]$befunde.Add([PSCustomObject]@{ Stufe=$stufe; Bereich=$bereich; Text=$text }) }\n    $istTreiber = $dateiname -match '(?i)\\.sys$'\n\n    # Phase 1: Hashes &amp; BYOVD\n    Write-Host \"`n[*] Phase 1: Hashes &amp; BYOVD-Abgleich\" -ForegroundColor Cyan\n    $hasher = [System.Security.Cryptography.SHA256]::Create()\n    $sha256 = [BitConverter]::ToString($hasher.ComputeHash($bytes)).Replace(\"-\",\"\").ToLower()\n    $md5    = [BitConverter]::ToString([System.Security.Cryptography.MD5]::Create().ComputeHash($bytes)).Replace(\"-\",\"\").ToLower()\n    Write-Host (\"    Groesse: {0:N0} Bytes\" -f $bytes.Length)\n    Write-Host \"    SHA256 : $sha256\"\n    Write-Host \"    MD5    : $md5\"\n    Write-Host \"    VT     : https://www.virustotal.com/gui/file/$sha256\" -ForegroundColor DarkGray\n    $byovdNamen = '(?i)^(iqvw64e|rtcore64|rtcore32|gdrv|asrdrv\\d*|asio\\d*|asupio|capcom|mhyprot\\d*|dbutil_2_3|ene|winring0\\w*|glckio\\d*|nvoclock|atillk64|bs_rcio\\d*|phymem\\w*|inpoutx64|zam64|kprocesshacker|speedfan|hw64)\\.sys$'\n    if ($byovdHashes.ContainsKey($sha256)) {\n        Write-Host \"    [!!!] BYOVD ERKANNT: $($byovdHashes[$sha256])\" -ForegroundColor Red\n        &amp; $bef 'HIGH' 'BYOVD' \"Hash eines bekannten verwundbaren Treibers: $($byovdHashes[$sha256])\"\n    } elseif ($dateiname -match $byovdNamen) {\n        Write-Host \"    [!] BYOVD  : Dateiname gehoert zu einem bekannten verwundbaren Treiber (Kernel-Mapper wie kdmapper nutzen solche).\" -ForegroundColor Yellow\n        Write-Host \"                 Hash nicht in der Liste - Version ueber den VirusTotal-Link pruefen. Neuere Herstellerversionen sind oft gepatcht.\" -ForegroundColor DarkGray\n        &amp; $bef 'MEDIUM' 'BYOVD' \"Dateiname eines bekannten verwundbaren Treibers ($dateiname) - Version/Hash pruefen\"\n    } else {\n        Write-Host \"    BYOVD  : Kein bekannter anfaelliger Treiber-Hash.\" -ForegroundColor Green\n    }\n    # Ort: Treiber gehoeren nach System32\\drivers oder in den DriverStore\n    if ($istTreiber -and $ziel -match '(?i)\\\\(Temp|Downloads|Desktop)\\\\|\\\\AppData\\\\|\\\\Users\\\\Public\\\\') {\n        Write-Host \"    [!!!] Treiberdatei in einem Benutzer-/Temp-Ordner - dort legen Kernel-Mapper ihren Treiber ab.\" -ForegroundColor Red\n        &amp; $bef 'HIGH' 'Speicherort' 'Treiber (.sys) liegt in Temp/Downloads/Desktop/AppData'\n    }\n\n    # Phase 2: Signatur &amp; EKUs\n    Write-Host \"`n[*] Phase 2: Digitale Signatur &amp; Zertifikats-EKUs\" -ForegroundColor Cyan\n    $sig = Get-AuthenticodeSignature -FilePath $ziel -ErrorAction SilentlyContinue\n    if ($sig) {\n        $sigCol = if ($sig.Status -eq 'Valid') { 'Green' } else { 'Red' }\n        Write-Host \"    Status     : $($sig.Status)\" -ForegroundColor $sigCol\n        if ($sig.SignerCertificate) {\n            Write-Host \"    Inhaber    : $($sig.SignerCertificate.Subject -replace '^(?:.*?,\\s*)?CN=(?:\"([^\"]+)\"|([^,]+)).*$','$1$2')\"\n            Write-Host \"    Aussteller : $($sig.SignerCertificate.Issuer -replace '^CN=([^,]+).*','$1')\"\n            foreach ($ext in $sig.SignerCertificate.Extensions) {\n                if ($ext -is [System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension]) {\n                    foreach ($oid in $ext.EnhancedKeyUsages) {\n                        switch ($oid.Value) {\n                            \"1.3.6.1.4.1.311.61.1.1\" { Write-Host \"    [EKU] WHQL Hardware-Signatur\" -ForegroundColor Green }\n                            \"1.3.6.1.4.1.311.10.3.6\" { Write-Host \"    [EKU] Windows Kernel-Mode Driver Signing\" -ForegroundColor Green }\n                            \"1.3.6.1.5.5.7.3.3\"       { Write-Host \"    [EKU] Standard Code-Signing\" }\n                        }\n                    }\n                }\n            }\n        } else { Write-Host \"    [!] Nicht signiert.\" -ForegroundColor Red }\n        if ($sig.Status -eq 'Valid') {\n            [void]$kontext.Add(\"Gueltige Authenticode-Signatur: \" + ($sig.SignerCertificate.Subject -replace '^(?:.*?,\\s*)?CN=(?:\"([^\"]+)\"|([^,]+)).*$','$1$2'))\n        } elseif ($sig.Status -eq 'HashMismatch') {\n            &amp; $bef 'HIGH' 'Signatur' 'HashMismatch - Datei wurde nach dem Signieren veraendert'\n        } else {\n            &amp; $bef $(if ($istTreiber) { 'HIGH' } else { 'MEDIUM' }) 'Signatur' \"Keine gueltige Signatur ($($sig.Status))\"\n        }\n    }\n\n    # Phase 3: PE-Header\n    Write-Host \"`n[*] Phase 3: PE-Header &amp; Anomalien\" -ForegroundColor Cyan\n    if ($bytes.Length -lt 64) { Write-Host \"    Datei zu klein.\" -ForegroundColor Red; return }\n\n    $stream = [System.IO.FileStream]::new($ziel, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)\n    $reader = [System.IO.BinaryReader]::new($stream)\n    $highestRawEnd = 0\n\n    try {\n        if ($reader.ReadUInt16() -ne 0x5A4D) { Write-Host \"    Kein MZ-Header.\" -ForegroundColor Red; return }\n        $null = $stream.Seek(0x3C, 0); $peOff = $reader.ReadUInt32()\n        $null = $stream.Seek($peOff, 0)\n        if ($reader.ReadUInt32() -ne 0x00004550) { Write-Host \"    Keine PE-Signatur.\" -ForegroundColor Red; return }\n\n        $null = $reader.ReadUInt16()              # Machine\n        $numSec = $reader.ReadUInt16()\n        $null = $reader.ReadUInt32()              # TimeDateStamp\n        $null = $stream.Seek(8, 1)                # PointerToSymbolTable + NumberOfSymbols\n        $optHdrSize = $reader.ReadUInt16()\n        $null = $reader.ReadUInt16()              # Characteristics\n        $optPos = $stream.Position\n        $optMagic = $reader.ReadUInt16()\n        $is64 = ($optMagic -eq 0x20B)\n        $null = $stream.Seek($optPos + 16, 0); $epRVA = $reader.ReadUInt32()\n        $null = $stream.Seek($optPos + 32, 0)\n        $secAlign = $reader.ReadUInt32(); $fileAlign = $reader.ReadUInt32()\n        $null = $stream.Seek($optPos + 60, 0); $sizeHdr = $reader.ReadUInt32()   # SizeOfHeaders\n        $dllCharOff = $optPos + 70                # DllCharacteristics (PE32 und PE32+)\n        $null = $stream.Seek($dllCharOff, 0); $dllChar = $reader.ReadUInt16()\n        $hasASLR = ($dllChar -band 0x0040) -ne 0\n        $hasDEP  = ($dllChar -band 0x0100) -ne 0\n\n        Write-Host \"    Architektur : $(if($is64){'x64'}else{'x86'})\"\n        Write-Host (\"    ASLR        : \" + $(if($hasASLR){'An'}else{'[!] AUS'})) -ForegroundColor $(if($hasASLR){'White'}else{'Red'})\n        Write-Host (\"    DEP/NX      : \" + $(if($hasDEP){'An'}else{'[!] AUS'})) -ForegroundColor $(if($hasDEP){'White'}else{'Red'})\n        Write-Host \"    Alignments  : Sektion=0x$($secAlign.ToString('X')) | Datei=0x$($fileAlign.ToString('X'))\"\n        if ($sizeHdr -gt 4096) { Write-Host \"    [!] SizeOfHeaders ungewoehnlich gross: $sizeHdr Bytes\" -ForegroundColor Yellow }\n        if (-not $hasASLR) { &amp; $bef 'MEDIUM' 'PE-Header' 'ASLR (DYNAMIC_BASE) ausgeschaltet' }\n        if (-not $hasDEP)  { &amp; $bef 'MEDIUM' 'PE-Header' 'DEP/NX ausgeschaltet' }\n\n        # PE-Pruefsumme: Windows verlangt bei Treibern eine korrekte Pruefsumme\n        try {\n            Add-Type -Namespace CtcPe -Name Chk -ErrorAction SilentlyContinue -MemberDefinition '[DllImport(\"imagehlp.dll\", CharSet = CharSet.Unicode)] public static extern uint MapFileAndCheckSumW(string file, out uint header, out uint calc);'\n            $chkHdr = [uint32]0; $chkCalc = [uint32]0\n            if ([CtcPe.Chk]::MapFileAndCheckSumW($ziel, [ref]$chkHdr, [ref]$chkCalc) -eq 0) {\n                if ($chkHdr -eq 0) {\n                    Write-Host \"    Pruefsumme  : nicht gesetzt (bei EXE/DLL ueblich)\" -ForegroundColor $(if ($istTreiber) { 'Yellow' } else { 'DarkGray' })\n                    if ($istTreiber) { &amp; $bef 'MEDIUM' 'PE-Header' 'Treiber ohne PE-Pruefsumme' }\n                } elseif ($chkHdr -eq $chkCalc) {\n                    Write-Host \"    Pruefsumme  : korrekt (0x$($chkHdr.ToString('X8')))\"\n                    [void]$kontext.Add('PE-Pruefsumme mathematisch korrekt')\n                } else {\n                    Write-Host \"    [!] Pruefsumme falsch: Kopf 0x$($chkHdr.ToString('X8')) / berechnet 0x$($chkCalc.ToString('X8')) - Datei nach dem Bauen veraendert (Patch?)\" -ForegroundColor Red\n                    &amp; $bef $(if ($istTreiber) { 'HIGH' } else { 'LOW' }) 'PE-Header' 'PE-Pruefsumme stimmt nicht - Datei nachtraeglich veraendert'\n                }\n            }\n        } catch {}\n\n        # Sanity-Check: Werte ausserhalb realistischer Grenzen = gepackt/geschuetzt\n        $parserValid = $true\n        if ($secAlign -gt 0x200000 -or $fileAlign -gt 0x100000 -or $sizeHdr -gt 0x100000) {\n            Write-Host \"`n    [!] PARSER-WARNUNG: Header-Werte ausserhalb normaler Bereiche.\" -ForegroundColor Yellow\n            Write-Host \"        SectionAlignment=0x$($secAlign.ToString('X')) | FileAlignment=0x$($fileAlign.ToString('X')) | SizeOfHeaders=$sizeHdr\" -ForegroundColor Yellow\n            Write-Host \"        PE-Kopf ist manipuliert oder beschaedigt - typisch fuer Protector (VMProtect, Themida) oder bewusst verfaelschte Loader.\" -ForegroundColor Yellow\n            Write-Host \"        Phase 4 (Sektionen) wird uebersprungen - Ergebnisse waeren nicht zuverlaessig.\" -ForegroundColor Yellow\n            $parserValid = $false\n            &amp; $bef 'HIGH' 'PE-Header' 'PE-Kopf mit unplausiblen Werten (Protector oder absichtlich verfaelscht)'\n        }\n\n        # Phase 4: Sektionen\n        Write-Host \"`n[*] Phase 4: Sektionen, Entropie &amp; Packer-Erkennung\" -ForegroundColor Cyan\n        if (-not $parserValid) {\n            Write-Host \"    Uebersprungen (siehe Warnung oben).\" -ForegroundColor Yellow\n        } else {\n        $null = $stream.Seek($peOff + 4 + 20 + $optHdrSize, 0)\n        $sectionMap = @()\n\n        for ($i = 0; $i -lt $numSec; $i++) {\n            $nameB = $reader.ReadBytes(8)\n            $sn    = [System.Text.Encoding]::ASCII.GetString($nameB).Trim([char]0)\n            $vSize = $reader.ReadUInt32(); $vAddr = $reader.ReadUInt32()\n            $rSize = $reader.ReadUInt32(); $rPtr  = $reader.ReadUInt32()\n            $null = $stream.Seek(12, 1); $sChar = $reader.ReadUInt32()\n            $isX = ($sChar -band 0x20000000) -ne 0\n            $isW = ($sChar -band 0x80000000) -ne 0\n            if (($rPtr + $rSize) -gt $highestRawEnd) { $highestRawEnd = $rPtr + $rSize }\n            $sectionMap += @{ VirtAddr=$vAddr; VirtSize=[Math]::Max($vSize,1); RawPtr=$rPtr; Name=$sn; W=$isW; X=$isX }\n\n            # Entropie inline berechnen\n            $ent = 0.0\n            if ($rSize -gt 0 -and ($rPtr + $rSize) -le $bytes.Length) {\n                $cnt = @{}\n                for ($x = $rPtr; $x -lt ($rPtr + $rSize); $x++) { $b = $bytes[$x]; $cnt[$b] = $cnt[$b] + 1 }\n                foreach ($k in $cnt.Keys) { $p = $cnt[$k] / $rSize; $ent -= $p * [Math]::Log($p, 2) }\n                $ent = [Math]::Round($ent, 2)\n            }\n\n            $fl = \"\"\n            if ($isW -and $isX) { $fl += \" [ALERT: W+X]\" }\n            if ($packerSections -contains $sn.ToLower()) { $fl += \" [PACKER]\" }\n            $col = if ($fl) { 'Red' } elseif ($ent -gt 7.0) { 'Yellow' } else { 'White' }\n            Write-Host (\"    [{0}] Raw:{1,-8} Virt:{2,-8} Entropie:{3}{4}\" -f $sn.PadRight(8),$rSize,$vSize,$ent,$fl) -ForegroundColor $col\n            if ($rSize -eq 0 -and $vSize -gt 0) { Write-Host \"      [!] 0 Bytes auf Platte, $vSize im RAM (Loader/Unpacker)\" -ForegroundColor Yellow }\n            if ($sn -eq '.text' -and $ent -gt 7.0) { Write-Host \"      [!] .text Entropie $ent/8.0 - Code verschluesselt oder gepackt!\" -ForegroundColor Red }\n            if ($isW -and $isX) { &amp; $bef 'HIGH' 'PE-Struktur' \"Sektion '$sn' ist gleichzeitig beschreibbar und ausfuehrbar (RWX) - Code kann sich zur Laufzeit selbst veraendern\" }\n            if ($packerSections -contains $sn.ToLower()) { &amp; $bef 'HIGH' 'PE-Struktur' \"Packer-/Protector-Sektion '$sn'\" }\n            if ($isX -and $ent -gt 7.2) { &amp; $bef 'HIGH' 'PE-Struktur' \"Code-Sektion '$sn' verschluesselt/gepackt (Entropie $ent)\" }\n        }\n\n        # Einstiegspunkt: liegt er in einer beschreibbaren Sektion oder ausserhalb aller Sektionen?\n        if ($epRVA -gt 0) {\n            $epSek = $sectionMap | Where-Object { $epRVA -ge $_.VirtAddr -and $epRVA -lt ($_.VirtAddr + $_.VirtSize) } | Select-Object -First 1\n            if (-not $epSek) {\n                Write-Host (\"    [!] Einstiegspunkt 0x{0:X} liegt in KEINER Sektion\" -f $epRVA) -ForegroundColor Red\n                &amp; $bef 'HIGH' 'Einstiegspunkt' 'Einstiegspunkt ausserhalb aller Sektionen'\n            } elseif ($epSek.W) {\n                Write-Host (\"    [!] Einstiegspunkt 0x{0:X} liegt in beschreibbarer Sektion '{1}'\" -f $epRVA, $epSek.Name) -ForegroundColor Red\n                &amp; $bef 'HIGH' 'Einstiegspunkt' \"Einstiegspunkt in beschreibbarer Sektion '$($epSek.Name)' (typisch fuer Packer und selbstmodifizierenden Code)\"\n            } else {\n                Write-Host (\"    Einstiegspunkt 0x{0:X} in Sektion '{1}' (nicht beschreibbar - normal)\" -f $epRVA, $epSek.Name) -ForegroundColor DarkGray\n            }\n        }\n\n        # Phase 4b: Import-Tabelle &amp; DLL-Hijacking-Kandidaten\n        Write-Host \"`n[*] Phase 4b: Import-Tabelle &amp; DLL-Hijacking-Check\" -ForegroundColor Cyan\n        $importDirPos = if ($is64) { $optPos + 120 } else { $optPos + 104 }\n        $null = $stream.Seek($importDirPos, 0)\n        $importRVA  = $reader.ReadUInt32()\n        $importSz   = $reader.ReadUInt32()\n\n        if ($importRVA -eq 0 -or $importSz -eq 0) {\n            Write-Host \"    Keine Import-Tabelle vorhanden.\" -ForegroundColor DarkGray\n        } else {\n            # RVA -&gt; Datei-Offset\n            $importOff = -1L\n            foreach ($s in $sectionMap) {\n                if ($importRVA -ge $s.VirtAddr -and $importRVA -lt ($s.VirtAddr + $s.VirtSize)) {\n                    $importOff = [int64]($importRVA - $s.VirtAddr + $s.RawPtr); break\n                }\n            }\n\n            if ($importOff -lt 0) {\n                Write-Host \"    Import-Tabelle nicht mappbar (gepackt?).\" -ForegroundColor Yellow\n            } else {\n                $importedDLLs = @()\n                $pos = [int64]$importOff\n                while ($pos + 20 -le $bytes.Length) {\n                    $nameRVA = [BitConverter]::ToUInt32($bytes, $pos + 12)\n                    if ($nameRVA -eq 0) { break }\n                    $nameOff = -1L\n                    foreach ($s in $sectionMap) {\n                        if ($nameRVA -ge $s.VirtAddr -and $nameRVA -lt ($s.VirtAddr + $s.VirtSize)) {\n                            $nameOff = [int64]($nameRVA - $s.VirtAddr + $s.RawPtr); break\n                        }\n                    }\n                    if ($nameOff -ge 0) {\n                        $sb = [System.Text.StringBuilder]::new()\n                        $nx = [int64]$nameOff\n                        while ($nx -lt $bytes.Length -and $bytes[$nx] -ne 0) { $null = $sb.Append([char]$bytes[$nx]); $nx++ }\n                        $dn = $sb.ToString()\n                        if ($dn -match '(?i)\\.dll$') { $importedDLLs += $dn }\n                    }\n                    $pos += 20\n                }\n\n                Write-Host \"    Importierte DLLs: $($importedDLLs.Count)\"\n                $parentDir = Split-Path $ziel -Parent\n                $hijackFound = $false\n                foreach ($dll in $importedDLLs) {\n                    $sameDir = Join-Path $parentDir $dll\n                    if (Test-Path $sameDir) {\n                        $dllSig = Get-AuthenticodeSignature $sameDir -ErrorAction SilentlyContinue\n                        $dllStatus = if ($dllSig) { $dllSig.Status } else { 'Unbekannt' }\n                        $dllColor = if ($dllStatus -eq 'Valid') { 'Yellow' } else { 'Red' }\n                        Write-Host (\"    [!] HIJACK-KANDIDAT: {0}\" -f $dll) -ForegroundColor $dllColor\n                        Write-Host (\"        Pfad: {0}\" -f $sameDir) -ForegroundColor $dllColor\n                        Write-Host (\"        Signatur: {0}\" -f $dllStatus) -ForegroundColor $dllColor\n                        $hijackFound = $true\n                    }\n                }\n                if (-not $hijackFound) {\n                    Write-Host \"    Keine gleichnamigen DLLs im selben Ordner.\" -ForegroundColor Green\n                }\n            }\n        }\n        } # Ende else parserValid\n\n        # Phase 5: Overlay &amp; eingebettete PEs\n        Write-Host \"`n[*] Phase 5: Overlay &amp; eingebettete PE-Dateien\" -ForegroundColor Cyan\n        if ($bytes.Length -gt $highestRawEnd -and $highestRawEnd -gt 0) {\n            $ovSize = $bytes.Length - $highestRawEnd\n            $cnt2 = @{}\n            for ($x = $highestRawEnd; $x -lt $bytes.Length; $x++) { $b=$bytes[$x]; $cnt2[$b]=$cnt2[$b]+1 }\n            $oe = 0.0\n            foreach ($k in $cnt2.Keys) { $p=$cnt2[$k]/$ovSize; $oe -= $p*[Math]::Log($p,2) }\n            Write-Host \"    [!] OVERLAY: $ovSize Bytes angehaengt (Entropie $([Math]::Round($oe,2))/8.0)\" -ForegroundColor Red\n        } else { Write-Host \"    Kein Overlay.\" -ForegroundColor Green }\n\n        $embN = 0\n        for ($j = 64; $j -lt ($bytes.Length - 1024); $j += 4) {\n            if ($bytes[$j] -eq 0x4D -and $bytes[$j+1] -eq 0x5A) {\n                $lf = [BitConverter]::ToUInt32($bytes, $j + 0x3C)\n                if ($lf -gt 0 -and ($j+$lf+4) -lt $bytes.Length -and $bytes[$j+$lf] -eq 0x50 -and $bytes[$j+$lf+1] -eq 0x45) {\n                    Write-Host \"    [!] Eingebettetes PE bei Offset 0x$($j.ToString('X')) (Dropper/Payload?)\" -ForegroundColor Red\n                    $embN++\n                }\n            }\n        }\n        if ($embN -eq 0) { Write-Host \"    Keine eingebetteten PE-Dateien.\" -ForegroundColor Green }\n\n    } finally { $reader.Close() }\n\n    # Phase 6: PDB-Pfad\n    Write-Host \"`n[*] Phase 6: Debug-Informationen (PDB-Pfad)\" -ForegroundColor Cyan\n    $pdb = $null\n    for ($i = 0; $i -lt ($bytes.Length - 28); $i++) {\n        if ($bytes[$i] -eq 0x52 -and $bytes[$i+1] -eq 0x53 -and $bytes[$i+2] -eq 0x44 -and $bytes[$i+3] -eq 0x53) {\n            $ss = $i + 24; $se = $ss\n            while ($se -lt $bytes.Length -and $bytes[$se] -ne 0) { $se++ }\n            if ($se -gt $ss) {\n                $p = [System.Text.Encoding]::UTF8.GetString($bytes, $ss, $se-$ss)\n                if ($p -match '(?i)\\.pdb$') { $pdb = $p; break }\n            }\n        }\n    }\n    if (-not $pdb) {\n        $ra = [System.Text.Encoding]::ASCII.GetString($bytes)\n        if ($ra -match '([a-zA-Z]:\\\\[^\\x00-\\x1F\\x7F-\\xFF]+\\.pdb)') { $pdb = $matches[1] }\n    }\n    if ($pdb) {\n        Write-Host \"    Build-Pfad: $pdb\"\n        if ($pdb -match '(?i)(cheat|inject|hook|hack|aim|esp|driver|bypass)') {\n            Write-Host \"    [!] ALERT: Verdaechtiges Keyword im Build-Pfad!\" -ForegroundColor Red\n        }\n    } else { Write-Host \"    PDB: Nicht gefunden oder gestrippt.\" -ForegroundColor DarkGray }\n\n    # Phase 7: High-Risk APIs &amp; Cheat-Keywords\n    Write-Host \"`n[*] Phase 7: High-Risk APIs &amp; Cheat-Keywords\" -ForegroundColor Cyan\n    $rawAscii = [System.Text.Encoding]::ASCII.GetString($bytes)\n    $apiTreffer = $false\n    foreach ($cat in $dangerousAPIs.Keys) {\n        $matched = @($dangerousAPIs[$cat] | Where-Object { $rawAscii -match [regex]::Escape($_) })\n        if ($matched.Count -gt 0) {\n            Write-Host \"    [!] $cat ($($matched.Count)): $($matched -join ', ')\" -ForegroundColor Red\n            $apiTreffer = $true\n            $stufeApi = switch ($cat) { 'Process Injection' { if ($matched.Count -ge 2) { 'MEDIUM' } else { 'LOW' } } 'Memory Tampering' { 'LOW' } 'Kernel Interaction' { 'LOW' } default { $null } }\n            if ($stufeApi) { &amp; $bef $stufeApi 'APIs' \"$($cat): $($matched -join ', ')\" }\n        }\n    }\n    if (-not $apiTreffer) { Write-Host \"    Keine gefaehrlichen APIs im Klartext.\" -ForegroundColor Green }\n\n    $foundKW = @($suspiciousStrings | Where-Object { $rawAscii -match [regex]::Escape($_) })\n    $foundKW += @($suspiciousStringsWB | Where-Object { $rawAscii -match \"\\b$([regex]::Escape($_))\\b\" })\n    $foundKW = $foundKW | Select-Object -Unique\n    if ($foundKW.Count -gt 0) {\n        Write-Host \"    [!] Verdaechtige Keywords: $($foundKW -join ', ')\" -ForegroundColor Red\n        &amp; $bef 'HIGH' 'Keywords' \"Cheat-Begriffe im Klartext: $($foundKW -join ', ')\"\n    } else { Write-Host \"    Keine Cheat-Keywords im Klartext.\" -ForegroundColor Green }\n\n    # Phase 8: Gesamtbewertung\n    $hoch = @($befunde | Where-Object Stufe -eq 'HIGH').Count\n    $mitt = @($befunde | Where-Object Stufe -eq 'MEDIUM').Count\n    $gesamt = if ($hoch -gt 0) { 'HIGH RISK' } elseif ($mitt -gt 0) { 'MEDIUM RISK' } elseif ($befunde.Count -gt 0) { 'LOW RISK' } else { 'UNAUFFAELLIG' }\n    $gCol   = if ($hoch -gt 0) { 'Red' } elseif ($mitt -gt 0) { 'Yellow' } else { 'Green' }\n    Write-Host \"`n[*] Phase 8: Gesamtbewertung\" -ForegroundColor Cyan\n    Write-Host (\"    [+] ERGEBNIS: {0}   ({1} hoch, {2} mittel, {3} niedrig)\" -f $gesamt, $hoch, $mitt, ($befunde.Count - $hoch - $mitt)) -ForegroundColor $gCol\n    foreach ($b in ($befunde | Sort-Object { @{ HIGH=0; MEDIUM=1; LOW=2 }[$_.Stufe] })) {\n        $c = switch ($b.Stufe) { 'HIGH' { 'Red' } 'MEDIUM' { 'Yellow' } default { 'DarkGray' } }\n        Write-Host (\"    [{0,-6}] [{1}] {2}\" -f $b.Stufe, $b.Bereich, $b.Text) -ForegroundColor $c\n    }\n    if ($kontext.Count -gt 0) {\n        Write-Host \"    Entlastender Kontext:\" -ForegroundColor DarkGray\n        $kontext | ForEach-Object { Write-Host \"      + $_\" -ForegroundColor Green }\n    }\n    Write-Host \"    Die Stufe bewertet nur den AUFBAU der Datei. Signierte Hersteller-Treiber haben oft RWX-/INIT-Sektionen -\" -ForegroundColor DarkGray\n    Write-Host \"    entscheidend sind Signierer, Speicherort und ob die Datei zu installierter Hardware/Software gehoert.\" -ForegroundColor DarkGray\n\n    Write-Host \"`n$('=' * 70)\" -ForegroundColor DarkGray\n    Write-Host \"Scan abgeschlossen: $dateiname\" -ForegroundColor Cyan\n    Write-Host \"Hinweis: Ergebnis wird im aktiven Transcript gesichert (Menue P).\" -ForegroundColor DarkGray\n    Write-Host \"Fuer groessere Dateien (.sys/.exe) empfiehlt sich zusaetzlich VirusTotal.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  13 - DLL Hijacking Live-Check (laufende Prozesse)\n# ============================================================\nfunction Invoke-DLLHijackCheck {\n    Write-Host \"`n=== DLL Hijacking Live-Check ===\" -ForegroundColor Cyan\n    Write-Host \"(Prueft laufende Prozesse auf Module aus unerwarteten Pfaden)\" -ForegroundColor DarkGray\n\n    # Pfade die als legitim gelten\n    $okPfade = @(\n        \"$env:SystemRoot\\\",\n        \"$env:ProgramFiles\\\",\n        \"${env:ProgramFiles(x86)}\\\",\n        \"$env:ProgramData\\Microsoft\\\"\n    )\n\n    Write-Host \"`n--- Module aus unerwarteten Pfaden ---\" -ForegroundColor DarkGray\n    $treffer = @()\n\n    Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Path } | ForEach-Object {\n        $proc    = $_\n        $procDir = (Split-Path $proc.Path -Parent).ToLower().TrimEnd('\\') + '\\'\n        try {\n            $proc.Modules | Where-Object { $_.FileName -and $_.FileName -notmatch '(?i)\\.(node|ocx|cpl|ax)$' } | ForEach-Object {\n                $modPath = $_.FileName\n                $modPathL = $modPath.ToLower()\n                $istOK = ($okPfade | Where-Object { $modPathL.StartsWith($_.ToLower()) }) -or\n                         $modPathL.StartsWith($procDir)\n                if (-not $istOK) {\n                    $sig = Get-AuthenticodeSignature $modPath -ErrorAction SilentlyContinue\n                    $status = if ($sig) { $sig.Status } else { 'Unbekannt' }\n                    $treffer += [PSCustomObject]@{\n                        Prozess  = $proc.Name\n                        PID      = $proc.Id\n                        Modul    = $_.ModuleName\n                        Pfad     = $modPath\n                        Signatur = $status\n                    }\n                }\n            }\n        } catch {}\n    }\n\n    if ($treffer.Count -gt 0) {\n        # Unsignierte zuerst\n        $treffer | Sort-Object Signatur, Prozess | ForEach-Object {\n            $col = if ($_.Signatur -eq 'Valid') { 'Yellow' } else { 'Red' }\n            Write-Host (\"`n  [{0}] PID {1}\" -f $_.Prozess, $_.PID) -ForegroundColor $col\n            Write-Host (\"  Modul : {0}\" -f $_.Modul) -ForegroundColor $col\n            Write-Host (\"  Pfad  : {0}\" -f $_.Pfad) -ForegroundColor $col\n            Write-Host (\"  Sig   : {0}\" -f $_.Signatur) -ForegroundColor $col\n        }\n        $unsigned = @($treffer | Where-Object { $_.Signatur -ne 'Valid' })\n        Write-Host \"`n$($treffer.Count) Treffer gesamt, davon $($unsigned.Count) nicht gueltig signiert.\" -ForegroundColor $(if($unsigned.Count -gt 0){'Red'}else{'Yellow'})\n    } else {\n        Write-Host \"Keine auffaelligen Module gefunden.\" -ForegroundColor Green\n    }\n\n    # Spielprozesse gezielt pruefen\n    Write-Host \"`n--- Spielprozesse gezielt pruefen ---\" -ForegroundColor DarkGray\n    $spielNamen = @('FiveM','FiveM_GTAProcess','GTA5','RageMP','altv','RedM','cfx')\n    $spielProcs = @(Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Name -match ($spielNamen -join '|') })\n    if ($spielProcs.Count -gt 0) {\n        foreach ($sp in $spielProcs) {\n            Write-Host \"`n  Prozess: $($sp.Name) (PID $($sp.Id))\" -ForegroundColor Yellow\n            try {\n                $sp.Modules | Where-Object { $_.FileName } | ForEach-Object {\n                    $sig = Get-AuthenticodeSignature $_.FileName -ErrorAction SilentlyContinue\n                    $status = if ($sig) { $sig.Status } else { 'Unbekannt' }\n                    if ($status -ne 'Valid') {\n                        Write-Host (\"  [!] Unsigniert: {0}\" -f $_.FileName) -ForegroundColor Red\n                    }\n                }\n            } catch {\n                Write-Host \"  Zugriff auf Module verweigert (Adminrechte noetig).\" -ForegroundColor Yellow\n            }\n        }\n    } else {\n        Write-Host \"Keine FiveM/GTA-Prozesse laufend.\" -ForegroundColor DarkGray\n    }\n\n    Write-Host \"`nHinweis: Gelb = signiert aber ungewoehnlicher Pfad.\" -ForegroundColor DarkGray\n    Write-Host \"         Rot  = unsigniert oder Signatur ungueltig = Befund pruefen.\" -ForegroundColor DarkGray\n    Write-Host \"Fuer Live-Analyse laufender Injektion: Sysinternals Process Monitor empfohlen.\" -ForegroundColor DarkGray\n\n    # --- Bekannte DLL-Hijacking-Zielordner ---\n    Write-Host \"`n--- Bekannte Hijacking-Zielordner (wbem, Tasks, Sysprep...) ---\" -ForegroundColor DarkGray\n\n    # Bekannte Ziel-DLLs fuer wbem-Hijacking (aus realen Faellen)\n    # PHANTOM = diese Dateien existieren auf normalem Windows NICHT in wbem\n    # Ihr blosses Vorhandensein ist bereits verdaechtig - Signatur egal\n    $wbemPhantom = @(\n        'WptsExtensions.dll',   # Phantom-DLL - existiert nie in wbem (Trojan.Yogi u.a.)\n        'WaasMedicSvc.dll',     # Phantom-DLL - gehoert nicht in wbem\n        'wlbsctrl.dll'          # Phantom-DLL - IKEEXT-Hijacking-Ziel\n    )\n    $wbemTargets = @(\n        'msdtcprx.dll',\n        'wmicmiplugin.dll',\n        'wbemcomn.dll'\n    )\n\n    $hijackOrdner = @{\n        'wbem'    = 'C:\\Windows\\System32\\wbem'\n        'Tasks'   = 'C:\\Windows\\System32\\Tasks'\n        'Sysprep' = 'C:\\Windows\\System32\\Sysprep'\n        'Spool'   = 'C:\\Windows\\System32\\spool\\drivers\\x64\\3'\n    }\n\n    $hijackFund = $false\n    foreach ($name in $hijackOrdner.Keys) {\n        $ordner = $hijackOrdner[$name]\n        if (-not (Test-Path $ordner)) { continue }\n\n        $dlls = @(Get-ChildItem $ordner -Filter '*.dll' -ErrorAction SilentlyContinue)\n        if ($dlls.Count -eq 0) { continue }\n\n        Write-Host \"`n  [$name] $ordner\" -ForegroundColor DarkGray\n        foreach ($f in $dlls) {\n            $sig = Get-AuthenticodeSignature $f.FullName -ErrorAction SilentlyContinue\n            $status = if ($sig) { $sig.Status } else { 'Unbekannt' }\n            $signierer = if ($sig -and $sig.SignerCertificate) {\n                $sig.SignerCertificate.Subject -replace '^(?:.*?,\\s*)?CN=(?:\"([^\"]+)\"|([^,]+)).*$','$1$2'\n            } else { '-' }\n\n            $istMS      = $signierer -match '(?i)Microsoft'\n            $istPhantom = $wbemPhantom -contains $f.Name\n            $istTarget  = $wbemTargets -contains $f.Name\n            $istVerd    = (-not $istMS) -or ($status -ne 'Valid')\n\n            if ($istPhantom) {\n                # Phantom-DLLs sind immer ein Befund - egal ob signiert\n                $col = 'Red'\n                Write-Host (\"    [!!!] PHANTOM-DLL: {0} | Sig: {1} | {2}\" -f $f.Name, $status, $signierer) -ForegroundColor $col\n                Write-Host (\"          Diese Datei gehoert NICHT in diesen Ordner - Hijacking-Beweis!\" ) -ForegroundColor $col\n                $hijackFound = $true\n            } elseif ($istVerd -or $istTarget) {\n                $col = if ($status -ne 'Valid' -or -not $istMS) { 'Red' } else { 'Yellow' }\n                $hinweis = if ($istTarget -and -not $istMS) { ' [BEKANNTES HIJACK-ZIEL + FREMD]' } elseif ($istTarget) { ' [BEKANNTES HIJACK-ZIEL]' } else { '' }\n                Write-Host (\"    [!] {0} | Sig: {1} | {2}{3}\" -f $f.Name, $status, $signierer, $hinweis) -ForegroundColor $col\n                $hijackFund = $true\n            }\n        }\n    }\n\n    if (-not $hijackFund) {\n        Write-Host \"  Keine auffaelligen DLLs in Hijacking-Zielordnern.\" -ForegroundColor Green\n    }\n\n    # --- setupapi.dev.log auf USB-Spuren pruefen ---\n    Write-Host \"`n--- SetupAPI: USB-Cheat-Lader-Spuren ---\" -ForegroundColor DarkGray\n    $setupLog = 'C:\\Windows\\INF\\setupapi.dev.log'\n    if (Test-Path $setupLog) {\n        # Ganzwort-Suche: 'bypass'/'loader'/'inject' nur als eigenes Wort - sonst Treffer in\n        # NVIDIA-Treibern (nvobjectloader64.dll, libcuda_loader.so) und Bluetooth (_HCIBYPASS)\n        $cheatMuster = '(?i)(?|]*?\\.(dll|sys|exe|cfg|inf|cat)\\b'\n\n        $begriffe = @(); $laufwerk = @()\n        $fsA = [System.IO.File]::Open($setupLog, 'Open', 'Read', 'ReadWrite')\n        $srA = New-Object System.IO.StreamReader($fsA)\n        $abschnitt = ''\n        while ($null -ne ($zeile = $srA.ReadLine())) {\n            if ($zeile -match '^&gt;&gt;&gt;\\s+Section start (\\d{4}/\\d{2}/\\d{2} \\d{2}:\\d{2}:\\d{2})') { $abschnitt = $matches[1]; continue }\n            if ($zeile -match $harmlos) { continue }\n            if ($zeile -match $cheatMuster) { $begriffe += [PSCustomObject]@{ Zeit=$abschnitt; Zeile=$zeile.Trim() } }\n            elseif ($zeile -match $fremdLw)  { $laufwerk += [PSCustomObject]@{ Zeit=$abschnitt; Zeile=$zeile.Trim() } }\n        }\n        $srA.Close()\n\n        if ($begriffe.Count -gt 0) {\n            Write-Host \"  [!] Verdaechtige Begriffe in setupapi.dev.log:\" -ForegroundColor Red\n            $begriffe | Select-Object -First 25 | ForEach-Object { Write-Host (\"    [{0}] {1}\" -f $_.Zeit, $_.Zeile) -ForegroundColor Red }\n        } else {\n            Write-Host \"  Keine verdaechtigen Cheat-Begriffe in setupapi.dev.log.\" -ForegroundColor Green\n        }\n\n        Write-Host \"`n--- Installationen von anderen Laufwerken als C: (USB-Stick, zweite Platte) ---\" -ForegroundColor DarkGray\n        $laufwerk = @($laufwerk | Group-Object Zeile | ForEach-Object { $_.Group[0] })\n        if ($laufwerk.Count -gt 0) {\n            Write-Host (\"  [!] {0} Eintraege mit Dateien von fremden Laufwerken:\" -f $laufwerk.Count) -ForegroundColor Yellow\n            $laufwerk | Select-Object -First 30 | ForEach-Object { Write-Host (\"    [{0}] {1}\" -f $_.Zeit, $_.Zeile) -ForegroundColor Yellow }\n            Write-Host \"    Treiber-CDs und Downloads auf D: sind normal - unbekannte .dll/.cfg von einem Stick sind es nicht.\" -ForegroundColor DarkGray\n        } else {\n            Write-Host \"  Keine Installationen von fremden Laufwerken.\" -ForegroundColor Green\n        }\n        # Datei-Zeitstempel: frisch erstellt nach Windows-Installation?\n        $f = Get-Item $setupLog\n        $os2 = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue\n        if ($os2 -and $f.CreationTime -gt $os2.InstallDate.AddDays(7)) {\n            Write-Host \"  [!] setupapi.dev.log wurde deutlich nach Windows-Installation erstellt - moeglicherweise neu angelegt (Spurverwischung).\" -ForegroundColor Red\n        }\n    } else {\n        Write-Host \"  setupapi.dev.log fehlt - Datei koennte geloescht worden sein.\" -ForegroundColor Red\n    }\n}\n\n# ============================================================\n#  14 - Systemprozesse &amp; Registry-Injection-Vektoren\n# ============================================================\nfunction Invoke-SystemProcessCheck {\n    Write-Host \"`n=== Systemprozesse &amp; Injection-Vektoren ===\" -ForegroundColor Cyan\n    Write-Host \"(Prueft kritische Prozesse auf fremde Module + Registry-Einstiegspunkte)\" -ForegroundColor DarkGray\n\n    # --- 14a: Kritische Systemprozesse auf nicht-Microsoft-Module ---\n    Write-Host \"`n--- Fremde Module in Systemprozessen ---\" -ForegroundColor DarkGray\n    $kritisch = @('svchost','lsass','winlogon','services','spoolsv','wininit',\n                  'csrss','explorer','lsm','dllhost','dwm','ctfmon','taskhostw',\n                  'msdtc','audiodg','SearchIndexer','WmiPrvSE')\n\n    # Bekannte legitime Dritt-Hersteller die in Systemprozesse laden duerfen\n    $vertrauenswuerdig = @(\n        'Malwarebytes','NVIDIA','Adobe','Intel Corporation','Advanced Micro Devices',\n        'Logitech','Razer','SteelSeries','Corsair','ASUS','MSI','Gigabyte',\n        'Realtek','Qualcomm','Broadcom','Apple','Google','Dropbox','OneDrive'\n    )\n    # Geschuetzte Prozesse bei denen leere Module normal sind (PPL)\n    $geschuetzt = @('lsass','csrss','wininit','services','smss','MsMpEng')\n\n    $systemFund = $false\n    foreach ($pName in $kritisch) {\n        $procs = @(Get-Process -Name $pName -ErrorAction SilentlyContinue)\n        foreach ($proc in $procs) {\n            try {\n                $fremd   = @()\n                $pathlos = @()\n                $proc.Modules | ForEach-Object {\n                    # Nur Module MIT Namen aber OHNE Pfad = Reflective Injection Kandidat\n                    # Leere Eintraege ohne Namen = Enumerierungs-Artefakt, kein Fund\n                    if ($_.ModuleName -and -not $_.FileName) {\n                        if ($geschuetzt -notcontains $pName) {\n                            $pathlos += $_.ModuleName\n                        }\n                        return\n                    }\n                    if (-not $_.FileName) { return }\n\n                    $sig = Get-AuthenticodeSignature $_.FileName -ErrorAction SilentlyContinue\n                    $istMS = $sig -and $sig.Status -eq 'Valid' -and\n                             $sig.SignerCertificate -and\n                             $sig.SignerCertificate.Subject -match '(?i)Microsoft'\n                    if (-not $istMS) {\n                        $status = if ($sig) { $sig.Status } else { 'Unbekannt' }\n                        $sign   = if ($sig -and $sig.SignerCertificate) {\n                            $sig.SignerCertificate.Subject -replace '^(?:.*?,\\s*)?CN=(?:\"([^\"]+)\"|([^,]+)).*$','$1$2'\n                        } else { 'Nicht signiert' }\n                        # Bekannte legitime Hersteller: grau, nicht rot\n                        $istBekannt = $vertrauenswuerdig | Where-Object { $sign -match [regex]::Escape($_) }\n                        $fremd += [PSCustomObject]@{\n                            Modul    = $_.ModuleName\n                            Pfad     = $_.FileName\n                            Sig      = $status\n                            Signierer= $sign\n                            Bekannt  = [bool]$istBekannt\n                        }\n                    }\n                }\n\n                # Nur ausgeben wenn wirklich verdaechtig (unbekannt/unsigniert ODER pathlos)\n                $echteWarnungen = @($fremd | Where-Object { -not $_.Bekannt -or $_.Sig -ne 'Valid' })\n                $bekannteListe  = @($fremd | Where-Object { $_.Bekannt -and $_.Sig -eq 'Valid' })\n\n                if ($echteWarnungen.Count -gt 0 -or $pathlos.Count -gt 0) {\n                    Write-Host (\"`n  [{0}] PID {1}\" -f $proc.Name, $proc.Id) -ForegroundColor Red\n                    $systemFund = $true\n                    foreach ($m in $echteWarnungen) {\n                        $col = if ($m.Sig -ne 'Valid') { 'Red' } else { 'Yellow' }\n                        Write-Host (\"    [!] {0}\" -f $m.Modul) -ForegroundColor $col\n                        Write-Host (\"        Pfad     : {0}\" -f $m.Pfad) -ForegroundColor $col\n                        Write-Host (\"        Sig      : {0} | {1}\" -f $m.Sig, $m.Signierer) -ForegroundColor $col\n                    }\n                    foreach ($m in $pathlos) {\n                        Write-Host (\"    [!!!] Modul ohne Dateipfad: $m (Reflective Injection?)\" ) -ForegroundColor Red\n                    }\n                }\n                if ($bekannteListe.Count -gt 0) {\n                    Write-Host (\"`n  [{0}] PID {1} - bekannte Dritt-Software ({2} Module):\" -f $proc.Name, $proc.Id, $bekannteListe.Count) -ForegroundColor DarkGray\n                    $bekannteListe | ForEach-Object { Write-Host (\"    $($_.Modul) | $($_.Signierer)\") -ForegroundColor DarkGray }\n                }\n            } catch {\n                if ($geschuetzt -notcontains $pName) {\n                    Write-Host (\"  [{0}] PID {1} - Zugriff verweigert\" -f $pName, $proc.Id) -ForegroundColor DarkGray\n                }\n            }\n        }\n    }\n    if (-not $systemFund) {\n        Write-Host \"Alle geprueften Systemprozesse: nur Microsoft-signierte Module.\" -ForegroundColor Green\n    }\n\n    # --- 14b: AppInit_DLLs ---\n    Write-Host \"`n--- AppInit_DLLs (laedt in JEDEN Prozess mit user32.dll) ---\" -ForegroundColor DarkGray\n    $appInitKeys = @(\n        'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows',\n        'HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows'\n    )\n    foreach ($k in $appInitKeys) {\n        if (Test-Path $k) {\n            $val = (Get-ItemProperty $k -ErrorAction SilentlyContinue).AppInit_DLLs\n            $load = (Get-ItemProperty $k -ErrorAction SilentlyContinue).LoadAppInit_DLLs\n            if ($val -and $val.Trim()) {\n                Write-Host \"  [!!!] AppInit_DLLs GESETZT: $val\" -ForegroundColor Red\n                Write-Host \"        LoadAppInit_DLLs: $load\" -ForegroundColor Red\n            } else {\n                Write-Host \"  $k : Leer (gut).\" -ForegroundColor Green\n            }\n        }\n    }\n\n    # --- 14c: Winlogon Injection (Shell, Userinit, Notify) ---\n    Write-Host \"`n--- Winlogon Injection-Vektoren ---\" -ForegroundColor DarkGray\n    $wlKey = 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon'\n    if (Test-Path $wlKey) {\n        $wl = Get-ItemProperty $wlKey -ErrorAction SilentlyContinue\n        # Shell sollte nur explorer.exe sein\n        if ($wl.Shell -and $wl.Shell -notmatch '^explorer\\.exe$') {\n            Write-Host \"  [!] Shell != explorer.exe: $($wl.Shell)\" -ForegroundColor Red\n        } else { Write-Host \"  Shell     : $($wl.Shell) (OK)\" -ForegroundColor Green }\n        # Userinit\n        if ($wl.Userinit -and $wl.Userinit -notmatch 'userinit\\.exe') {\n            Write-Host \"  [!] Userinit auffaellig: $($wl.Userinit)\" -ForegroundColor Red\n        } else { Write-Host \"  Userinit  : $($wl.Userinit) (OK)\" -ForegroundColor Green }\n    }\n\n    # --- 14d: LSA Security Packages ---\n    Write-Host \"`n--- LSA Authentication &amp; Security Packages ---\" -ForegroundColor DarkGray\n    $lsaKey = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa'\n    if (Test-Path $lsaKey) {\n        $lsa = Get-ItemProperty $lsaKey -ErrorAction SilentlyContinue\n        $authPkg = $lsa.'Authentication Packages'\n        $secPkg  = $lsa.'Security Packages'\n        $notifPkg= $lsa.'Notification Packages'\n        $standard = @('msv1_0','','scecli')\n        foreach ($pkg in $authPkg) {\n            if ($pkg -and $standard -notcontains $pkg.ToLower()) {\n                Write-Host \"  [!] Unbekanntes Auth-Package: $pkg\" -ForegroundColor Red\n            }\n        }\n        Write-Host \"  Auth-Packages  : $($authPkg -join ', ')\"\n        Write-Host \"  Sec-Packages   : $($secPkg -join ', ')\"\n        Write-Host \"  Notify-Packages: $($notifPkg -join ', ')\"\n    }\n\n    # --- 14e: Dienste mit DLL in ungewoehnlichem Pfad ---\n    Write-Host \"`n--- Dienst-DLLs ausserhalb von System32/SysWOW64 ---\" -ForegroundColor DarkGray\n    $dienste = Get-ItemProperty 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\*' -ErrorAction SilentlyContinue |\n        Where-Object { $_.ImagePath -like '*svchost*' }\n    $fremdDienst = $false\n    foreach ($svc in $dienste) {\n        $param = $svc.PSPath -replace 'Registry::',''\n        $paramKey = $param + '\\Parameters'\n        if (Test-Path \"Registry::$paramKey\") {\n            $dll = (Get-ItemProperty \"Registry::$paramKey\" -ErrorAction SilentlyContinue).ServiceDll\n            if ($dll -and $dll -notmatch '(?i)^(%SystemRoot%|C:\\\\Windows)\\\\(System32|SysWOW64)\\\\') {\n                Write-Host (\"  [!] Dienst '{0}' laedt DLL aus ungewoehnlichem Pfad:\" -f $svc.PSChildName) -ForegroundColor Red\n                Write-Host (\"      $dll\") -ForegroundColor Red\n                $sig = Get-AuthenticodeSignature ($dll -replace '%SystemRoot%',$env:SystemRoot) -ErrorAction SilentlyContinue\n                if ($sig) { Write-Host (\"      Sig: {0}\" -f $sig.Status) -ForegroundColor Red }\n                $fremdDienst = $true\n            }\n        }\n    }\n    if (-not $fremdDienst) { Write-Host \"  Alle Dienst-DLLs in erwarteten Systempfaden.\" -ForegroundColor Green }\n\n    Write-Host \"`nHinweis: lsass-Module sind ohne SeDebugPrivilege oft nicht lesbar.\" -ForegroundColor DarkGray\n    Write-Host \"Fuer Kernel-Level-Injection (DKOM, direkte Speichermanipulation):\" -ForegroundColor DarkGray\n    Write-Host \"PowerShell reicht nicht aus - da braucht es WinPmem oder Volatility.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  15 - HVCI / Memory Integrity &amp; Code Integrity Treiber-Check\n# ============================================================\nfunction Invoke-HVCICheck {\n    Write-Host \"`n=== HVCI / Memory Integrity &amp; Inkompatible Treiber ===\" -ForegroundColor Cyan\n    Write-Host \"(Deaktivierte Speicherintegritaet + geblockte Kernel-Treiber = DMA-Indiz)\" -ForegroundColor DarkGray\n\n    # --- 15a: HVCI-Status ---\n    Write-Host \"`n--- Memory Integrity (HVCI) Status ---\" -ForegroundColor DarkGray\n    $hvciKey = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\DeviceGuard\\Scenarios\\HypervisorEnforcedCodeIntegrity'\n    $vbsKey  = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\DeviceGuard'\n    $hvciAktiv = $false\n\n    if (Test-Path $hvciKey) {\n        $hvci = Get-ItemProperty $hvciKey -ErrorAction SilentlyContinue\n        $hvciAktiv = $hvci.Enabled -eq 1\n        $col = if ($hvciAktiv) { 'Green' } else { 'Red' }\n        Write-Host (\"  HVCI (Speicherintegritaet) : {0}\" -f $(if($hvciAktiv){'AKTIV'}else{'DEAKTIVIERT [!]'})) -ForegroundColor $col\n        if (-not $hvciAktiv) {\n            Write-Host \"  --&gt; Inkompatible Treiber koennen in den Kernel geladen werden.\" -ForegroundColor Yellow\n            Write-Host \"      DMA-Karten mit schwach signierten Treibern nutzen genau das.\" -ForegroundColor Yellow\n            Write-Host \"  Manuell pruefen: Windows-Sicherheit \u2192 Geraetesicherheit \u2192 Kernisolierung\" -ForegroundColor DarkGray\n        }\n    } else {\n        Write-Host \"  HVCI-Key nicht gefunden - VBS moeglicherweise nicht konfiguriert.\" -ForegroundColor Yellow\n    }\n\n    if (Test-Path $vbsKey) {\n        $vbs = Get-ItemProperty $vbsKey -ErrorAction SilentlyContinue\n        $vbsAktiv = $vbs.EnableVirtualizationBasedSecurity -eq 1\n        Write-Host (\"  VBS (Virt. Based Security)  : {0}\" -f $(if($vbsAktiv){'AKTIV'}else{'DEAKTIVIERT'})) -ForegroundColor $(if($vbsAktiv){'Green'}else{'Yellow'})\n    }\n\n    # Secure Boot\n    $sb = $null\n    try {\n        $sb = Confirm-SecureBootUEFI -ErrorAction Stop\n        Write-Host (\"  Secure Boot                 : {0}\" -f $(if($sb){'AKTIV'}else{'DEAKTIVIERT [!]'})) -ForegroundColor $(if($sb){'Green'}else{'Red'})\n    } catch {\n        Write-Host \"  Secure Boot                 : Nicht abfragbar (Legacy BIOS oder kein UEFI)\" -ForegroundColor Yellow\n    }\n\n    # --- 15b: Code Integrity Log - geblockte Treiber ---\n    Write-Host \"`n--- Code Integrity: geblockte / abgelehnte Treiber ---\" -ForegroundColor DarkGray\n    Write-Host \"(Event 3033 = geblockt | 3034 = Boot-Treiber | 3076 = Audit | 3077 = Prozess)\" -ForegroundColor DarkGray\n\n    $ciEvents = @(Get-WinEvent -FilterHashtable @{\n        LogName = 'Microsoft-Windows-CodeIntegrity/Operational'\n        Id      = 3033, 3034, 3076, 3077\n    } -MaxEvents 100 -ErrorAction SilentlyContinue)\n\n    # Bekannte legitime Security-DLLs die bei HVCI haeufig 3033 ausloesen\n    $ciWhitelist = @('mbae64\\.dll','mbae\\.dll','mbamswissarmy','MBAMSwissArmy',\n                     'mbamsi64\\.dll','mbamsi\\.dll','mbamupdatetool',\n                     'hmpalert','hmpalert64','CrExigency','sophos','mbae')\n\n    if ($ciEvents.Count -gt 0) {\n        $ciGefiltert = @($ciEvents | Where-Object {\n            $msg = $_.Message\n            -not ($ciWhitelist | Where-Object { $msg -match $_ })\n        })\n        $ciGefiltert_kurz = @($ciEvents | Where-Object {\n            $msg = $_.Message\n            ($ciWhitelist | Where-Object { $msg -match $_ })\n        })\n\n        if ($ciGefiltert_kurz.Count -gt 0) {\n            Write-Host \"  (Herausgefiltert: $($ciGefiltert_kurz.Count)x bekannte Security-Software wie Malwarebytes Anti-Exploit)\" -ForegroundColor DarkGray\n        }\n\n        if ($ciGefiltert.Count -gt 0) {\n            Write-Host \"  $($ciGefiltert.Count) relevante Ereignisse:\" -ForegroundColor Red\n            $ciGefiltert | Sort-Object TimeCreated -Descending | Select-Object -First 20 | ForEach-Object {\n                $eid = $_.Id\n                $col = if ($eid -in @(3033,3034)) { 'Red' } else { 'Yellow' }\n                $msg = ($_.Message -replace '\\s+',' ')\n                $datei = if ($msg -match '\\\\([^\\\\]+\\.sys|[^\\\\]+\\.dll)') { $matches[1] } else { '' }\n                Write-Host (\"`n  [{0}] EID {1}\" -f $_.TimeCreated, $eid) -ForegroundColor $col\n                if ($datei) { Write-Host (\"  Treiber : {0}\" -f $datei) -ForegroundColor $col }\n                Write-Host (\"  Details : {0}...\" -f $msg.Substring(0, [Math]::Min(160, $msg.Length))) -ForegroundColor DarkGray\n            }\n        } else {\n            Write-Host \"  Keine unbekannten geblockten Treiber - nur bekannte Security-Software.\" -ForegroundColor Green\n        }\n    } else {\n        Write-Host \"  Keine geblockten Treiber im Code Integrity Log.\" -ForegroundColor Green\n        if ($hvciAktiv) {\n            Write-Host \"  (HVCI aktiv = Treiber werden gar nicht erst geladen - das ist gut)\" -ForegroundColor DarkGray\n        }\n    }\n\n    # --- 15c: bcdedit - Testsigning und Integritaets-Bypass ---\n    Write-Host \"`n--- Boot-Konfiguration: Testsigning &amp; Integrity-Checks ---\" -ForegroundColor DarkGray\n    $bcd = &amp; bcdedit /enum 2&gt;&amp;1 | Out-String\n    $testsigning = $bcd -match 'testsigning\\s+yes'\n    $nointegrity = $bcd -match 'nointegritychecks\\s+yes'\n    $dbgmode     = $bcd -match 'debug\\s+yes'\n\n    Write-Host (\"  Testsigning        : {0}\" -f $(if($testsigning){'[!!!] AKTIV - unsignierte Treiber erlaubt!'}else{'Deaktiviert (OK)'})) -ForegroundColor $(if($testsigning){'Red'}else{'Green'})\n    Write-Host (\"  NoIntegrityChecks  : {0}\" -f $(if($nointegrity){'[!!!] AKTIV - Integritaetspruefung umgangen!'}else{'Deaktiviert (OK)'})) -ForegroundColor $(if($nointegrity){'Red'}else{'Green'})\n    Write-Host (\"  Debug-Modus        : {0}\" -f $(if($dbgmode){'[!] Aktiv'}else{'Deaktiviert (OK)'})) -ForegroundColor $(if($dbgmode){'Yellow'}else{'Green'})\n\n    if ($testsigning -or $nointegrity) {\n        Write-Host \"`n  [!!!] Treibersignaturen sind aktiv umgangen.\" -ForegroundColor Red\n        Write-Host \"        Jeder beliebige unsignierte Kernel-Treiber kann geladen werden.\" -ForegroundColor Red\n        Write-Host \"        Das ist eine Grundvoraussetzung vieler DMA- und Cheat-Treiber.\" -ForegroundColor Red\n    }\n\n    # --- 15d: Inkompatible Treiber aus pnputil (ergaenzt HVCI-Liste) ---\n    Write-Host \"`n--- Installierte Treiber ohne gueltige WHQL-Signatur ---\" -ForegroundColor DarkGray\n    Write-Host \"(Diese wuerden die HVCI-Aktivierung verhindern)\" -ForegroundColor DarkGray\n    try {\n        $pnpOut = &amp; pnputil /enum-drivers 2&gt;&amp;1 | Out-String\n        $bloecke = $pnpOut -split '(?=Veroeffentlichter Name|Published Name)'\n        $verdaechtig = @($bloecke | Where-Object {\n            $_ -match 'Nicht signiert|Not Signed|Unsigned' -or\n            ($_ -match '(Signierer|Signer)\\s*:' -and $_ -notmatch '(?i)Microsoft|WHQL')\n        })\n        if ($verdaechtig.Count -gt 0) {\n            Write-Host \"  [!] $($verdaechtig.Count) potenziell inkompatible Treiber:\" -ForegroundColor Red\n            $verdaechtig | Select-Object -First 10 | ForEach-Object {\n                $name = if ($_ -match 'oem\\d+\\.inf') { $matches[0] } else { '' }\n                $pub  = if ($_ -match '(?:Herausgeber|Publisher)\\s*:\\s*(.+)') { $matches[1].Trim() } else { '' }\n                if ($name) { Write-Host (\"  {0} | {1}\" -f $name, $pub) -ForegroundColor Yellow }\n            }\n        } else {\n            Write-Host \"  Keine offensichtlich unsignierten Treiber gefunden.\" -ForegroundColor Green\n        }\n    } catch {\n        Write-Host \"  pnputil nicht verfuegbar.\" -ForegroundColor DarkGray\n    }\n\n    # --- 15e: DMA-Schutz - IOMMU / VT-d, Windows-DMA-Schutz, Aenderungszeitpunkte ---\n    Write-Host \"`n--- DMA-Schutz: IOMMU (AMD) / VT-d (Intel) ---\" -ForegroundColor DarkGray\n    Write-Host \"(Viele DMA-Karten verlangen: IOMMU bzw. VT-d im BIOS AUS + Kernisolierung AUS)\" -ForegroundColor DarkGray\n\n    Add-Type -ErrorAction SilentlyContinue -TypeDefinition @\"\nusing System;\nusing System.Text;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\npublic static class CtcFw {\n    [DllImport(\"kernel32.dll\", SetLastError = true)]\n    static extern uint EnumSystemFirmwareTables(uint provider, byte[] buffer, uint size);\n    public static string[] Acpi() {\n        uint prov = 0x41435049;                       // 'ACPI'\n        uint n = EnumSystemFirmwareTables(prov, null, 0);\n        if (n == 0) return new string[0];\n        byte[] b = new byte[n];\n        EnumSystemFirmwareTables(prov, b, n);\n        var l = new List();\n        for (int i = 0; i + 4 &lt;= n; i += 4) l.Add(Encoding.ASCII.GetString(b, i, 4));\n        return l.ToArray();\n    }\n}\n\"@\n    $sigRQ3 = '[DllImport(\"advapi32.dll\")]public static extern int RegQueryInfoKey(Microsoft.Win32.SafeHandles.SafeRegistryHandle h,System.Text.StringBuilder a,ref int b,int c,ref int d,ref int e,ref int f,ref int g,ref int i,ref int j,ref int k,ref long l);'\n    Add-Type -MemberDefinition $sigRQ3 -Name RK3 -Namespace W3 -ErrorAction SilentlyContinue\n    $keyZeit = {\n        param($pfad)\n        try {\n            $k = Get-Item $pfad -ErrorAction Stop\n            $t = 0L; $z = 0; $n = New-Object Text.StringBuilder 1024\n            [void][W3.RK3]::RegQueryInfoKey($k.Handle,$n,[ref]$z,0,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$t)\n            [DateTime]::FromFileTime($t)\n        } catch { $null }\n    }\n\n    $cpuHersteller = [string](Get-CimInstance Win32_Processor -ErrorAction SilentlyContinue | Select-Object -First 1).Manufacturer\n    $istAmd   = $cpuHersteller -match '(?i)AMD'\n    $iommuName = if ($istAmd) { 'IOMMU (AMD-Vi)' } else { 'VT-d (Intel)' }\n    $tabellen = @()\n    try { $tabellen = @([CtcFw]::Acpi()) } catch {}\n    $iommuAn = $null\n    if ($tabellen.Count -gt 0) {\n        $iommuAn = [bool]($tabellen | Where-Object { $_ -match '^(DMAR|RAMD|IVRS|SRVI)$' })\n        $col = if ($iommuAn) { 'Green' } else { 'Red' }\n        $txt = if ($iommuAn) { 'AN (Firmware meldet IOMMU-Tabelle)' } else { 'AUS [!] - keine DMAR/IVRS-Tabelle, im BIOS deaktiviert' }\n        Write-Host (\"  {0,-27} : {1}\" -f $iommuName, $txt) -ForegroundColor $col\n    } else {\n        Write-Host (\"  {0,-27} : nicht ermittelbar (Firmware-Tabellen nicht lesbar)\" -f $iommuName) -ForegroundColor Yellow\n    }\n\n    $dg = Get-CimInstance -Namespace 'root\\Microsoft\\Windows\\DeviceGuard' -ClassName Win32_DeviceGuard -ErrorAction SilentlyContinue\n    $dmaSchutz = $null\n    if ($dg) {\n        $dmaSchutz = @($dg.AvailableSecurityProperties) -contains 3\n        Write-Host (\"  Windows DMA-Schutz verfuegbar: {0}\" -f $(if ($dmaSchutz) { 'JA' } else { 'NEIN [!]' })) -ForegroundColor $(if ($dmaSchutz) { 'Green' } else { 'Yellow' })\n        $vbsLauf = switch ([int]$dg.VirtualizationBasedSecurityStatus) { 2 { 'laeuft' } 1 { 'konfiguriert, laeuft NICHT' } default { 'aus' } }\n        $hvciLauf = @($dg.SecurityServicesRunning) -contains 2\n        Write-Host (\"  VBS tatsaechlich           : {0}\" -f $vbsLauf) -ForegroundColor $(if ($vbsLauf -eq 'laeuft') { 'Green' } else { 'Yellow' })\n        Write-Host (\"  HVCI tatsaechlich aktiv    : {0}\" -f $(if ($hvciLauf) { 'JA' } else { 'NEIN' })) -ForegroundColor $(if ($hvciLauf) { 'Green' } else { 'Yellow' })\n    }\n    $hyp = [bool](Get-CimInstance Win32_ComputerSystem -ErrorAction SilentlyContinue).HypervisorPresent\n    Write-Host (\"  Hypervisor aktiv           : {0}\" -f $(if ($hyp) { 'JA' } else { 'NEIN' })) -ForegroundColor DarkGray\n\n    # Wann wurden Speicherintegritaet / VBS zuletzt umgestellt?\n    $zHvci = &amp; $keyZeit 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\DeviceGuard\\Scenarios\\HypervisorEnforcedCodeIntegrity'\n    $zVbs  = &amp; $keyZeit 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\DeviceGuard'\n    $osInst = (Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue).InstallDate\n    foreach ($e in @(@{ N='Speicherintegritaet (HVCI)'; Z=$zHvci }, @{ N='VBS / Device Guard'; Z=$zVbs })) {\n        if (-not $e.Z) { continue }\n        $neu = $osInst -and $e.Z -gt $osInst.AddHours(2)\n        $col = if ($neu -and -not $hvciAktiv) { 'Yellow' } else { 'DarkGray' }\n        Write-Host (\"  {0,-27} zuletzt geaendert: {1}{2}\" -f $e.N, $e.Z, $(if ($neu) { '  (nach der Windows-Installation umgestellt)' } else { '' })) -ForegroundColor $col\n    }\n    if ($osInst) { Write-Host (\"  Windows installiert am     : {0}\" -f $osInst) -ForegroundColor DarkGray }\n\n    # Gesamtbild\n    $faktoren = @()\n    if ($iommuAn -eq $false) { $faktoren += \"$iommuName aus\" }\n    if (-not $hvciAktiv)     { $faktoren += 'Speicherintegritaet aus' }\n    if ($sb -eq $false)      { $faktoren += 'Secure Boot aus' }\n    if ($dg -and $dmaSchutz -eq $false -and $iommuAn -ne $false) { $faktoren += 'Windows-DMA-Schutz nicht verfuegbar' }\n    Write-Host \"\"\n    if ($iommuAn -eq $false -and -not $hvciAktiv) {\n        Write-Host (\"  [!!!] TYPISCHES DMA-PROFIL: {0}\" -f ($faktoren -join ' + ')) -ForegroundColor Red\n        Write-Host \"        Genau diese Einstellungen verlangen die meisten DMA-Karten. Mit Punkt 3 (Steckkarten) und 17 (Fuser) abgleichen.\" -ForegroundColor Red\n    } elseif ($faktoren.Count -gt 0) {\n        Write-Host (\"  [!] Abgeschwaechter Schutz: {0}\" -f ($faktoren -join ' + ')) -ForegroundColor Yellow\n        Write-Host \"      Allein kein Beweis - viele Gaming-PCs haben das ab Werk. Zusammen mit Hardware-Spuren werten.\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"  DMA-Schutz vollstaendig aktiv - eine DMA-Karte haette es hier deutlich schwerer.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`nFazit-Hilfe:\" -ForegroundColor DarkGray\n    Write-Host \"  IOMMU/VT-d AUS + Speicherintegritaet AUS = typisches DMA-Profil\" -ForegroundColor DarkGray\n    Write-Host \"  Testsigning=Ja + unbekannter Treiber = starker DMA-Hinweis\" -ForegroundColor DarkGray\n    Write-Host \"  HVCI deaktiviert + CI-Events = Treiber wurde installiert und verweigert\" -ForegroundColor DarkGray\n    Write-Host \"  Gut konfigurierte DMA-Karten (echt signiert) erscheinen NICHT im CI-Log\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  16 - System32 Fremdkoerper &amp; Typosquatting-Check\n# ============================================================\nfunction Invoke-System32Check {\n    param([string]$Umfang)\n    Write-Host \"`n=== Signatur-Scan jeder DLL, EXE und SYS ===\" -ForegroundColor Cyan\n    Write-Host \"  [1] Systemordner (System32/SysWOW64 inkl. Unterordner) - schnell\" -ForegroundColor White\n    Write-Host \"  [2] Ganzes Windows-Laufwerk (Standard)\" -ForegroundColor White\n    Write-Host \"  [3] Alle Laufwerke inkl. zweiter Platten und USB-Sticks\" -ForegroundColor White\n    if (-not $umfang) { $umfang = (Read-Host \"Umfang (Enter = 2)\").Trim() } else { Write-Host \"Umfang (automatisch): $umfang\" -ForegroundColor DarkGray }\n    if ($umfang -notin @('1','2','3')) { $umfang = '2' }\n\n    $uhr = [System.Diagnostics.Stopwatch]::StartNew()\n    $bekannteSigner = '(?i)NVIDIA|Intel|Advanced Micro|AMD|Realtek|Qualcomm|Broadcom|Logitech|Razer|Corsair|Elgato|Malwarebytes|ASUSTeK|Micro-Star|Gigabyte|MediaTek|Synaptics|Dolby|Waves|Nahimic|Creative|SteelSeries|Adobe|Google|Mozilla|Oracle|VMware|Valve|Epic Games|Electronic Arts|Ubisoft|Rockstar|Discord|Spotify|Zoom|Dropbox|Apple|Python Software|OpenJS|Node\\.js|JetBrains|Autodesk|Cisco|Citrix|Overwolf|Riot|Blizzard|Microsoft|^\\.NET|Windows Phone|Json\\.NET|Prism|Medal|Ferox Games|The Qt Company|OBS Project|TeamSpeak|BattlEye|KRAFTON|PUBG|Bluehole|Unity Technologies|Skutta|Winsider|ZimTech|Kilonova|MUSIC Tribe|Zhongshan Eurotec|REALiX|Pocket Soft|WireGuard|TC-Helicon|Brave Software|Gen Digital|NortonLifeLock|Symantec|Avast|AVG Technologies|Now\\.gg|BlueStack|NetEase|Netease|VOICEMOD|Roblox|Bitdefender|ESET|Kaspersky'\n    $fernwartung    = '(?i)PURSLANE|RustDesk|AnyDesk|TeamViewer|Splashtop|Parsec|UltraViewer|Ammyy|DWService'\n    $pruefTools     = '(?i)Inspect Element'                       # Echo\n    $makroRx        = '(?i)\\\\[^\\\\]*(autoclick|auto-click|tinytask|macro ?recorder|macrorecorder|pulover|jitbit|mouse ?recorder|clickermann|opautoclicker|gs ?auto ?clicker)[^\\\\]*$|\\.ahk$'\n    $phantomRx      = '(?i)\\\\WptsExtensions\\.dll$|\\\\(cryptbase2|version2|cryptsp2)\\.dll$|\\\\wbem\\\\(WaaSMedicSvc|wlbsctrl)\\.dll$'\n    $sysDllName     = '(?i)\\\\(version|winhttp|wininet|dbghelp|dbgcore|uxtheme|dwmapi|cryptbase|cryptsp|winmm|userenv|profapi|wtsapi32|iphlpapi|netapi32|mpr|secur32|sspicli|wldp|amsi|msimg32|oleacc|propsys|edputil|winsta|dsound|hid|setupapi|cfgmgr32|wer|dbgeng|srvcli|netutils|ntmarta|mscms|winspool)\\.dll$'\n    $auslassen      = '(?i)^[A-Z]:\\\\Windows\\\\(WinSxS|SystemApps|assembly\\\\NativeImages_[^\\\\]*|Installer\\\\\\$PatchCache\\$)(\\\\|$)|^[A-Z]:\\\\Windows\\\\Installer\\\\\\{[0-9A-Fa-f-]+\\}(\\\\|$)|\\\\Microsoft\\\\NetFramework\\\\BreadcrumbStore(\\\\|$)|\\\\WindowsApps(\\\\|$)|\\\\System Volume Information(\\\\|$)'\n    $kritischeDLLs  = @('ntdll','kernel32','kernelbase','user32','advapi32','rpcrt4','msvcrt','sechost','combase','ucrtbase',\n                        'win32u','gdi32','ole32','oleaut32','shell32','shlwapi','wininet','ws2_32','crypt32','bcrypt','ncrypt',\n                        'lsasrv','wintrust','wldp','amsi','version','winhttp','dbghelp','cryptbase','cryptsp')\n    $osInstall  = (Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue).InstallDate\n    $sysLw      = $env:SystemDrive.ToUpper()\n    $grenzeNeu  = (Get-Date).AddDays(-14)\n\n    $wurzeln = switch ($umfang) {\n        '1' { @(\"$env:SystemRoot\\System32\", \"$env:SystemRoot\\SysWOW64\") }\n        '2' { @(\"$sysLw\\\") }\n        '3' { @([System.IO.DriveInfo]::GetDrives() | Where-Object { $_.IsReady -and $_.DriveType -in 'Fixed','Removable' } | ForEach-Object { $_.RootDirectory.FullName }) }\n    }\n    Write-Host (\"  Umfang: {0}\" -f ($wurzeln -join ', ')) -ForegroundColor DarkGray\n\n    # --- 1) Alle DLLs sammeln (rekursiv, ohne Verknuepfungen, Ordner ohne Zugriff merken) ---\n    Write-Host \"  Sammle Dateien...\" -ForegroundColor DarkGray\n    $dateien      = New-Object System.Collections.Generic.List[string]\n    $ordnerFehler = New-Object System.Collections.Generic.List[string]\n    $ausgelassenN = 0\n    $stapel = New-Object System.Collections.Generic.Stack[string]\n    foreach ($w in $wurzeln) { if (Test-Path $w) { $stapel.Push($w) } }\n    while ($stapel.Count -gt 0) {\n        $d = $stapel.Pop()\n        if ($d -match $auslassen) { $ausgelassenN++; continue }\n        try {\n            foreach ($muster in @('*.dll','*.exe','*.sys')) { foreach ($f in [System.IO.Directory]::EnumerateFiles($d, $muster)) { $dateien.Add($f) } }\n            foreach ($s in [System.IO.Directory]::EnumerateDirectories($d)) {\n                try {\n                    if (([System.IO.File]::GetAttributes($s) -band [System.IO.FileAttributes]::ReparsePoint) -eq 0) { $stapel.Push($s) }\n                } catch { $ordnerFehler.Add($s) }\n            }\n        } catch { $ordnerFehler.Add($d) }\n        if ($dateien.Count % 5000 -eq 0 -and $dateien.Count -gt 0) {\n            Write-Progress -Activity 'CTC Signatur-Scan' -Status (\"Sammle ... {0:N0} DLLs\" -f $dateien.Count)\n        }\n    }\n    Write-Host (\"  {0:N0} Dateien gefunden (DLL/EXE/SYS), pruefe Signaturen parallel...\" -f $dateien.Count) -ForegroundColor DarkGray\n\n    # --- 2) Tiefenanalyse vorbereiten (C#, laeuft in allen Threads) ---\n    Add-Type -ErrorAction SilentlyContinue -TypeDefinition @\"\nusing System;\nusing System.IO;\nusing System.Text;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\npublic static class CtcTief3 {\n    static double Entropie(byte[] b, int off, int len) {\n        int[] c = new int[256];\n        for (int i = off; i &lt; off + len; i++) c[b[i]]++;\n        double e = 0;\n        foreach (int n in c) { if (n == 0) continue; double p = (double)n / len; e -= p * Math.Log(p, 2); }\n        return e;\n    }\n    static readonly string[] Schreibend = { \"writeprocessmemory\", \"ntwritevirtualmemory\", \"createremotethread\", \"createremotethreadex\",\n                                            \"ntcreatethreadex\", \"rtlcreateuserthread\", \"ntqueueapcthread\", \"mmcopyvirtualmemory\" };\n    const string ZielRx = @\"FiveM_[A-Za-z0-9_]*GTAProcess|FiveM_b\\d{4}|FiveM_GameProcess|GTA5(_Enhanced)?\\.exe|RedM_[A-Za-z]*Process|CitizenFX|citizen-scripting|FiveM\\.exe\";\n    public static string Analyse(string pfad, string apiRx, string kwRx, string domRx) {\n        var g = new List();\n        try {\n            var fi = new FileInfo(pfad);\n            if (fi.Length &lt; 64) return \"\";\n            if (fi.Length &gt; 64L * 1024 * 1024) return \"zu gross fuer Tiefenanalyse (ueber 64 MB)\";\n            byte[] b;\n            using (var fs = new FileStream(pfad, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) {\n                b = new byte[fs.Length]; int gelesen = 0;\n                while (gelesen &lt; b.Length) { int n = fs.Read(b, gelesen, b.Length - gelesen); if (n &lt;= 0) break; gelesen += n; }\n            }\n            // PE-Sektionen\n            if (b[0] == 0x4D &amp;&amp; b[1] == 0x5A) {\n                int pe = BitConverter.ToInt32(b, 0x3C);\n                if (pe &gt; 0 &amp;&amp; pe &lt; b.Length - 248 &amp;&amp; b[pe] == 0x50 &amp;&amp; b[pe + 1] == 0x45 &amp;&amp; b[pe + 2] == 0 &amp;&amp; b[pe + 3] == 0) {\n                    int nsec = BitConverter.ToUInt16(b, pe + 6);\n                    int opt  = BitConverter.ToUInt16(b, pe + 20);\n                    int sec  = pe + 24 + opt;\n                    for (int i = 0; i &lt; Math.Min(nsec, 96); i++) {\n                        int o = sec + i * 40; if (o + 40 &gt; b.Length) break;\n                        string name = Encoding.ASCII.GetString(b, o, 8).TrimEnd('\\0');\n                        uint rawSize = BitConverter.ToUInt32(b, o + 16), rawPtr = BitConverter.ToUInt32(b, o + 20), ch = BitConverter.ToUInt32(b, o + 36);\n                        bool x = (ch &amp; 0x20000000) != 0, w = (ch &amp; 0x80000000) != 0;\n                        if (Regex.IsMatch(name, @\"^UPX\\d$\", RegexOptions.IgnoreCase))\n                            g.Add(\"UPX-gepackt (\" + name + \")\");\n                        else if (Regex.IsMatch(name, @\"^(\\.vmp\\d|\\.themida|\\.winlice|\\.enigma\\d|\\.aspack|\\.adata|\\.mpress\\d|\\.petite|pec\\d|\\.boom|\\.ropf|\\.vlizer)$\", RegexOptions.IgnoreCase))\n                            g.Add(\"Protector-Sektion \" + name);\n                        if (x &amp;&amp; w) g.Add(\"W+X-Sektion \" + name);\n                        if (x &amp;&amp; rawSize &gt; 4096 &amp;&amp; (long)rawPtr + rawSize &lt;= b.Length) {\n                            double e = Entropie(b, (int)rawPtr, (int)rawSize);\n                            if (e &gt; 7.2) g.Add(string.Format(\"Code-Sektion {0} verschluesselt/gepackt (Entropie {1:0.00})\", name, e));\n                        }\n                    }\n                }\n            }\n            string asc = Encoding.GetEncoding(28591).GetString(b);\n            string uni = Encoding.Unicode.GetString(b);\n            // Injection-Funktionen: mind. 2, davon mind. 1 schreibende/Remote-Thread-Funktion\n            var apis = new HashSet(StringComparer.OrdinalIgnoreCase);\n            foreach (Match m in Regex.Matches(asc, apiRx)) apis.Add(m.Value);\n            bool schreibt = false;\n            foreach (string a in apis) if (Array.IndexOf(Schreibend, a.ToLowerInvariant()) &gt;= 0) { schreibt = true; break; }\n            if (apis.Count &gt;= 2 &amp;&amp; schreibt) g.Add(\"Injection-APIs: \" + string.Join(\", \", apis));\n            // Externer Speicherleser (ESP/Radar/Aimbot ueber Eingaben): liest fremden Speicher, schreibt aber nicht\n            bool liest = apis.Contains(\"ReadProcessMemory\") || apis.Contains(\"NtReadVirtualMemory\");\n            if (liest &amp;&amp; !(apis.Count &gt;= 2 &amp;&amp; schreibt) &amp;&amp; Regex.IsMatch(asc, @\"\\bOpenProcess\\b\"))\n                g.Add(\"liest fremden Prozessspeicher (OpenProcess + ReadProcessMemory)\");\n            // Ziel-Spiel: Prozess- oder Modulnamen von FiveM/GTA/RedM im Code\n            Match z = Regex.Match(asc, ZielRx, RegexOptions.IgnoreCase);\n            if (!z.Success) z = Regex.Match(uni, ZielRx, RegexOptions.IgnoreCase);\n            if (z.Success) g.Add(\"Ziel-Spiel im Code: \" + z.Value);\n            // ImGui - Menue-Bibliothek fast aller Cheat-Overlays\n            if (Regex.IsMatch(asc, @\"imgui\\.ini|Dear ImGui|ImGuiContext|ImGui::\", RegexOptions.IgnoreCase))\n                g.Add(\"ImGui-Oberflaeche (typisch fuer Cheat-Menues/Overlays)\");\n            // Cheat-Begriffe im Code\n            var kw = new HashSet(StringComparer.OrdinalIgnoreCase);\n            foreach (Match m in Regex.Matches(asc, kwRx, RegexOptions.IgnoreCase)) kw.Add(m.Value.ToLowerInvariant());\n            foreach (Match m in Regex.Matches(uni, kwRx, RegexOptions.IgnoreCase)) kw.Add(m.Value.ToLowerInvariant());\n            if (kw.Count &gt; 0) g.Add(\"Cheat-Begriffe im Code: \" + string.Join(\", \", kw));\n            // Bekannte Cheat-Domains im Code\n            if (!string.IsNullOrEmpty(domRx)) {\n                Match d = Regex.Match(asc, domRx, RegexOptions.IgnoreCase);\n                if (!d.Success) d = Regex.Match(uni, domRx, RegexOptions.IgnoreCase);\n                if (d.Success) g.Add(\"CHEAT-DOMAIN im Code: \" + d.Value);\n            }\n            // Verdaechtiger Build-Pfad\n            Match pdb = Regex.Match(asc, @\"[A-Za-z]:\\\\[^\\x00-\\x1F\"\"&lt;&gt;|]{3,200}\\.pdb\", RegexOptions.IgnoreCase);\n            if (pdb.Success &amp;&amp; Regex.IsMatch(pdb.Value, @\"\\\\[^\\\\]*(cheat|hack|inject|bypass|spoof|aimbot|triggerbot|wallhack|mapper)[^\\\\]*\\\\|\\\\(esp|dma|loader|external|internal)\\\\\", RegexOptions.IgnoreCase))\n                g.Add(\"verdaechtiger Build-Pfad: \" + pdb.Value);\n        } catch { }\n        return string.Join(\" | \", g);\n    }\n}\n\"@\n    $apiRx = '\\b(VirtualAllocEx|WriteProcessMemory|CreateRemoteThreadEx|CreateRemoteThread|NtCreateThreadEx|RtlCreateUserThread|NtWriteVirtualMemory|NtQueueApcThread|QueueUserAPC|SetWindowsHookExA|SetWindowsHookExW|NtMapViewOfSection|ZwMapViewOfSection|MmCopyVirtualMemory|ReadProcessMemory|NtReadVirtualMemory)\\b'\n    $kwRx  = '\\b(aimbot|wallhack|triggerbot|silent_?aim|manual_?map(per)?|kdmapper|dll_?injector|hwid_?spoof(er)?|spoofer|esp_(box|name|line|skeleton|health)|cheat_?menu|lua_?executor|anti_?cheat_?bypass|ac_?bypass|no_?recoil|recoil_?control)\\b'\n    $domRx = if ($CheatDomains.Count -gt 0) { '(?= 5 neue DLLs im selben Ordner = Programm wurde installiert, nicht einzeln listen\n    $neuInstall = @()\n    $neuGruppen = @($prioritaet | Where-Object { $_.Rang -eq 6 } | Group-Object { Split-Path $_.R.Pfad -Parent } | Where-Object { $_.Count -ge 5 })\n    foreach ($g in $neuGruppen) {\n        $zeiten = @($g.Group | ForEach-Object { $_.R.Erstellt } | Sort-Object)\n        $neuInstall += [PSCustomObject]@{ Ordner=$g.Name; Anzahl=$g.Count; Zeit=$zeiten[0] }\n        foreach ($x in $g.Group) { $restlich += $x.R }\n    }\n    $neuOrdner = @{}; foreach ($g in $neuGruppen) { $neuOrdner[$g.Name] = $true }\n    $prioritaet = @($prioritaet | Where-Object { -not ($_.Rang -eq 6 -and $neuOrdner.ContainsKey((Split-Path $_.R.Pfad -Parent))) })\n\n    # --- 4) Ausgabe ---\n    Write-Host \"\"\n    Write-Host (\"  Gescannt   : {0,9:N0}\" -f $ergebnisse.Count) -ForegroundColor White\n    Write-Host (\"  Verifiziert: {0,9:N0}\" -f $verifiziert) -ForegroundColor Green\n    Write-Host (\"  Unsigniert : {0,9:N0}   davon auffaellig: {1:N0}\" -f $markiert.Count, $prioritaet.Count) -ForegroundColor $(if ($prioritaet.Count) { 'Red' } elseif ($markiert.Count) { 'Yellow' } else { 'Green' })\n    $tiefN = @($markiert | Where-Object { $_.Tief -ne $null }).Count\n    Write-Host (\"  Tiefenanalyse: alle {0:N0} unsignierten DLLs auf Cheat-Begriffe, Injection, Protectoren und Build-Pfade geprueft\" -f $markiert.Count) -ForegroundColor DarkGray\n    Write-Host (\"  Fremd      : {0,9:N0}   (+ {1:N0} bekannte Hersteller/Treiberpakete)\" -f $fremd.Count, $bekanntN) -ForegroundColor $(if ($fremd.Count) { 'Yellow' } else { 'Green' })\n    Write-Host (\"  Fehler     : {0,9:N0}   | Ordner ohne Zugriff: {1} | bewusst ausgelassen: {2}\" -f $fehler.Count, $ordnerFehler.Count, $ausgelassenN) -ForegroundColor DarkGray\n    Write-Host (\"  Dauer      : {0:N1} s mit {1} Threads\" -f $uhr.Elapsed.TotalSeconds, $threads) -ForegroundColor DarkGray\n\n    if ($phantom.Count -gt 0) {\n        Write-Host \"`n  [!!!] PHANTOM-DLLs (gehoeren an diesen Ort NIE hin):\" -ForegroundColor Red\n        foreach ($r in $phantom) { Write-Host (\"    {0}  [Sig: {1} | {2}]\" -f $r.Pfad, $r.Status, $r.Signierer) -ForegroundColor Red }\n    }\n    if ($typo.Count -gt 0) {\n        Write-Host \"`n  [!!!] Typosquatting im Windows-Ordner - Name aehnelt einer System-DLL:\" -ForegroundColor Red\n        foreach ($x in $typo) { Write-Host (\"    {0}   sieht aus wie {1}\" -f $x.Pfad, $x.Wie) -ForegroundColor Red }\n    }\n\n    $hashMap = @{}\n    if ($prioritaet.Count -gt 0) {\n        Write-Host (\"`n  --- AUFFAELLIG: {0} Dateien nach Prioritaet (unsigniert oder unbekannter Signierer) ---\" -f $prioritaet.Count) -ForegroundColor Red\n        foreach ($x in ($prioritaet | Sort-Object Rang, { $_.R.Pfad })) {\n            $r = $x.R\n            $hash = $r.Hash\n            $cn = Get-CheatName $r.Pfad\n            Write-Host (\"`n    {0}\" -f $r.Pfad) -ForegroundColor Red\n            Write-Host (\"      {0} | Status: {1}{2}\" -f $x.Grund, $r.Status, $(if ($cn) { \" | BEKANNTER CHEAT-NAME: $cn\" } else { '' })) -ForegroundColor Red\n            if ($r.Tief -and $x.Grund -notmatch 'Tiefenanalyse') { Write-Host (\"      Tiefenanalyse: {0}\" -f $r.Tief) -ForegroundColor Yellow }\n            if ($r.Erstellt) { Write-Host (\"      erstellt {0} | {1:N0} KB{2}\" -f $r.Erstellt, [Math]::Round([double]$r.Groesse / 1KB), $(if ($osInstall -and $r.Erstellt -gt $osInstall.AddDays(30)) { '  [nach Windows-Installation]' } else { '' })) -ForegroundColor DarkGray }\n            if ($hash) { Write-Host (\"      VirusTotal: https://www.virustotal.com/gui/file/{0}\" -f $hash) -ForegroundColor DarkGray }\n        }\n    }\n\n    if ($neuInstall.Count -gt 0) {\n        Write-Host \"`n  --- Neu installierte Programme (letzte 14 Tage, viele neue Dateien auf einmal) ---\" -ForegroundColor DarkGray\n        foreach ($n in ($neuInstall | Sort-Object Zeit -Descending)) {\n            $cn = Get-CheatName $n.Ordner\n            Write-Host (\"    {0}  {1,5} Dateien  {2}{3}\" -f $n.Zeit.ToString('dd.MM.yyyy HH:mm'), $n.Anzahl, $n.Ordner, $(if ($cn) { \"   &lt;-- BEKANNTER CHEAT-NAME: $cn\" } else { '' })) -ForegroundColor $(if ($cn) { 'Red' } else { 'DarkGray' })\n        }\n        Write-Host \"    Unbekannter Programmname hier = pruefen, was kurz vor der Pruefung installiert wurde.\" -ForegroundColor DarkGray\n    }\n    if ($installerReste.Count -gt 0) {\n        $iOrdner = @($installerReste | ForEach-Object { Split-Path $_.Pfad -Parent } | Sort-Object -Unique)\n        Write-Host (\"`n  ({0} DLLs aus Installer-Entpackungen in Temp ausgeblendet, {1} Ordner, z. B. {2})\" -f $installerReste.Count, $iOrdner.Count, $iOrdner[0]) -ForegroundColor DarkGray\n    }\n    if ($schwach.Count -gt 0) {\n        Write-Host (\"`n  --- Schwache Hinweise aus der Tiefenanalyse ({0}) - in Spielen/Anti-Cheats oft legitim ---\" -f $schwach.Count) -ForegroundColor DarkYellow\n        foreach ($r in ($schwach | Sort-Object Pfad | Select-Object -First 25)) {\n            Write-Host (\"    {0}\" -f $r.Pfad) -ForegroundColor DarkYellow\n            Write-Host (\"      {0}\" -f $r.Tief) -ForegroundColor DarkGray\n        }\n        if ($schwach.Count -gt 25) { Write-Host (\"    ... und {0} weitere (siehe CSV, Spalte Tiefenanalyse)\" -f ($schwach.Count - 25)) -ForegroundColor DarkGray }\n    }\n    if ($restlich.Count -gt 0) {\n        Write-Host (\"`n  --- Weitere unsignierte Dateien ({0:N0}) - einzeln, jeweils tiefenanalysiert ohne starken Befund ---\" -f $restlich.Count) -ForegroundColor Yellow\n        $letzterOrdner = ''\n        foreach ($r in ($restlich | Sort-Object Pfad)) {\n            $ordner = Split-Path $r.Pfad -Parent\n            if ($ordner -ne $letzterOrdner) { Write-Host (\"`n    [{0}]\" -f $ordner) -ForegroundColor DarkYellow; $letzterOrdner = $ordner }\n            $cn = Get-CheatName $r.Pfad\n            $col = if ($cn) { 'Red' } else { 'White' }\n            $zeit = if ($r.Erstellt) { $r.Erstellt.ToString('dd.MM.yyyy HH:mm') } else { '?' }\n            Write-Host (\"      {0,-45} {1,9:N0} KB  erstellt {2}  {3}{4}\" -f (Split-Path $r.Pfad -Leaf), [Math]::Round([double]$r.Groesse / 1KB), $zeit, $r.Status, $(if ($cn) { \"   &lt;-- BEKANNTER CHEAT-NAME: $cn\" } else { '' })) -ForegroundColor $col\n            if ($r.Tief) { Write-Host (\"        Tiefenanalyse: {0}\" -f $r.Tief) -ForegroundColor DarkYellow }\n            if ($r.Hash) { Write-Host (\"        https://www.virustotal.com/gui/file/{0}\" -f $r.Hash) -ForegroundColor DarkGray }\n        }\n    }\n\n    if ($fremdRest.Count -gt 0) {\n        Write-Host (\"`n  --- FREMD: gueltig signiert, unbekannter Hersteller, ohne Befund ({0}) ---\" -f $fremdRest.Count) -ForegroundColor Yellow\n        Write-Host \"  (Signatur beweist nur, WER unterschrieben hat - nicht, dass die Datei harmlos ist)\" -ForegroundColor DarkGray\n        foreach ($g in ($fremdRest | Group-Object Signierer | Sort-Object Count -Descending)) {\n            $fwTxt = if ($g.Name -match $fernwartung) { '   &lt;-- FERNWARTUNG' } else { '' }\n            Write-Host (\"`n    {0}  ({1}){2}\" -f $g.Name, $g.Count, $fwTxt) -ForegroundColor $(if ($fwTxt) { 'Red' } else { 'Yellow' })\n            foreach ($r in ($g.Group | Sort-Object Pfad)) {\n                Write-Host (\"      {0}\" -f $r.Pfad) -ForegroundColor DarkGray\n                if ($r.Tief) { Write-Host (\"        Tiefenanalyse: {0}\" -f $r.Tief) -ForegroundColor DarkYellow }\n            }\n        }\n    }\n    if ($fehler.Count -gt 0) {\n        Write-Host (\"`n  --- FEHLER: {0} Dateien nicht pruefbar (gesperrt/kein Zugriff) - Liste in der CSV ---\" -f $fehler.Count) -ForegroundColor DarkGray\n    }\n\n    # --- 5) CSV-Export ---\n    $csv = \"$env:USERPROFILE\\Desktop\\ctc_signaturen_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv\"\n    try {\n        $prioMap = @{}; foreach ($x in $prioritaet) { $prioMap[$x.R.Pfad] = $x.Grund }\n        $ergebnisse | Select-Object Pfad, Status, Signierer,\n            @{ n='Auffaellig'; e={ $prioMap[$_.Pfad] } },\n            @{ n='Erstellt';   e={ if ($_.Erstellt) { $_.Erstellt.ToString('dd.MM.yyyy HH:mm') } else { '' } } },\n            Attribute, Fehler, @{ n='Tiefenanalyse'; e={ $_.Tief } },\n            @{ n='GroesseKB';  e={ if ($_.Groesse) { [Math]::Round([double]$_.Groesse / 1KB) } else { '' } } },\n            @{ n='SHA256';     e={ $_.Hash } },\n            @{ n='VirusTotal'; e={ if ($_.Hash) { 'https://www.virustotal.com/gui/file/' + $_.Hash } else { '' } } } |\n            Export-Csv -Path $csv -NoTypeInformation -Encoding UTF8 -Delimiter ';'\n        Write-Host \"`n  Alle Ergebnisse gespeichert: $csv\" -ForegroundColor Green\n    } catch {\n        Write-Host \"  CSV-Export fehlgeschlagen.\" -ForegroundColor DarkGray\n    }\n\n    # --- 6) HTML-Bericht (wird direkt aus den Scan-Daten erzeugt) ---\n    try {\n        $enc   = { param($s) [System.Net.WebUtility]::HtmlEncode([string]$s) }\n        $kbTxt = { param($g) if ($g) { '{0:N0} KB' -f [Math]::Round([double]$g / 1KB) } else { '' } }\n        $ztTxt = { param($d) if ($d) { ([datetime]$d).ToString('yyyy-MM-dd HH:mm') } else { '' } }\n        $vtTxt = { param($h) if ($h) { \"VirusTotal\" } else { '' } }\n        $zeileHtml = {\n            param($r, [string]$grund, [string]$klasse)\n            $sigTxt = if ($r.Status -eq 'Valid') { 'signiert: ' + $r.Signierer } else { $r.Status }\n            \"$(&amp; $enc $r.Pfad)$(&amp; $enc $grund)$(&amp; $enc $sigTxt)$(&amp; $ztTxt $r.Erstellt)$(&amp; $kbTxt $r.Groesse)$(&amp; $enc $r.Tief)$(&amp; $vtTxt $r.Hash)\"\n        }\n        $tabKopf = '\nDateiGrundSignaturErstelltGroesseTiefenanalyseLink'\n        $os    = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue\n        $jetzt = Get-Date\n\n        $sb = New-Object System.Text.StringBuilder\n        [void]$sb.Append(@\"\n\n\nCTC Signatur-Scan - $(&amp; $enc $env:COMPUTERNAME)\n\n:root { --bg:#0f1115; --karte:#171a21; --rand:#262b36; --text:#d7dbe3; --grau:#7d8594; --rot:#ff5c5c; --gelb:#f2c14e; --gruen:#4ecb71; --blau:#5cc8ff; }\n* { box-sizing:border-box; }\nbody { margin:0; background:var(--bg); color:var(--text); font:14px/1.45 \"Segoe UI\",system-ui,sans-serif; }\nheader { padding:22px 28px; border-bottom:1px solid var(--rand); background:linear-gradient(180deg,#151924,#0f1115); }\nh1 { margin:0 0 4px; font-size:21px; } h1 span { color:var(--blau); }\n.meta { color:var(--grau); font-size:13px; }\nmain { padding:20px 28px; }\n.kacheln { display:grid; grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); gap:10px; margin-bottom:18px; }\n.kachel { background:var(--karte); border:1px solid var(--rand); border-radius:10px; padding:12px 14px; }\n.kachel b { display:block; font-size:24px; } .kachel small { color:var(--grau); }\n.k-rot b { color:var(--rot); } .k-gelb b { color:var(--gelb); } .k-gruen b { color:var(--gruen); }\n.leiste { position:sticky; top:0; z-index:5; background:var(--bg); padding:10px 0; display:flex; gap:8px; }\ninput, button { background:var(--karte); color:var(--text); border:1px solid var(--rand); border-radius:8px; padding:7px 12px; font:inherit; }\ninput { flex:1; }\ndetails { background:var(--karte); border:1px solid var(--rand); border-radius:10px; margin-bottom:12px; overflow:hidden; }\nsummary { cursor:pointer; padding:12px 16px; font-weight:600; }\nsummary small { color:var(--grau); font-weight:400; margin-left:8px; }\n.wrap { overflow-x:auto; }\ntable { width:100%; border-collapse:collapse; font-size:12.5px; }\nth { text-align:left; color:var(--grau); font-weight:600; padding:7px 10px; border-top:1px solid var(--rand); cursor:pointer; white-space:nowrap; user-select:none; }\nth:hover { color:var(--blau); }\ntd { padding:7px 10px; border-top:1px solid var(--rand); vertical-align:top; }\ntd.pfad { font-family:Consolas,\"Cascadia Mono\",monospace; word-break:break-all; min-width:320px; }\ntd.tief { color:var(--gelb); font-size:12px; max-width:420px; }\ntd.num, td.nw { white-space:nowrap; } td.num { text-align:right; }\ntr.rot td:first-child { border-left:3px solid var(--rot); } tr.rot td.pfad { color:var(--rot); }\ntr.gelb td:first-child { border-left:3px solid var(--gelb); }\ntr.grau td { color:var(--grau); } tr.grau td.tief { color:var(--gelb); }\na { color:var(--blau); } .leer { color:var(--grau); padding:10px 16px; } ul { margin:0; padding:6px 16px 12px 34px; }\nli { font-family:Consolas,monospace; font-size:12.5px; word-break:break-all; padding:2px 0; } li.rot { color:var(--rot); }\n.hinweis { color:var(--grau); font-size:12.5px; padding:6px 2px; }\n\n\n\n  \nCTC by Dark &ndash; Signatur-Scan und Tiefenanalyse\n  \nPC $(&amp; $enc $env:COMPUTERNAME) &middot; Benutzer $(&amp; $enc $env:USERNAME) &middot; $(&amp; $enc $os.Caption) $(&amp; $enc $os.Version) &middot; $($jetzt.ToString('dd.MM.yyyy HH:mm'))\n  Umfang: $(&amp; $enc ($wurzeln -join ', ')) &middot; Dauer $('{0:N1}' -f $uhr.Elapsed.TotalSeconds) s mit $threads Threads\n\n\n\n\n\n  \n$('{0:N0}' -f $ergebnisse.Count)gescannt (DLL/EXE/SYS)\n  \n$('{0:N0}' -f $verifiziert)gueltig signiert\n  \n$($prioritaet.Count + $phantom.Count + $typo.Count)auffaellig\n  \n$($schwach.Count)schwache Hinweise\n  \n$('{0:N0}' -f $markiert.Count)unsigniert gesamt\n  \n$($fremd.Count)unbekannte Signierer\n  \n$($fehler.Count)nicht pruefbar\n\n\n\n  \n  Alles aufAlles zu\n\n\nTipp: Auf eine Spaltenueberschrift klicken, um zu sortieren. Rot bedeutet &quot;pruefen&quot;, nicht automatisch Cheat.\n\"@)\n\n        # Phantom-DLLs und Typosquatting\n        if ($phantom.Count -gt 0 -or $typo.Count -gt 0) {\n            [void]$sb.Append('\nPhantom-DLLs und Typosquattinggehoeren an diesen Ort nie hin\n')\n            foreach ($r in $phantom) { [void]$sb.Append(\"\n$(&amp; $enc $r.Pfad) &nbsp; [$(&amp; $enc $r.Status) | $(&amp; $enc $r.Signierer)]\") }\n            foreach ($x in $typo)    { [void]$sb.Append(\"\n$(&amp; $enc $x.Pfad) &nbsp; sieht aus wie $(&amp; $enc $x.Wie)\") }\n            [void]$sb.Append('')\n        }\n\n        # Auffaellig\n        [void]$sb.Append(\"\nAuffaellig ($($prioritaet.Count))nach Prioritaet sortiert\")\n        if ($prioritaet.Count -gt 0) {\n            [void]$sb.Append('\n' + $tabKopf)\n            foreach ($x in ($prioritaet | Sort-Object Rang, { $_.R.Pfad })) {\n                $kl = if ($x.Rang -le 2) { 'rot' } else { 'gelb' }\n                [void]$sb.Append((&amp; $zeileHtml $x.R $x.Grund $kl))\n            }\n            [void]$sb.Append('')\n        } else { [void]$sb.Append('\nKeine auffaelligen Dateien.') }\n        [void]$sb.Append('')\n\n        # Neu installierte Programme\n        if ($neuInstall.Count -gt 0) {\n            [void]$sb.Append(\"\nNeu installierte Programme ($($neuInstall.Count))viele neue Dateien auf einmal, letzte 14 Tage\n\")\n            foreach ($n in ($neuInstall | Sort-Object Zeit -Descending)) { [void]$sb.Append(\"\n$($n.Zeit.ToString('dd.MM.yyyy HH:mm')) &nbsp; $($n.Anzahl) Dateien &nbsp; $(&amp; $enc $n.Ordner)\") }\n            [void]$sb.Append('')\n        }\n\n        # Schwache Hinweise\n        if ($schwach.Count -gt 0) {\n            [void]$sb.Append(\"\nSchwache Hinweise ($($schwach.Count))in Spielen, Anti-Cheats und Installern oft legitim\n$tabKopf\")\n            foreach ($r in ($schwach | Sort-Object Pfad)) { [void]$sb.Append((&amp; $zeileHtml $r '' 'grau')) }\n            [void]$sb.Append('')\n        }\n\n        # Unbekannte Signierer ohne Befund\n        if ($fremdRest.Count -gt 0) {\n            [void]$sb.Append(\"\nUnbekannte Signierer ohne Befund ($($fremdRest.Count))Signatur beweist nur, wer unterschrieben hat\n$tabKopf\")\n            foreach ($r in ($fremdRest | Sort-Object Signierer, Pfad)) {\n                $fw = if ($r.Signierer -match $fernwartung) { 'FERNWARTUNG' } else { '' }\n                [void]$sb.Append((&amp; $zeileHtml $r $fw $(if ($fw) { 'gelb' } else { 'grau' })))\n            }\n            [void]$sb.Append('')\n        }\n\n        # Weitere unsignierte Dateien\n        if ($restlich.Count -gt 0) {\n            [void]$sb.Append(\"\nWeitere unsignierte Dateien ($('{0:N0}' -f $restlich.Count))einzeln tiefenanalysiert, ohne starken Befund\n$tabKopf\")\n            foreach ($r in ($restlich | Sort-Object Pfad)) { [void]$sb.Append((&amp; $zeileHtml $r '' 'grau')) }\n            [void]$sb.Append('')\n        }\n\n        # Installer-Reste, Fehler, uebersprungene Ordner\n        if ($installerReste.Count -gt 0 -or $fehler.Count -gt 0 -or $ordnerFehler.Count -gt 0) {\n            [void]$sb.Append('\nAusgeblendet und nicht pruefbar\n')\n            foreach ($r in $installerReste) { [void]$sb.Append(\"\nInstaller-Rest: $(&amp; $enc $r.Pfad)\") }\n            foreach ($r in $fehler)         { [void]$sb.Append(\"\nFehler: $(&amp; $enc $r.Pfad) &nbsp; ($(&amp; $enc $r.Fehler))\") }\n            foreach ($o in $ordnerFehler)   { [void]$sb.Append(\"\nOrdner ohne Zugriff: $(&amp; $enc $o)\") }\n            [void]$sb.Append('')\n        }\n\n        [void]$sb.Append(@\"\n\nVollstaendige Liste aller $('{0:N0}' -f $ergebnisse.Count) Dateien: $(&amp; $enc $csv)\nGrenze: Echt signierte, aber verwundbare Treiber (BYOVD) und dateiloser Code im Speicher sind hier nicht sichtbar - dafuer Punkt 21.\n\n\nfunction suchen(q){q=q.toLowerCase();document.querySelectorAll('tbody tr, li').forEach(function(r){r.style.display=!q||r.textContent.toLowerCase().indexOf(q)&gt;=0?'':'none';});if(q){alle(true);}}\nfunction alle(o){document.querySelectorAll('details').forEach(function(d){d.open=o;});}\ndocument.querySelectorAll('table.sort th').forEach(function(th,i){th.onclick=function(){var tb=th.closest('table').tBodies[0],rs=[].slice.call(tb.rows),a=(th.getAttribute('data-a')=='1')?'0':'1';th.setAttribute('data-a',a);rs.sort(function(x,y){var p=x.cells[i].textContent,q=y.cells[i].textContent;return a=='1'?p.localeCompare(q,'de',{numeric:true}):q.localeCompare(p,'de',{numeric:true});});rs.forEach(function(r){tb.appendChild(r);});};});\n\n\n\"@)\n        $html = \"$env:USERPROFILE\\Desktop\\ctc_signaturen_$(Get-Date -Format 'yyyyMMdd_HHmmss').html\"\n        [System.IO.File]::WriteAllText($html, $sb.ToString(), (New-Object System.Text.UTF8Encoding($false)))\n        Write-Host \"  HTML-Bericht gespeichert: $html\" -ForegroundColor Green\n        try { Start-Process $html } catch { Write-Host \"  Bitte die Datei manuell im Browser oeffnen.\" -ForegroundColor Yellow }\n    } catch {\n        Write-Host (\"  HTML-Bericht konnte nicht erstellt werden: {0}\" -f $_.Exception.Message) -ForegroundColor Yellow\n    }\n\n    Write-Host \"`nAuswertung:\" -ForegroundColor DarkGray\n    Write-Host \"  Prioritaet: Cheat-Name &gt; HashMismatch &gt; Papierkorb &gt; Windows-Ordner &gt; Temp &gt; Side-Loading &gt; neu &gt; versteckt.\" -ForegroundColor DarkGray\n    Write-Host \"  Die 'uebrigen' unsignierten DLLs sind meist Spiele und Tools - nur ansehen, wenn der Ordnername unbekannt ist.\" -ForegroundColor DarkGray\n    Write-Host \"  Grenze: Echt signierte Treiber (BYOVD) und dateiloser Code sind hier 'sauber' -&gt; Punkte 21c und 21a.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  17 - DMA Fuser &amp; Zweiter-PC-Verbindungen\n# ============================================================\nfunction Invoke-FuserCheck {\n    Write-Host \"`n=== DMA Fuser &amp; Zweiter-PC-Verbindungen ===\" -ForegroundColor Cyan\n    Write-Host \"(Netzwerkverbindungen, windowlose Prozesse, Named Pipes, bekannte Fuser)\" -ForegroundColor DarkGray\n\n    # --- 17a: Bekannte Fuser-Prozessnamen ---\n    Write-Host \"`n--- Bekannte DMA-Fuser Prozesse ---\" -ForegroundColor DarkGray\n    $fuserNamen = @(\n        'pcileech','memflow','memprocfs','dmaclient','dmaservice',\n        'easymapi','leechcore','leechagent','fpga','dma_client',\n        'scatterclient','scatter','vmmdll','vmmsharp',\n        'winpmem','rekall','volatility','dumpit'\n    )\n    $fuserGefunden = $false\n    foreach ($n in $fuserNamen) {\n        $p = @(Get-Process -Name $n -ErrorAction SilentlyContinue)\n        if ($p.Count -gt 0) {\n            $p | ForEach-Object {\n                Write-Host (\"  [!!!] {0} (PID {1}) - {2}\" -f $_.Name, $_.Id, $_.Path) -ForegroundColor Red\n            }\n            $fuserGefunden = $true\n        }\n    }\n    if (-not $fuserGefunden) {\n        Write-Host \"  Keine bekannten Fuser-Prozesse gefunden.\" -ForegroundColor Green\n    }\n\n    # --- 17b: Netzwerkverbindungen zu lokalen IPs (PC2-Verbindung) ---\n    Write-Host \"`n--- Netzwerkverbindungen zu lokalen IPs (DMA PC2) ---\" -ForegroundColor DarkGray\n    Write-Host \"(192.168.x.x / 10.x.x.x / 172.16-31.x.x auf ungewoehnlichen Ports)\" -ForegroundColor DarkGray\n\n    $bekanntePortsOK = @(80,443,8080,8443,3389,5985,5986,53,67,68,123,137,138,139,445,1900,5353)\n    $lokaleVerbindungen = @()\n\n    Get-NetTCPConnection -State Established -ErrorAction SilentlyContinue | ForEach-Object {\n        $remIP = $_.RemoteAddress\n        $remPort = $_.RemotePort\n        $istLokal = $remIP -match '^192\\.168\\.|^10\\.|^172\\.(1[6-9]|2[0-9]|3[01])\\.'\n        $portUngewoehnlich = $bekanntePortsOK -notcontains $remPort\n\n        if ($istLokal -and $portUngewoehnlich) {\n            $proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue\n            $lokaleVerbindungen += [PSCustomObject]@{\n                Prozess  = if ($proc) { $proc.Name } else { 'Unbekannt' }\n                PID      = $_.OwningProcess\n                LokPort  = $_.LocalPort\n                RemoteIP = $remIP\n                RemPort  = $remPort\n                Pfad     = if ($proc) { $proc.Path } else { '-' }\n            }\n        }\n    }\n\n    if ($lokaleVerbindungen.Count -gt 0) {\n        Write-Host \"  [!] $($lokaleVerbindungen.Count) Verbindungen zu lokalen IPs auf ungewoehnlichen Ports:\" -ForegroundColor Red\n        $lokaleVerbindungen | Sort-Object RemoteIP | ForEach-Object {\n            Write-Host (\"`n  [{0}] PID {1}\" -f $_.Prozess, $_.PID) -ForegroundColor Red\n            Write-Host (\"  Remote: {0}:{1}  (lokal Port {2})\" -f $_.RemoteIP, $_.RemPort, $_.LokPort) -ForegroundColor Red\n            Write-Host (\"  Pfad  : {0}\" -f $_.Pfad) -ForegroundColor DarkGray\n        }\n    } else {\n        Write-Host \"  Keine auffaelligen lokalen Netzwerkverbindungen.\" -ForegroundColor Green\n    }\n\n    # --- 17c: Windowlose Prozesse ohne bekanntes Elternteil ---\n    Write-Host \"`n--- Windowlose Hintergrundprozesse (moegliche versteckte Fuser) ---\" -ForegroundColor DarkGray\n    $systemProz = @('svchost','services','lsass','csrss','wininit','smss','System',\n                    'Registry','fontdrvhost','dwm','WmiPrvSE','spoolsv','SearchIndexer',\n                    'RuntimeBroker','ShellExperienceHost','StartMenuExperienceHost',\n                    'sihost','taskhostw','ctfmon','conhost','dllhost','audiodg',\n                    'MsMpEng','NisSrv','SecurityHealthService','TextInputHost')\n\n    $verdaechtigeProz = @()\n    Add-Type @\"\nusing System;\nusing System.Runtime.InteropServices;\npublic class WinAPI {\n    [DllImport(\"user32.dll\")]\n    public static extern bool IsWindowVisible(IntPtr hWnd);\n    [DllImport(\"user32.dll\")]\n    public static extern IntPtr GetForegroundWindow();\n}\n\"@ -ErrorAction SilentlyContinue\n\n    Get-Process -ErrorAction SilentlyContinue | Where-Object {\n        $_.Name -notin $systemProz -and\n        $_.MainWindowHandle -eq [IntPtr]::Zero -and\n        $_.SessionId -eq (Get-Process -PID $PID).SessionId\n    } | ForEach-Object {\n        $p = $_\n        # Nur Prozesse mit Pfad und ohne Fenster die nicht bekannte Apps sind\n        if ($p.Path -and $p.Path -notmatch '(?i)\\\\Windows\\\\|\\\\Program Files\\\\|\\\\Program Files \\(x86\\)\\\\') {\n            $sig = Get-AuthenticodeSignature $p.Path -ErrorAction SilentlyContinue\n            $istMS = $sig -and $sig.Status -eq 'Valid' -and $sig.SignerCertificate -and $sig.SignerCertificate.Subject -match '(?i)Microsoft'\n            if (-not $istMS) {\n                $verdaechtigeProz += [PSCustomObject]@{\n                    Name     = $p.Name\n                    PID      = $p.Id\n                    Pfad     = $p.Path\n                    Sig      = if ($sig) { $sig.Status } else { 'Unbekannt' }\n                    Signierer= if ($sig -and $sig.SignerCertificate) { $sig.SignerCertificate.Subject -replace '^(?:.*?,\\s*)?CN=(?:\"([^\"]+)\"|([^,]+)).*$','$1$2' } else { '-' }\n                }\n            }\n        }\n    }\n\n    if ($verdaechtigeProz.Count -gt 0) {\n        Write-Host \"  $($verdaechtigeProz.Count) windowlose, nicht-MS-signierte Prozesse ausserhalb Systemordner:\" -ForegroundColor Yellow\n        $verdaechtigeProz | ForEach-Object {\n            $col = if ($_.Sig -ne 'Valid') { 'Red' } else { 'Yellow' }\n            Write-Host (\"`n  [{0}] PID {1}\" -f $_.Name, $_.PID) -ForegroundColor $col\n            Write-Host (\"  Pfad : {0}\" -f $_.Pfad) -ForegroundColor $col\n            Write-Host (\"  Sig  : {0} | {1}\" -f $_.Sig, $_.Signierer) -ForegroundColor DarkGray\n        }\n    } else {\n        Write-Host \"  Keine auffaelligen windowlosen Prozesse.\" -ForegroundColor Green\n    }\n\n    # --- 17d: Named Pipes mit DMA-typischen Namen ---\n    Write-Host \"`n--- Named Pipes (DMA/Fuser-Kommunikation) ---\" -ForegroundColor DarkGray\n    $dmaPipeMuster = 'dma|fuser|pcileech|memflow|leech|scatter|fpga|cheat|inject|overlay|radar'\n    try {\n        $pipes = @([System.IO.Directory]::GetFiles('\\\\.\\pipe\\') 2&gt;$null)\n        $verdPipes = @($pipes | Where-Object { $_ -match $dmaPipeMuster })\n        if ($verdPipes.Count -gt 0) {\n            Write-Host \"  [!] Verdaechtige Named Pipes:\" -ForegroundColor Red\n            $verdPipes | ForEach-Object { Write-Host \"  $_\" -ForegroundColor Red }\n        } else {\n            Write-Host \"  Keine DMA-typischen Named Pipes.\" -ForegroundColor Green\n        }\n        Write-Host \"  (Alle Pipes: $($pipes.Count) vorhanden)\" -ForegroundColor DarkGray\n    } catch {\n        # Alternativer Weg ueber Sysinternals wenn verfuegbar\n        Write-Host \"  Direkter Pipe-Zugriff nicht moeglich. Alternativ:\" -ForegroundColor DarkGray\n        Write-Host \"  handle.exe -a | findstr '\\pipe' (Sysinternals)\" -ForegroundColor DarkGray\n    }\n\n    # --- 17e: Autostart-Eintraege fuer Fuser ---\n    Write-Host \"`n--- Autostart-Eintraege (Fuser beim Boot) ---\" -ForegroundColor DarkGray\n    $autoKeys = @(\n        'HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run',\n        'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run',\n        'HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce',\n        'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce'\n    )\n    foreach ($k in $autoKeys) {\n        if (-not (Test-Path $k)) { continue }\n        $vals = Get-ItemProperty $k -ErrorAction SilentlyContinue\n        $vals.PSObject.Properties | Where-Object { $_.Name -notmatch '^PS' } | ForEach-Object {\n            $pfad = $_.Value -replace '\"','' -replace ' .*$',''\n            if (Test-Path $pfad -ErrorAction SilentlyContinue) {\n                $sig = Get-AuthenticodeSignature $pfad -ErrorAction SilentlyContinue\n                $istMS = $sig -and $sig.Status -eq 'Valid' -and $sig.SignerCertificate -and $sig.SignerCertificate.Subject -match '(?i)Microsoft'\n                if (-not $istMS) {\n                    $col = if ($sig -and $sig.Status -ne 'Valid') { 'Red' } else { 'Yellow' }\n                    Write-Host (\"  [!] {0} = {1}\" -f $_.Name, $_.Value) -ForegroundColor $col\n                    Write-Host (\"      Sig: {0}\" -f $(if($sig){$sig.Status}else{'Unbekannt'})) -ForegroundColor $col\n                }\n            }\n        }\n    }\n    Write-Host \"  Autostart-Check abgeschlossen.\" -ForegroundColor DarkGray\n\n    Write-Host \"`nFuser-Erkennungs-Tipp:\" -ForegroundColor DarkGray\n    Write-Host \"  Netzwerkverbindung zu 192.168.x.x auf Port &gt;10000 + windowloser Prozess = starkes Indiz.\" -ForegroundColor DarkGray\n    Write-Host \"  Fuser laufen oft nur waehrend des Spiels - deshalb Pruefung waehrend aktiver Session.\" -ForegroundColor DarkGray\n\n    # --- 17f: Display-Analyse (HDMI-Splitter / Capture-Setup) ---\n    Write-Host \"`n--- Display-Analyse (HDMI-Splitter / gespiegeltes Bild) ---\" -ForegroundColor DarkGray\n    Write-Host \"(Mehr Displays als Monitore sichtbar = moeglicher Splitter oder Capture-Input)\" -ForegroundColor DarkGray\n\n    try {\n        $monitors = @(Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorID -ErrorAction SilentlyContinue)\n        Write-Host (\"  Erkannte Displays: {0}\" -f $monitors.Count)\n        foreach ($m in $monitors) {\n            $hersteller = try { [System.Text.Encoding]::ASCII.GetString(($m.ManufacturerName | Where-Object {$_ -ne 0})) } catch { '?' }\n            $modell     = try { [System.Text.Encoding]::ASCII.GetString(($m.UserFriendlyName  | Where-Object {$_ -ne 0})) } catch { '?' }\n            $serial     = try { [System.Text.Encoding]::ASCII.GetString(($m.SerialNumberID    | Where-Object {$_ -ne 0})) } catch { '' }\n            $col = 'White'\n            $hinweis = ''\n            # Typische Capture-Card oder Virtual-Display Hersteller\n            if ($hersteller -match '(?i)AVerMedia|Elgato|Magewell|Blackmagic|Datapath|DisplayLink|ITE|GENERIC|VirtualDisplay|Parsec|NoMachine') {\n                $col = 'Red'\n                $hinweis = ' [!] CAPTURE/VIRTUAL DISPLAY'\n            }\n            Write-Host (\"  {0,-8} {1,-25} Serial: {2}{3}\" -f $hersteller.Trim(), $modell.Trim(), $serial.Trim(), $hinweis) -ForegroundColor $col\n        }\n\n        if ($monitors.Count -gt 2) {\n            Write-Host (\"  [!] {0} Displays erkannt - mehr als 2 ist ungewoehnlich fuer einen Gaming-PC.\" -f $monitors.Count) -ForegroundColor Yellow\n            Write-Host \"      Moeglicher HDMI-Splitter oder Capture-Eingang aktiv.\" -ForegroundColor Yellow\n        }\n    } catch {\n        Write-Host \"  Display-Abfrage fehlgeschlagen.\" -ForegroundColor DarkGray\n    }\n\n    # --- 17g: Capture-Cards und Video-Devices auf PC1 ---\n    Write-Host \"`n--- Capture-Cards &amp; Video-Geraete auf diesem PC ---\" -ForegroundColor DarkGray\n    $captureGeraete = @(Get-PnpDevice -ErrorAction SilentlyContinue | Where-Object {\n        $_.Class -match '(?i)Media|Image|Camera' -and $_.Status -eq 'OK'\n    })\n    if ($captureGeraete.Count -gt 0) {\n        foreach ($g in $captureGeraete) {\n            $istVerd = $g.FriendlyName -match '(?i)capture|hdmi|video|grabber|avermedia|elgato|magewell|blackmagic|hauppauge'\n            $col = if ($istVerd) { 'Yellow' } else { 'DarkGray' }\n            Write-Host (\"  [{0}] {1}\" -f $g.Class, $g.FriendlyName) -ForegroundColor $col\n            if ($istVerd) {\n                Write-Host (\"  --&gt; Capture-Device: {0}\" -f $g.InstanceId) -ForegroundColor Yellow\n                Write-Host \"      Pruefe ob das Geraet fuer Cheat-Capture oder legitimes Streaming genutzt wird.\" -ForegroundColor DarkGray\n            }\n        }\n    } else {\n        Write-Host \"  Keine Video/Capture-Geraete gefunden.\" -ForegroundColor Green\n    }\n\n    # --- 17h: Aktive GPU-Ausgaenge (mehr als physische Monitore) ---\n    Write-Host \"`n--- GPU: aktive Video-Ausgaenge ---\" -ForegroundColor DarkGray\n    Get-CimInstance Win32_VideoController -ErrorAction SilentlyContinue | ForEach-Object {\n        Write-Host (\"  GPU       : {0}\" -f $_.Name)\n        Write-Host (\"  Adapter   : {0}\" -f $_.AdapterCompatibility)\n        Write-Host (\"  Aufloesung: {0}x{1}\" -f $_.CurrentHorizontalResolution, $_.CurrentVerticalResolution)\n    }\n\n    Write-Host \"`nHDMI-Splitter-Tipp:\" -ForegroundColor DarkGray\n    Write-Host \"  Physische Pruefung: 2 HDMI-Kabel am Monitor (Input 1 + Input 2) ist verdaechtig.\" -ForegroundColor DarkGray\n    Write-Host \"  Ein zweiter laufender PC ohne sichtbare Aktivitaet = moeglicher Cheat-PC.\" -ForegroundColor DarkGray\n    Write-Host \"  Netzwerk (Punkt 17b) findet die DMA-Verbindung zwischen PC1 und PC2.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  18 - Forensische Tools herunterladen\n# ============================================================\nfunction Invoke-ToolDownload {\n    Write-Host \"`n=== Forensische Tools - Download ===\" -ForegroundColor Cyan\n    Write-Host \"(Alle Tools sind kostenlos und Open Source / Freeware)\" -ForegroundColor DarkGray\n\n    $zielOrdner = \"$env:USERPROFILE\\Desktop\\CTC_Tools\"\n    if (-not (Test-Path $zielOrdner)) {\n        New-Item -ItemType Directory -Path $zielOrdner | Out-Null\n        Write-Host \"Ordner erstellt: $zielOrdner\" -ForegroundColor Green\n    } else {\n        Write-Host \"Zielordner: $zielOrdner\" -ForegroundColor DarkGray\n    }\n\n    $tools = [ordered]@{\n        '1' = @{\n            Name   = 'Everything 1.4 (Blitzschnelle Dateisuche)'\n            URL    = 'https://www.voidtools.com/Everything-1.4.1.1024.x64.zip'\n            Zip    = $true\n            Tipp   = 'Findet DLLs, .sys-Dateien und Cheat-Dateien sofort'\n        }\n        '2' = @{\n            Name   = 'System Informer (Prozesse, Handles, Netzwerk)'\n            URL    = 'github_latest'\n            Repo   = 'winsiderss/systeminformer'\n            Zip    = $true\n            Tipp   = 'Zeigt geladene DLLs, Named Pipes und versteckte Prozesse'\n        }\n        '3' = @{\n            Name   = 'Autoruns (Alle Autostart-Eintraege)'\n            URL    = 'https://download.sysinternals.com/files/Autoruns.zip'\n            Zip    = $true\n            Tipp   = 'Zeigt JEDEN Autostart-Eintrag - Fuser-Erkennung'\n        }\n        '4' = @{\n            Name   = 'Process Monitor (Live Datei/Registry/Netzwerk)'\n            URL    = 'https://download.sysinternals.com/files/ProcessMonitor.zip'\n            Zip    = $true\n            Tipp   = 'Zeigt phantom DLL-Suchen in Echtzeit (DLL Hijacking live)'\n        }\n        '5' = @{\n            Name   = 'TCPView (Netzwerkverbindungen live)'\n            URL    = 'https://download.sysinternals.com/files/TCPView.zip'\n            Zip    = $true\n            Tipp   = 'Fuser-Verbindungen zu PC2 in Echtzeit sehen'\n        }\n        '6' = @{\n            Name   = 'Handle (Named Pipes &amp; Handles)'\n            URL    = 'https://download.sysinternals.com/files/Handle.zip'\n            Zip    = $true\n            Tipp   = 'Zeigt alle Named Pipes - DMA Fuser Kommunikation'\n        }\n        '7' = @{\n            Name   = 'Strings (Strings aus Binaerdateien extrahieren)'\n            URL    = 'https://download.sysinternals.com/files/Strings.zip'\n            Zip    = $true\n            Tipp   = 'Wie im WptsExtensions.dll Fund - inject/manualmap Strings sehen'\n        }\n        '8' = @{\n            Name   = 'Hollows Hunter (Injizierte Module finden)'\n            URL    = 'github_latest'\n            Repo   = 'hasherezade/hollows_hunter'\n            Zip    = $false\n            Tipp   = 'Findet reflective injection und manual mapped Code in Prozessen'\n        }\n        '9' = @{\n            Name   = 'SrumECmd (Netzwerkverkehr pro Programm, rueckwirkend)'\n            URL    = 'https://download.ericzimmermanstools.com/net9/SrumECmd.zip'\n            Zip    = $true\n            Tipp   = 'Fuer Punkt 20: Netzwerkverkehr auch geloeschter Programme. Braucht .NET 9 Runtime. Falls Download scheitert: ericzimmerman.github.io'\n        }\n        'A' = @{ Name = 'Alle Tools herunterladen'; URL = ''; Zip = $false; Tipp = '' }\n    }\n\n    Write-Host \"`n  Verfuegbare Tools:\" -ForegroundColor Cyan\n    foreach ($k in $tools.Keys) {\n        if ($k -eq 'A') {\n            Write-Host \"`n  [A] Alle herunterladen\" -ForegroundColor Yellow\n        } else {\n            $t = $tools[$k]\n            Write-Host (\"  [{0}] {1}\" -f $k, $t.Name) -ForegroundColor White\n            Write-Host (\"      --&gt; {0}\" -f $t.Tipp) -ForegroundColor DarkGray\n        }\n    }\n    Write-Host \"  [Q] Abbrechen\" -ForegroundColor DarkGray\n\n    $wahl = (Read-Host \"`nAuswahl\").Trim().ToUpper()\n    if ($wahl -eq 'Q') { return }\n\n    $zuLaden = if ($wahl -eq 'A') { $tools.Keys | Where-Object { $_ -ne 'A' } } else { @($wahl) }\n\n    foreach ($k in $zuLaden) {\n        if (-not $tools.ContainsKey($k)) { Write-Host \"Unbekannte Auswahl: $k\" -ForegroundColor Red; continue }\n        $tool = $tools[$k]\n        Write-Host (\"`n[{0}] Lade {1}...\" -f $k, $tool.Name) -ForegroundColor Cyan\n\n        $url = $tool.URL\n\n        # GitHub Latest Release URL holen\n        if ($url -eq 'github_latest') {\n            try {\n                Write-Host \"  GitHub Release API abfragen...\" -ForegroundColor DarkGray\n                $apiUrl = \"https://api.github.com/repos/$($tool.Repo)/releases/latest\"\n                $release = Invoke-RestMethod $apiUrl -Headers @{'User-Agent'='CTC-by-Dark'} -ErrorAction Stop\n                # Passende Asset-URL finden (x64, Windows)\n                $asset = $release.assets | Where-Object {\n                    $_.name -match '(?i)x64|amd64|win64' -and\n                    $_.name -match '(?i)\\.zip$|\\.exe$' -and\n                    $_.name -notmatch '(?i)debug|pdb|symbols'\n                } | Select-Object -First 1\n\n                if ($asset) {\n                    $url = $asset.browser_download_url\n                    Write-Host (\"  Version: {0} | Asset: {1}\" -f $release.tag_name, $asset.name) -ForegroundColor DarkGray\n                } else {\n                    Write-Host \"  Kein passendes Asset gefunden. Bitte manuell herunterladen:\" -ForegroundColor Yellow\n                    Write-Host (\"  https://github.com/{0}/releases\" -f $tool.Repo) -ForegroundColor Yellow\n                    continue\n                }\n            } catch {\n                Write-Host (\"  GitHub-Abfrage fehlgeschlagen: {0}\" -f $_) -ForegroundColor Red\n                Write-Host (\"  Manuell: https://github.com/{0}/releases\" -f $tool.Repo) -ForegroundColor Yellow\n                continue\n            }\n        }\n\n        # Dateiname aus URL\n        $dateiName = [System.IO.Path]::GetFileName($url)\n        $zielPfad  = Join-Path $zielOrdner $dateiName\n\n        try {\n            Write-Host (\"  Download: {0}\" -f $url) -ForegroundColor DarkGray\n            Invoke-WebRequest -Uri $url -OutFile $zielPfad -UseBasicParsing -ErrorAction Stop\n            Write-Host (\"  Gespeichert: {0}\" -f $zielPfad) -ForegroundColor Green\n\n            # ZIP entpacken\n            if ($tool.Zip -and $dateiName -match '\\.zip$') {\n                $extraktOrdner = Join-Path $zielOrdner ([System.IO.Path]::GetFileNameWithoutExtension($dateiName))\n                if (-not (Test-Path $extraktOrdner)) { New-Item -ItemType Directory -Path $extraktOrdner | Out-Null }\n                Expand-Archive -Path $zielPfad -DestinationPath $extraktOrdner -Force\n                Remove-Item $zielPfad -Force\n                Write-Host (\"  Entpackt: {0}\" -f $extraktOrdner) -ForegroundColor Green\n            }\n        } catch {\n            Write-Host (\"  Fehler: {0}\" -f $_) -ForegroundColor Red\n            Write-Host (\"  Manuell herunterladen: {0}\" -f $url) -ForegroundColor Yellow\n        }\n    }\n\n    Write-Host \"`n======================================\" -ForegroundColor Cyan\n    Write-Host \"  Tools gespeichert in:\" -ForegroundColor Cyan\n    Write-Host \"  $zielOrdner\" -ForegroundColor Yellow\n    Write-Host \"======================================\" -ForegroundColor Cyan\n    Write-Host \"Empfohlene Reihenfolge fuer eine Analyse:\" -ForegroundColor DarkGray\n    Write-Host \"  1. Autoruns    - Was startet beim Boot?\" -ForegroundColor DarkGray\n    Write-Host \"  2. TCPView     - Welche Verbindungen laufen?\" -ForegroundColor DarkGray\n    Write-Host \"  3. ProcMon     - Welche DLLs werden gesucht?\" -ForegroundColor DarkGray\n    Write-Host \"  4. SysInformer - Was ist in den Prozessen geladen?\" -ForegroundColor DarkGray\n    Write-Host \"  5. Everything  - Verdaechtige Dateien suchen\" -ForegroundColor DarkGray\n    Write-Host \"  6. HollowsHunter - Injizierte Module aufdecken\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  19 - Session-Rekonstruktion: Was lief nach der Fernwartung?\n# ============================================================\nfunction Invoke-SessionTimeline {\n    Write-Host \"`n=== Session-Rekonstruktion (Timeline nach Fernwartung) ===\" -ForegroundColor Cyan\n    Write-Host \"(Alle Quellen chronologisch: Programme, PowerShell, Defender, Dienste, neue/geloeschte Dateien)\" -ForegroundColor DarkGray\n\n    $fwMuster  = 'rustdesk|anydesk|teamviewer|parsec|ultraviewer|splashtop|supremo|getscreen|aeroadmin'\n    $eigenCode = 'CTC by Dark|CatchTheCheat|CTC_by_Dark|pnpcheck\\.ps1|ctcbydark|analystdark|Invoke-SessionTimeline'\n    $verdPS    = '(?i)-enc\\b|-encodedcommand|-e\\s+[A-Za-z0-9+/=]{20}|hidden|\\biex\\b|invoke-expression|downloadstring|downloadfile|\\birm\\b|\\biwr\\b|invoke-webrequest|invoke-restmethod|https?://|add-mppreference|set-mppreference|frombase64|reflection\\.assembly|start-bitstransfer|certutil|bypass'\n\n    $kurz = {\n        param([string]$m, [int]$n = 180)\n        $m2 = ($m -replace '\\s+',' ').Trim()\n        if ($m2.Length -gt $n) { $m2.Substring(0,$n) + ' [...]' } else { $m2 }\n    }\n\n    # --- Hilfsmittel: Device-Pfad -&gt; Laufwerk, Registry-Key-Zeitstempel ---\n    Add-Type -ErrorAction SilentlyContinue -TypeDefinition @\"\nusing System;\nusing System.Text;\nusing System.Runtime.InteropServices;\npublic static class CtcDos {\n    [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)]\n    public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);\n}\n\"@\n    $sigRQ3 = '[DllImport(\"advapi32.dll\")]public static extern int RegQueryInfoKey(Microsoft.Win32.SafeHandles.SafeRegistryHandle h,System.Text.StringBuilder a,ref int b,int c,ref int d,ref int e,ref int f,ref int g,ref int i,ref int j,ref int k,ref long l);'\n    Add-Type -MemberDefinition $sigRQ3 -Name RK3 -Namespace W3 -ErrorAction SilentlyContinue\n    $keyZeit = {\n        param($pfad)\n        try {\n            $k = Get-Item $pfad -ErrorAction Stop\n            $t = 0L; $z = 0; $n = New-Object Text.StringBuilder 1024\n            [void][W3.RK3]::RegQueryInfoKey($k.Handle,$n,[ref]$z,0,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$t)\n            [DateTime]::FromFileTime($t)\n        } catch { $null }\n    }\n\n    $devMap = @{}\n    foreach ($cc in 67..90) {\n        $lw = ([string][char]$cc) + ':'\n        $sb = New-Object System.Text.StringBuilder 260\n        try { if ([CtcDos]::QueryDosDevice($lw, $sb, 260) -gt 0) { $devMap[$sb.ToString()] = $lw } } catch {}\n    }\n    $konvDev = {\n        param([string]$p)\n        foreach ($k in $devMap.Keys) {\n            if ($p.StartsWith($k + '\\', [StringComparison]::OrdinalIgnoreCase)) { return ($devMap[$k] + $p.Substring($k.Length)) }\n        }\n        return $p\n    }\n\n    # --- BAM einlesen (jede ausgefuehrte EXE mit letzter Laufzeit, ueberlebt Loeschen) ---\n    $bam = @()\n    foreach ($root in @('HKLM:\\SYSTEM\\CurrentControlSet\\Services\\bam\\State\\UserSettings','HKLM:\\SYSTEM\\CurrentControlSet\\Services\\bam\\UserSettings')) {\n        if (-not (Test-Path $root)) { continue }\n        foreach ($sidKey in (Get-ChildItem $root -ErrorAction SilentlyContinue)) {\n            $props = Get-ItemProperty $sidKey.PSPath -ErrorAction SilentlyContinue\n            if (-not $props) { continue }\n            foreach ($pr in $props.PSObject.Properties) {\n                if ($pr.Name -notlike '\\Device\\*') { continue }\n                $b = $pr.Value\n                if (-not ($b -is [byte[]]) -or $b.Length -lt 8) { continue }\n                $bam += [PSCustomObject]@{ Zeit = [DateTime]::FromFileTime([BitConverter]::ToInt64($b,0)); Pfad = (&amp; $konvDev $pr.Name) }\n            }\n        }\n    }\n\n    # ============================================================\n    # Schritt 1: Start der Fernwartung finden\n    # ============================================================\n    Write-Host \"`n--- Schritt 1: Fernwartungs-Start finden ---\" -ForegroundColor DarkGray\n    $anker = @()\n    foreach ($e in ($bam | Where-Object { $_.Pfad -match $fwMuster })) {\n        $anker += [PSCustomObject]@{ Zeit=$e.Zeit; Quelle='BAM (letzter Start)'; Info=$e.Pfad }\n    }\n    Get-ChildItem \"$env:SystemRoot\\Prefetch\\*.pf\" -ErrorAction SilentlyContinue | Where-Object { $_.Name -match $fwMuster } | ForEach-Object {\n        $anker += [PSCustomObject]@{ Zeit=$_.CreationTime;  Quelle='Prefetch (erster Start)'; Info=$_.Name }\n        $anker += [PSCustomObject]@{ Zeit=$_.LastWriteTime; Quelle='Prefetch (letzter Start)'; Info=$_.Name }\n    }\n    Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Firewall With Advanced Security/Firewall';Id=2004,2071,2097} -MaxEvents 2000 -ErrorAction SilentlyContinue |\n        Where-Object { $_.Message -match $fwMuster } | ForEach-Object {\n            $anker += [PSCustomObject]@{ Zeit=$_.TimeCreated; Quelle='Firewall-Regel angelegt'; Info=(&amp; $kurz $_.Message 110) }\n        }\n    $rdLogs = @(\"$env:SystemRoot\\System32\\config\\systemprofile\\AppData\\Roaming\\RustDesk\\log\",\n                \"$env:SystemRoot\\ServiceProfiles\\LocalService\\AppData\\Roaming\\RustDesk\\log\",\n                \"$env:ProgramData\\RustDesk\")\n    Get-ChildItem 'C:\\Users' -Directory -ErrorAction SilentlyContinue | ForEach-Object { $rdLogs += (Join-Path $_.FullName 'AppData\\Roaming\\RustDesk\\log') }\n    foreach ($lp in $rdLogs) {\n        if (-not (Test-Path $lp)) { continue }\n        Get-ChildItem $lp -Recurse -File -ErrorAction SilentlyContinue | ForEach-Object {\n            $anker += [PSCustomObject]@{ Zeit=$_.LastWriteTime; Quelle='RustDesk-Log'; Info=$_.FullName }\n        }\n    }\n\n    $anker = @($anker | Sort-Object Zeit)\n    $standardStart = $null\n    if ($anker.Count -gt 0) {\n        Write-Host \"  Gefundene Fernwartungs-Spuren:\" -ForegroundColor Red\n        foreach ($a in $anker) {\n            Write-Host (\"  [{0}] {1,-26} {2}\" -f $a.Zeit.ToString('dd.MM.yyyy HH:mm:ss'), $a.Quelle, $a.Info) -ForegroundColor Red\n        }\n        $standardStart = $anker[0].Zeit.AddMinutes(-15)\n    } else {\n        Write-Host \"  Keine Fernwartungs-Spuren gefunden (BAM, Prefetch, Firewall, RustDesk-Logs).\" -ForegroundColor Yellow\n        Write-Host \"  Startzeit bitte manuell eingeben (z. B. den Zeitpunkt, den der Spieler nennt).\" -ForegroundColor DarkGray\n    }\n\n    $vorschlag = if ($standardStart) { $standardStart.ToString('dd.MM.yyyy HH:mm') } else { 'keiner' }\n    $eingabe = Read-Host \"`nStartzeit der Timeline (Enter = $vorschlag | Format: 21.09.2026 20:15)\"\n    if ([string]::IsNullOrWhiteSpace($eingabe)) {\n        if (-not $standardStart) { Write-Host \"Keine Startzeit - Abbruch.\" -ForegroundColor Yellow; return }\n        $von = $standardStart\n    } else {\n        $dtIn = [DateTime]::MinValue\n        if (-not [DateTime]::TryParse($eingabe, [Globalization.CultureInfo]::GetCultureInfo('de-DE'), [Globalization.DateTimeStyles]::None, [ref]$dtIn)) {\n            Write-Host \"Datum nicht erkannt: $eingabe\" -ForegroundColor Red; return\n        }\n        $von = $dtIn\n    }\n    $hIn = Read-Host \"Zeitfenster in Stunden (Enter = 6)\"\n    $stunden = 6\n    if ($hIn -match '^\\d+$') { $stunden = [int]$hIn }\n    $bis = $von.AddHours($stunden)\n    Write-Host (\"`n  Zeitfenster: {0} bis {1}\" -f $von.ToString('dd.MM.yyyy HH:mm'), $bis.ToString('dd.MM.yyyy HH:mm')) -ForegroundColor Cyan\n\n    # ============================================================\n    # Schritt 2: Alle Quellen im Zeitfenster sammeln\n    # ============================================================\n    $tl  = New-Object System.Collections.Generic.List[object]\n    $eigenStarts   = New-Object System.Collections.Generic.List[datetime]\n    $addTypeMuster = '(?i)^[a-z0-9]{8}\\.(dll|pdb|cs|0\\.cs|cmdline|out|err)$'\n    $mbInstalliert = Test-Path \"$env:ProgramData\\Malwarebytes\"\n    $nahEigen = {\n        param($z)\n        foreach ($es in $eigenStarts) { $d = ($z - $es).TotalSeconds; if ($d -ge -5 -and $d -le 300) { return $true } }\n        return $false\n    }\n    $add = {\n        param($z, [string]$q, [string]$i, [string]$s)\n        if ($z -and $z -ge $von -and $z -le $bis) { $tl.Add([PSCustomObject]@{ Zeit=$z; Quelle=$q; Info=$i; Stufe=$s }) }\n    }\n    Write-Host \"  Sammle Spuren...\" -ForegroundColor DarkGray\n\n    # a) BAM\n    foreach ($e in $bam) {\n        if ($e.Zeit -lt $von -or $e.Zeit -gt $bis) { continue }\n        $weg  = ($e.Pfad -match '^[A-Z]:\\\\') -and -not (Test-Path -LiteralPath $e.Pfad)\n        $info = $e.Pfad; if ($weg) { $info += '  [GELOESCHT]' }\n        $s = 'Info'\n        if ($e.Pfad -match $fwMuster) { $s = 'Rot' }\n        elseif ($weg -or $e.Pfad -match '(?i)\\\\(Temp|Downloads|Desktop)\\\\') { $s = 'Gelb' }\n        &amp; $add $e.Zeit 'Programm (BAM)' $info $s\n    }\n\n    # b) Prefetch\n    $lolbins = '(?i)^(POWERSHELL|PWSH|CMD|WSCRIPT|CSCRIPT|MSHTA|RUNDLL32|REGSVR32|CERTUTIL|BITSADMIN|CURL|SC|REG|SCHTASKS|WEVTUTIL|BCDEDIT|NET|NET1|WMIC)\\.EXE$'\n    Get-ChildItem \"$env:SystemRoot\\Prefetch\\*.pf\" -ErrorAction SilentlyContinue | ForEach-Object {\n        $exe = $_.BaseName -replace '-[0-9A-F]{8}$',''\n        $s = if ($exe -match $fwMuster) { 'Rot' } elseif ($exe -match $lolbins) { 'Gelb' } else { 'Info' }\n        &amp; $add $_.CreationTime 'Prefetch (erster Start)' $exe $s\n        if ($_.LastWriteTime -ne $_.CreationTime) { &amp; $add $_.LastWriteTime 'Prefetch (letzter Start)' $exe $s }\n    }\n\n    # c) PowerShell-Starts (EID 400/600 HostApplication)\n    Get-WinEvent -FilterHashtable @{LogName='Windows PowerShell';Id=400,600;StartTime=$von;EndTime=$bis} -ErrorAction SilentlyContinue | ForEach-Object {\n        if ($_.Message -match 'HostApplication=(.+?)(\\r?\\n|$)') {\n            $cmd = $matches[1].Trim()\n            if ($cmd -match $eigenCode) { $eigenStarts.Add($_.TimeCreated); return }\n            $s = if ($cmd -match $verdPS) { 'Rot' } else { 'Gelb' }\n            &amp; $add $_.TimeCreated 'PowerShell-Start' (&amp; $kurz $cmd 220) $s\n        }\n    }\n\n    # d) PowerShell-Code (EID 4104)\n    Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational';Id=4104;StartTime=$von;EndTime=$bis} -ErrorAction SilentlyContinue | ForEach-Object {\n        $ev = $_\n        $d  = ([xml]$ev.ToXml()).Event.EventData.Data\n        $nr   = ($d | Where-Object { $_.Name -eq 'MessageNumber' }).'#text'\n        $code = ($d | Where-Object { $_.Name -eq 'ScriptBlockText' }).'#text'\n        if ($nr -ne '1' -or -not $code) { return }\n        if ($code -match $eigenCode -or $code -match '^\\s*#requires -version 3\\.0' -or $code -match 'PSConsoleHostReadLine') { return }\n        $s = if ($code -match $verdPS) { 'Rot' } else { 'Gelb' }\n        &amp; $add $ev.TimeCreated 'PowerShell-Code (4104)' (&amp; $kurz $code 220) $s\n    }\n\n    # e) Microsoft Defender\n    Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Defender/Operational';Id=1116,1117,1118,1119,5001,5004,5007,5010,5012,5013;StartTime=$von;EndTime=$bis} -ErrorAction SilentlyContinue | ForEach-Object {\n        $ev = $_\n        $m  = $ev.Message\n        $info = switch ($ev.Id) {\n            { $_ -in 1116,1117,1118,1119 } { 'Erkennung/Aktion: ' + (&amp; $kurz $m 200) }\n            5001 { 'ECHTZEITSCHUTZ DEAKTIVIERT' }\n            5004 { 'Echtzeitschutz-Konfiguration geaendert' }\n            5007 { if ($m -match '(New value|Neuer Wert):\\s*(.+?)(\\r?\\n|$)') { 'Konfig geaendert -&gt; ' + $matches[2].Trim() } else { 'Konfig geaendert: ' + (&amp; $kurz $m 160) } }\n            5010 { 'Malware-Scan deaktiviert' }\n            5012 { 'Virenscan deaktiviert' }\n            5013 { 'Manipulationsschutz hat Aenderung blockiert' }\n            default { &amp; $kurz $m 160 }\n        }\n        $s = if ($ev.Id -in 5001,5010,5012 -or $info -match '(?i)Exclusion') { 'Rot' } else { 'Gelb' }\n        &amp; $add $ev.TimeCreated 'Defender' $info $s\n    }\n\n    # f) Dienste / Treiber installiert (System 7045)\n    Get-WinEvent -FilterHashtable @{LogName='System';Id=7045;StartTime=$von;EndTime=$bis} -ErrorAction SilentlyContinue | ForEach-Object {\n        $ev = $_\n        $d  = ([xml]$ev.ToXml()).Event.EventData.Data\n        $n   = ($d | Where-Object { $_.Name -eq 'ServiceName' }).'#text'\n        $img = ($d | Where-Object { $_.Name -eq 'ImagePath' }).'#text'\n        $typ = ($d | Where-Object { $_.Name -eq 'ServiceType' }).'#text'\n        $s = if ($typ -match '(?i)kernel|treiber' -or $img -notmatch '(?i)\\\\Windows\\\\|\\\\Program Files') { 'Rot' } else { 'Gelb' }\n        &amp; $add $ev.TimeCreated 'Dienst installiert' (\"{0} | {1} | {2}\" -f $n, $typ, $img) $s\n    }\n\n    # g) Geplante Aufgaben + Security-Log (falls Auditing aktiv)\n    Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-TaskScheduler/Operational';Id=106,140,141;StartTime=$von;EndTime=$bis} -ErrorAction SilentlyContinue | ForEach-Object {\n        &amp; $add $_.TimeCreated 'Geplante Aufgabe' (&amp; $kurz $_.Message 180) 'Gelb'\n    }\n    Get-WinEvent -FilterHashtable @{LogName='Security';Id=4688,4698,1102;StartTime=$von;EndTime=$bis} -MaxEvents 5000 -ErrorAction SilentlyContinue | ForEach-Object {\n        $ev = $_\n        if ($ev.Id -eq 4688) {\n            $d  = ([xml]$ev.ToXml()).Event.EventData.Data\n            $np = ($d | Where-Object { $_.Name -eq 'NewProcessName' }).'#text'\n            $cl = ($d | Where-Object { $_.Name -eq 'CommandLine' }).'#text'\n            $txt = if ($cl) { $cl } else { $np }\n            if ($txt -match $eigenCode) { return }\n            $s = if ($txt -match $verdPS) { 'Rot' } elseif ($txt -match '(?i)powershell|cmd\\.exe|mshta|rundll32|regsvr32|certutil|bitsadmin|curl') { 'Gelb' } else { 'Info' }\n            &amp; $add $ev.TimeCreated 'Prozess (4688)' (&amp; $kurz $txt 220) $s\n        } elseif ($ev.Id -eq 4698) {\n            &amp; $add $ev.TimeCreated 'Aufgabe erstellt (4698)' (&amp; $kurz $ev.Message 180) 'Rot'\n        } else {\n            &amp; $add $ev.TimeCreated 'SECURITY-LOG GELEERT' '1102' 'Rot'\n        }\n    }\n\n    # h) Log geleert, Zeit verstellt, Firewall, CodeIntegrity, Geraete\n    Get-WinEvent -FilterHashtable @{LogName='System';Id=104;StartTime=$von;EndTime=$bis} -ErrorAction SilentlyContinue | ForEach-Object {\n        &amp; $add $_.TimeCreated 'LOG GELEERT' ([string]$_.Properties[2].Value) 'Rot'\n    }\n    Get-WinEvent -FilterHashtable @{LogName='System';Id=1;ProviderName='Microsoft-Windows-Kernel-General';StartTime=$von;EndTime=$bis} -ErrorAction SilentlyContinue | ForEach-Object {\n        $pn = (([xml]$_.ToXml()).Event.EventData.Data | Where-Object { $_.Name -eq 'ProcessName' }).'#text'\n        if ($pn -notmatch '(?i)svchost\\.exe$') { &amp; $add $_.TimeCreated 'Systemzeit geaendert' (\"durch \" + $pn) 'Rot' }\n    }\n    Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Firewall With Advanced Security/Firewall';Id=2004,2006,2052,2071,2097;StartTime=$von;EndTime=$bis} -ErrorAction SilentlyContinue | ForEach-Object {\n        $s = if ($_.Message -match $fwMuster) { 'Rot' } else { 'Gelb' }\n        $q = if ($_.Id -in 2006,2052) { 'Firewall-Regel geloescht' } else { 'Firewall-Regel angelegt' }\n        &amp; $add $_.TimeCreated $q (&amp; $kurz $_.Message 160) $s\n    }\n    Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-CodeIntegrity/Operational';Id=3033,3034,3077;StartTime=$von;EndTime=$bis} -ErrorAction SilentlyContinue |\n        Where-Object { $_.Message -notmatch '(?i)mbae|mbamsi|mbamswissarmy|hmpalert' } | ForEach-Object {\n            &amp; $add $_.TimeCreated 'CodeIntegrity blockiert' (&amp; $kurz $_.Message 180) 'Rot'\n        }\n    Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Kernel-PnP/Configuration';Id=400,420;StartTime=$von;EndTime=$bis} -ErrorAction SilentlyContinue | ForEach-Object {\n        $ev = $_\n        $dev = (([xml]$ev.ToXml()).Event.EventData.Data | Where-Object { $_.Name -eq 'DeviceInstanceId' }).'#text'\n        if (-not $dev -or $dev -match 'MMDEVAPI') { return }\n        $s = if ($dev -match '(?i)VID_1A86|VID_303A|VID_2341|VID_0000|VID_301A|^PCI\\\\') { 'Gelb' } else { 'Info' }\n        $q = if ($ev.Id -eq 420) { 'Geraet entfernt' } else { 'Geraet konfiguriert' }\n        &amp; $add $ev.TimeCreated $q $dev $s\n    }\n\n    # i) PowerShell-History-Dateien, die im Fenster geschrieben wurden (inkl. SYSTEM-Profil)\n    $histDateien = @()\n    Get-ChildItem 'C:\\Users' -Directory -ErrorAction SilentlyContinue | ForEach-Object {\n        $histDateien += [PSCustomObject]@{ Wer=$_.Name; Pfad=(Join-Path $_.FullName 'AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadLine\\ConsoleHost_history.txt') }\n    }\n    $sysProfile = [ordered]@{\n        'SYSTEM'         = \"$env:SystemRoot\\System32\\config\\systemprofile\"\n        'SYSTEM (32bit)' = \"$env:SystemRoot\\SysWOW64\\config\\systemprofile\"\n        'LocalService'   = \"$env:SystemRoot\\ServiceProfiles\\LocalService\"\n        'NetworkService' = \"$env:SystemRoot\\ServiceProfiles\\NetworkService\"\n    }\n    foreach ($k in $sysProfile.Keys) {\n        $histDateien += [PSCustomObject]@{ Wer=$k; Pfad=(Join-Path $sysProfile[$k] 'AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadLine\\ConsoleHost_history.txt') }\n    }\n    foreach ($h in $histDateien) {\n        if (Test-Path -LiteralPath $h.Pfad) {\n            $fi = Get-Item -LiteralPath $h.Pfad -Force\n            $s = if ($h.Wer -match 'SYSTEM|Service') { 'Rot' } else { 'Gelb' }\n            &amp; $add $fi.LastWriteTime 'PS-History geschrieben' (\"{0} ({1} Bytes)\" -f $h.Wer, $fi.Length) $s\n        }\n    }\n\n    # j) Win+R Verlauf (RunMRU) - letzter Eintrag hat Zeitstempel\n    $runEintraege = @()\n    Get-ChildItem 'Registry::HKEY_USERS' -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -match '^S-1-5-21-[\\d-]+$' } | ForEach-Object {\n        $sidAkt = $_.PSChildName\n        $rk = \"Registry::HKEY_USERS\\$sidAkt\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU\"\n        if (-not (Test-Path $rk)) { return }\n        $p = Get-ItemProperty $rk -ErrorAction SilentlyContinue\n        if (-not $p -or -not $p.MRUList) { return }\n        $letzte = &amp; $keyZeit $rk\n        $pos = 0\n        foreach ($ch in $p.MRUList.ToCharArray()) {\n            $wert = ([string]$p.([string]$ch)) -replace '\\\\1$',''\n            $runEintraege += [PSCustomObject]@{ SID=$sidAkt; Pos=$pos; Wert=$wert; Zeit=$(if ($pos -eq 0) { $letzte } else { $null }) }\n            $pos++\n        }\n        $erster = $runEintraege | Where-Object { $_.SID -eq $sidAkt -and $_.Pos -eq 0 } | Select-Object -First 1\n        if ($letzte -and $erster) {\n            $s = if ($erster.Wert -match $verdPS -or $erster.Wert -match '(?i)powershell|cmd|mshta') { 'Rot' } else { 'Gelb' }\n            &amp; $add $letzte 'Win+R (letzte Eingabe)' $erster.Wert $s\n        }\n    }\n\n    # j2) Geplante Aufgaben direkt aus System32\\Tasks (Task-Log ist standardmaessig deaktiviert)\n    $taskRoot = \"$env:SystemRoot\\System32\\Tasks\"\n    Get-ChildItem $taskRoot -Recurse -File -Force -ErrorAction SilentlyContinue | ForEach-Object {\n        $f = $_\n        $cmdT = ''\n        try {\n            [xml]$tx = Get-Content -LiteralPath $f.FullName -Raw -ErrorAction Stop\n            $ex = @($tx.Task.Actions.Exec)[0]\n            if ($ex) { $cmdT = (\"{0} {1}\" -f $ex.Command, $ex.Arguments).Trim() }\n        } catch {}\n        $s = if ($cmdT -match $verdPS -or $cmdT -match '(?i)\\\\Temp\\\\|\\\\AppData\\\\|\\\\ProgramData\\\\|\\\\Users\\\\Public\\\\|powershell|cmd\\.exe|mshta|rundll32') { 'Rot' } else { 'Gelb' }\n        $kurzName = $f.FullName.Substring($taskRoot.Length)\n        &amp; $add $f.CreationTime 'Aufgabe angelegt' (\"{0} -&gt; {1}\" -f $kurzName, $cmdT) $s\n        if ($f.LastWriteTime -ne $f.CreationTime) { &amp; $add $f.LastWriteTime 'Aufgabe geaendert' (\"{0} -&gt; {1}\" -f $kurzName, $cmdT) $s }\n    }\n\n    # k) Neu angelegte Dateien im Fenster\n    Write-Host \"  Suche neu angelegte Dateien im Zeitfenster...\" -ForegroundColor DarkGray\n    $extMuster = '(?i)\\.(exe|dll|sys|ps1|bat|cmd|vbs|js|hta|msi|zip|rar|7z|asi|lua)$'\n    $orte = @(\"$env:ProgramData\", \"$env:SystemRoot\\Temp\", \"$env:SystemRoot\\System32\\drivers\", \"$env:SystemRoot\\System32\\wbem\")\n    Get-ChildItem 'C:\\Users' -Directory -ErrorAction SilentlyContinue | ForEach-Object {\n        $orte += @((Join-Path $_.FullName 'Desktop'), (Join-Path $_.FullName 'Downloads'), (Join-Path $_.FullName 'Documents'), (Join-Path $_.FullName 'AppData'))\n    }\n    foreach ($ort in $orte) {\n        if (-not (Test-Path $ort)) { continue }\n        Get-ChildItem $ort -Recurse -Depth 4 -File -Force -ErrorAction SilentlyContinue |\n            Where-Object { $_.Name -match $extMuster -and (($_.CreationTime -ge $von -and $_.CreationTime -le $bis) -or ($_.LastWriteTime -ge $von -and $_.LastWriteTime -le $bis)) } |\n            ForEach-Object {\n                $z = if ($_.CreationTime -ge $von -and $_.CreationTime -le $bis) { $_.CreationTime } else { $_.LastWriteTime }\n                if ($_.FullName -match '(?i)\\\\Malwarebytes\\\\|\\\\Windows Defender\\\\') { return }\n                if ($_.FullName -match $eigenCode) { return }\n                if ($_.Name -match $addTypeMuster -and (&amp; $nahEigen $z)) { return }\n                $sig = Get-AuthenticodeSignature -LiteralPath $_.FullName -ErrorAction SilentlyContinue\n                $st  = if ($sig) { [string]$sig.Status } else { '?' }\n                $s = if ($st -ne 'Valid') { 'Rot' } else { 'Info' }\n                &amp; $add $z 'Datei angelegt' (\"{0}  [Sig: {1}]\" -f $_.FullName, $st) $s\n            }\n    }\n    Get-ChildItem \"$env:SystemRoot\\System32\" -File -Force -ErrorAction SilentlyContinue |\n        Where-Object { $_.Name -match $extMuster -and $_.CreationTime -ge $von -and $_.CreationTime -le $bis } | ForEach-Object {\n            $sig = Get-AuthenticodeSignature -LiteralPath $_.FullName -ErrorAction SilentlyContinue\n            $st  = if ($sig) { [string]$sig.Status } else { '?' }\n            $s = if ($st -ne 'Valid') { 'Rot' } else { 'Gelb' }\n            &amp; $add $_.CreationTime 'Datei in System32' (\"{0}  [Sig: {1}]\" -f $_.FullName, $st) $s\n        }\n\n    # l) USN-Journal (optional) - zeigt auch GELOESCHTE Dateien\n    $usnWahl = Read-Host \"`nUSN-Journal durchsuchen? Zeigt auch GELOESCHTE Dateien im Zeitfenster (1-5 Min) [j/N]\"\n    if ($usnWahl -match '^[jJyY]') {\n        Write-Host \"  Lese USN-Journal (C:)...\" -ForegroundColor DarkGray\n        $kopf = @(&amp; fsutil usn readjournal C: csv 2&gt;$null | Select-Object -First 8)\n        $hdrZeile = $kopf | Where-Object { $_ -match ',' -and $_ -match '(?i)usn' } | Select-Object -First 1\n        if (-not $hdrZeile) {\n            Write-Host \"  USN-Journal nicht lesbar (deaktiviert, geloescht oder fsutil zu alt).\" -ForegroundColor Yellow\n        } else {\n            $cols = @($hdrZeile -split ',' | ForEach-Object { $_.Trim().Trim('\"') })\n            $iName = -1; $iGrund = -1; $iZeit = -1\n            for ($c = 0; $c -lt $cols.Count; $c++) {\n                if ($iName  -lt 0 -and $cols[$c] -match '(?i)^(file ?name|dateiname)$') { $iName = $c }\n                if ($iGrund -lt 0 -and $cols[$c] -match '(?i)^(reason|grund|ursache)$') { $iGrund = $c }\n                if ($iZeit  -lt 0 -and $cols[$c] -match '(?i)^(time ?stamp|zeitstempel)$') { $iZeit = $c }\n            }\n            if ($iName -lt 0 -or $iZeit -lt 0) {\n                Write-Host \"  USN-Spalten nicht erkannt: $hdrZeile\" -ForegroundColor Yellow\n            } else {\n                $usnExt = '(?i)\\.(exe|dll|sys|ps1|bat|cmd|vbs|js|hta|msi|zip|rar|7z|asi)\\b'\n                $zeilen = @(&amp; fsutil usn readjournal C: csv 2&gt;$null | Select-String -Pattern $usnExt | ForEach-Object { $_.Line })\n                Write-Host (\"  {0} Journal-Eintraege mit ausfuehrbaren Endungen - filtere Zeitfenster...\" -f $zeilen.Count) -ForegroundColor DarkGray\n                $hdrNamen = @(0..($cols.Count - 1) | ForEach-Object { \"c$_\" })\n                $usnN = 0\n                foreach ($r in ($zeilen | ConvertFrom-Csv -Header $hdrNamen)) {\n                    $werte = @($r.PSObject.Properties.Value)\n                    $dtU = [DateTime]::MinValue\n                    if (-not [DateTime]::TryParse([string]$werte[$iZeit], [ref]$dtU)) { continue }\n                    if ($dtU -lt $von -or $dtU -gt $bis) { continue }\n                    $grund = if ($iGrund -ge 0) { [string]$werte[$iGrund] } else { '' }\n                    # 'l.{1,2}sch' faengt 'loeschen' auch bei kaputter Umlaut-Kodierung der deutschen fsutil-Ausgabe\n                    if ($grund -notmatch '(?i)create|delete|rename|erstell|l.{1,2}sch|umbenenn') { continue }\n                    $name = [string]$werte[$iName]\n                    if ($name -match '^~|\\.tmp$') { continue }\n                    if ($name -notmatch '(?i)\\.(exe|dll|sys|ps1|bat|cmd|vbs|js|hta|msi|zip|rar|7z|asi)$') { continue }\n                    if ($name -match '(?i)^__PSScriptPolicyTest_') { continue }\n                    if ($mbInstalliert -and $name -match '(?i)^[0-9a-f]{32}\\.zip$') { continue }\n                    if ($name -match $eigenCode) { continue }\n                    $istLoesch = $grund -match '(?i)delete|l.{1,2}sch'\n                    $quelleU = if ($istLoesch) { 'USN: GELOESCHT' } else { 'USN-Journal' }\n                    if ($name -match $addTypeMuster) {\n                        if (&amp; $nahEigen $dtU) { continue }\n                        $quelleU = 'USN: C#-Kompilat (Add-Type)'\n                        $s = 'Rot'\n                    } else {\n                        $s = if ($istLoesch -and $name -match '(?i)\\.(exe|ps1|bat|cmd|vbs|js|hta|sys|zip|rar|7z|asi)$') { 'Rot' } else { 'Gelb' }\n                    }\n                    &amp; $add $dtU $quelleU (\"{0}  ({1})\" -f $name, (&amp; $kurz $grund 60)) $s\n                    $usnN++\n                }\n                Write-Host \"  $usnN USN-Eintraege im Zeitfenster uebernommen.\" -ForegroundColor DarkGray\n            }\n        }\n    }\n\n    # ============================================================\n    # Schritt 3: Timeline ausgeben + exportieren\n    # ============================================================\n    foreach ($eintrag in $tl) {\n        $cn = Get-CheatName $eintrag.Info\n        if ($cn) { $eintrag.Stufe = 'Rot'; $eintrag.Quelle = \"CHEAT-NAME '$cn' | \" + $eintrag.Quelle }\n    }\n    $ergebnis = @($tl | Group-Object { '{0}|{1}|{2}' -f $_.Zeit.ToString('yyyyMMddHHmmss'), $_.Quelle, $_.Info } | ForEach-Object { $_.Group[0] } | Sort-Object Zeit)\n    $nRot  = @($ergebnis | Where-Object { $_.Stufe -eq 'Rot' }).Count\n    $nGelb = @($ergebnis | Where-Object { $_.Stufe -eq 'Gelb' }).Count\n    Write-Host (\"`n=== Timeline: {0} Eintraege | {1} rot | {2} gelb ===\" -f $ergebnis.Count, $nRot, $nGelb) -ForegroundColor Cyan\n    $nurWichtig = Read-Host \"Nur rote und gelbe Eintraege anzeigen? [J/n]\"\n    $zeigen = if ($nurWichtig -match '^[nN]') { $ergebnis } else { @($ergebnis | Where-Object { $_.Stufe -ne 'Info' }) }\n    foreach ($e in $zeigen) {\n        $col = switch ($e.Stufe) { 'Rot' { 'Red' } 'Gelb' { 'Yellow' } default { 'DarkGray' } }\n        Write-Host (\"  [{0}] {1,-24} {2}\" -f $e.Zeit.ToString('dd.MM HH:mm:ss'), $e.Quelle, $e.Info) -ForegroundColor $col\n    }\n    $csv = \"$env:USERPROFILE\\Desktop\\ctc_timeline_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv\"\n    try {\n        $ergebnis | Select-Object @{n='Zeit';e={ $_.Zeit.ToString('dd.MM.yyyy HH:mm:ss') }}, Quelle, Stufe, Info |\n            Export-Csv -Path $csv -NoTypeInformation -Encoding UTF8 -Delimiter ';'\n        Write-Host \"`n  Vollstaendige Timeline gespeichert: $csv\" -ForegroundColor Green\n    } catch {\n        Write-Host \"  CSV-Export fehlgeschlagen.\" -ForegroundColor DarkGray\n    }\n\n    # ============================================================\n    # Schritt 4: Zeitunabhaengige Einrichtungs-Spuren\n    # ============================================================\n    Write-Host \"`n=== Einrichtungs-Spuren (unabhaengig vom Zeitfenster) ===\" -ForegroundColor Cyan\n\n    Write-Host \"`n--- Microsoft Defender: Status &amp; Ausnahmen ---\" -ForegroundColor DarkGray\n    try {\n        $st = Get-MpComputerStatus -ErrorAction Stop\n        $avs = @(Get-CimInstance -Namespace 'root/SecurityCenter2' -ClassName AntiVirusProduct -ErrorAction SilentlyContinue | Select-Object -ExpandProperty displayName)\n        $fremdAV = @($avs | Where-Object { $_ -notmatch '(?i)Windows Defender|Microsoft Defender' })\n        $colSt = if ($st.RealTimeProtectionEnabled -or $fremdAV.Count -gt 0) { 'Green' } else { 'Red' }\n        Write-Host (\"  Echtzeitschutz: {0} | Manipulationsschutz: {1} | Dienst: {2}\" -f $st.RealTimeProtectionEnabled, $st.IsTamperProtected, $st.AMServiceEnabled) -ForegroundColor $colSt\n        if ($avs.Count -gt 0) { Write-Host (\"  Registrierter Virenschutz: {0}\" -f ($avs -join ', ')) -ForegroundColor DarkGray }\n        if (-not $st.RealTimeProtectionEnabled) {\n            if ($fremdAV.Count -gt 0) {\n                Write-Host \"  Defender ist passiv, weil ein anderer Virenschutz aktiv ist - normal.\" -ForegroundColor DarkGray\n            } else {\n                Write-Host \"  [!] Echtzeitschutz AUS und kein anderer Virenschutz - Defender wurde abgeschaltet!\" -ForegroundColor Red\n            }\n        }\n    } catch {\n        Write-Host \"  Defender-Status nicht abfragbar (anderer Virenschutz aktiv?).\" -ForegroundColor DarkGray\n    }\n    try {\n        $mp = Get-MpPreference -ErrorAction Stop\n        $ausn = @()\n        foreach ($feld in 'ExclusionPath','ExclusionProcess','ExclusionExtension','ExclusionIpAddress') {\n            foreach ($v in @($mp.$feld)) { if ($v -and $v -notmatch '^N/A') { $ausn += [PSCustomObject]@{ Typ=$feld; Wert=$v } } }\n        }\n        if ($ausn.Count -gt 0) {\n            Write-Host \"  [!] $($ausn.Count) Defender-Ausnahme(n):\" -ForegroundColor Red\n            $ausn | ForEach-Object { Write-Host (\"    {0,-20} {1}\" -f $_.Typ, $_.Wert) -ForegroundColor Red }\n            Write-Host \"    Ausnahmen fuer Temp/AppData/ProgramData oder einzelne EXEs = typischer Schritt beim Cheat-Einrichten.\" -ForegroundColor DarkGray\n        } else {\n            Write-Host \"  Keine Defender-Ausnahmen.\" -ForegroundColor Green\n        }\n    } catch {\n        Write-Host \"  Defender-Ausnahmen nicht lesbar.\" -ForegroundColor DarkGray\n    }\n\n    Write-Host \"`n--- Ausfuehren-Dialog (Win+R), neueste zuerst ---\" -ForegroundColor DarkGray\n    if ($runEintraege.Count -gt 0) {\n        foreach ($r in $runEintraege) {\n            $col = if ($r.Wert -match $verdPS -or $r.Wert -match '(?i)powershell|cmd|mshta|%temp%|appdata') { 'Red' } else { 'White' }\n            $zeitTxt = if ($r.Zeit) { \" (zuletzt {0})\" -f $r.Zeit } else { '' }\n            Write-Host (\"    {0}{1}\" -f $r.Wert, $zeitTxt) -ForegroundColor $col\n        }\n    } else {\n        Write-Host \"  Kein Win+R-Verlauf (leer oder geloescht).\" -ForegroundColor DarkGray\n    }\n\n    Write-Host \"`n--- PowerShell-History in System- und Dienstprofilen ---\" -ForegroundColor DarkGray\n    Write-Host \"(Befehle, die als SYSTEM liefen - z. B. ueber einen Fernwartungsdienst - landen NICHT in C:\\Users)\" -ForegroundColor DarkGray\n    $sysGefunden = $false\n    foreach ($h in ($histDateien | Where-Object { $_.Wer -match 'SYSTEM|Service' })) {\n        if (-not (Test-Path -LiteralPath $h.Pfad)) { continue }\n        $sysGefunden = $true\n        $fi = Get-Item -LiteralPath $h.Pfad -Force\n        Write-Host (\"  [!] {0} - geaendert {1}:\" -f $h.Wer, $fi.LastWriteTime) -ForegroundColor Red\n        Get-Content -LiteralPath $h.Pfad -ErrorAction SilentlyContinue | Select-Object -Last 50 | ForEach-Object {\n            $col = if ($_ -match $verdPS) { 'Red' } else { 'White' }\n            Write-Host \"    $_\" -ForegroundColor $col\n        }\n    }\n    if (-not $sysGefunden) { Write-Host \"  Keine History in System-/Dienstprofilen.\" -ForegroundColor Green }\n\n    Write-Host \"`nAuswertung:\" -ForegroundColor DarkGray\n    Write-Host \"  Typischer Ablauf: Fernwartung startet -&gt; Defender-Ausnahme / Schutz aus -&gt; Download (irm/iwr/Browser)\" -ForegroundColor DarkGray\n    Write-Host \"  -&gt; Loader/Treiber (neue Datei, Dienst 7045) -&gt; Aufraeumen (USN-Loeschungen, Log geleert/verkleinert).\" -ForegroundColor DarkGray\n    Write-Host \"  Fehlen die Befehle selbst, zaehlen die Wirkungen: Ausnahmen, neue Dateien, Dienste, Loeschungen.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  20 - Handy-Fernsteuerung / Web-Panel\n# ============================================================\nfunction Invoke-RemoteControlCheck {\n    param([switch]$OhneFrage)\n\n    Write-Host \"`n=== Fernsteuerung per Handy / Web-Panel ===\" -ForegroundColor Cyan\n    Write-Host \"(Lauschende Ports, Verbindungen aus dem Heimnetz, Firewall-Freigaben, Hotspot, Cloud-Verbindungen)\" -ForegroundColor DarkGray\n\n    $begriff = $null   # kein Suchbegriff - Cheats tragen ihren Namen nicht in Pfaden oder Domains\n\n    $privatNetz     = '^(10\\.|192\\.168\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|169\\.254\\.|fe80:|fd|fc)'\n    $bekannteSigner = '(?i)Valve|NVIDIA|Discord|Spotify|Google|Razer|Logitech|Corsair|Elgato|Adobe|Malwarebytes|Epic Games|Riot|Medal|sipgate|OBS Project|TC-Helicon|Skillbrains|Electronic Arts|Ubisoft|Rockstar|Cfx|Intel|Advanced Micro|Realtek|Mozilla|Opera|Brave|Microsoft|Apple|Dropbox|Zoom|TeamSpeak|Overwolf|SteelSeries|Turtle Beach|Nahimic|ASUSTeK|Micro-Star|Gigabyte'\n\n    $sigCache = @{}\n    $pruefe = {\n        param([string]$pfad)\n        if (-not $pfad) { return [PSCustomObject]@{ Status='?'; Signierer='-'; MS=$false; Bekannt=$false } }\n        if ($sigCache.ContainsKey($pfad)) { return $sigCache[$pfad] }\n        $sig = $null\n        if (Test-Path -LiteralPath $pfad) { $sig = Get-AuthenticodeSignature -LiteralPath $pfad -ErrorAction SilentlyContinue }\n        $sgn = if ($sig -and $sig.SignerCertificate) { $sig.SignerCertificate.Subject -replace '^(?:.*?,\\s*)?CN=(?:\"([^\"]+)\"|([^,]+)).*$','$1$2' } else { '-' }\n        $ok  = $sig -and $sig.Status -eq 'Valid'\n        $r = [PSCustomObject]@{\n            Status    = $(if ($sig) { [string]$sig.Status } else { 'fehlt' })\n            Signierer = $sgn\n            MS        = ($ok -and $sgn -match '(?i)Microsoft')\n            Bekannt   = ($ok -and $sgn -match $bekannteSigner)\n        }\n        $sigCache[$pfad] = $r\n        $r\n    }\n    $farbe = {\n        param([string]$text, $si)\n        if ($begriff -and $text -match $begriff) { return 'Red' }\n        if ($si.Bekannt) { return 'DarkGray' }\n        if ($si.Status -ne 'Valid') {\n            if ($text -match '(?i)\\\\steamapps\\\\common\\\\') { return 'Yellow' }   # unsignierte Steam-Spiele sind normal\n            return 'Red'\n        }\n        return 'Yellow'\n    }\n    Add-Type -ErrorAction SilentlyContinue -TypeDefinition @\"\nusing System;\nusing System.Text;\nusing System.Runtime.InteropServices;\npublic static class CtcProc {\n    [DllImport(\"kernel32.dll\", SetLastError = true)] static extern IntPtr OpenProcess(uint access, bool inherit, int pid);\n    [DllImport(\"kernel32.dll\")] static extern bool CloseHandle(IntPtr h);\n    [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)]\n    static extern bool QueryFullProcessImageName(IntPtr h, int flags, StringBuilder name, ref int size);\n    public static string Pfad(int pid) {\n        IntPtr h = OpenProcess(0x1000, false, pid);   // QUERY_LIMITED_INFORMATION - klappt auch bei geschuetzten Prozessen\n        if (h == IntPtr.Zero) return null;\n        try { var sb = new StringBuilder(1024); int n = sb.Capacity; return QueryFullProcessImageName(h, 0, sb, ref n) ? sb.ToString() : null; }\n        finally { CloseHandle(h); }\n    }\n}\n\"@\n    $procPfad = {\n        param($proc)\n        if ($proc.Path) { return $proc.Path }\n        try { return [CtcProc]::Pfad([int]$proc.Id) } catch { return $null }\n    }\n    $zufallsMac = {\n        param([string]$mac)\n        if ($mac -match '^[0-9A-Fa-f]([0-9A-Fa-f])') { return '26AE'.Contains($matches[1].ToUpper()) }\n        return $false\n    }\n\n    # Device-Pfad -&gt; Laufwerksbuchstabe (SRUM und WFP speichern \\Device\\HarddiskVolumeX\\...)\n    Add-Type -ErrorAction SilentlyContinue -TypeDefinition @\"\nusing System;\nusing System.Text;\nusing System.Runtime.InteropServices;\npublic static class CtcDos {\n    [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)]\n    public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);\n}\n\"@\n    $devMap = @{}\n    foreach ($cc in 67..90) {\n        $lw = ([string][char]$cc) + ':'\n        $sb = New-Object System.Text.StringBuilder 260\n        try { if ([CtcDos]::QueryDosDevice($lw, $sb, 260) -gt 0) { $devMap[$sb.ToString().ToLower()] = $lw } } catch {}\n    }\n    $konv = {\n        param([string]$p)\n        $pl = $p.ToLower()\n        foreach ($k in $devMap.Keys) {\n            if ($pl.StartsWith($k + '\\')) { return ($devMap[$k] + $p.Substring($k.Length)) }\n        }\n        return $p\n    }\n    $sigRQ3 = '[DllImport(\"advapi32.dll\")]public static extern int RegQueryInfoKey(Microsoft.Win32.SafeHandles.SafeRegistryHandle h,System.Text.StringBuilder a,ref int b,int c,ref int d,ref int e,ref int f,ref int g,ref int i,ref int j,ref int k,ref long l);'\n    Add-Type -MemberDefinition $sigRQ3 -Name RK3 -Namespace W3 -ErrorAction SilentlyContinue\n    $keyZeit = {\n        param($pfad)\n        try {\n            $k = Get-Item $pfad -ErrorAction Stop\n            $t = 0L; $z = 0; $n = New-Object Text.StringBuilder 1024\n            [void][W3.RK3]::RegQueryInfoKey($k.Handle,$n,[ref]$z,0,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$t)\n            [DateTime]::FromFileTime($t)\n        } catch { $null }\n    }\n\n    # Update-Reste: Versions-/Hash-Ordner durch * ersetzen und pruefen, ob eine andere Version existiert\n    $versionWild = {\n        param([string]$pfad)\n        $w = $pfad -replace '(?i)\\\\([a-z_]+-)?\\d+(\\.\\d+)+\\\\', '\\*\\'\n        $w = $w    -replace '(?i)\\\\[^\\\\]*_amd64_[0-9a-f]{16}\\\\', '\\*\\'\n        $w = $w    -replace '(?i)\\\\[0-9a-f]{12,}\\\\', '\\*\\'\n        return $w\n    }\n    $istUpdateRest = {\n        param([string]$pfad)\n        $w = &amp; $versionWild $pfad\n        if ($w -ne $pfad -and (Test-Path $w)) { return $true }\n        if ($pfad -match '^(.+?)\\s+--') {                     # Startparameter im Pfad ('chrome --flag...exe')\n            $b = $matches[1]; if ($b -notmatch '(?i)\\.exe$') { $b += '.exe' }\n            if (Test-Path -LiteralPath $b) { return $true }\n        }\n        return $false\n    }\n    # Installer/Updater, die sich nach getaner Arbeit selbst loeschen\n    $installerMuster = '(?i)\\\\is-[a-z0-9]{5}\\.tmp\\\\|\\\\ns[a-z0-9]{2,8}\\.tmp\\\\|\\\\ghub-|\\\\lghub\\\\|\\\\google\\d+_\\d+\\\\|\\\\ota-artifacts\\\\|\\\\onedrive\\\\update\\\\onedrivesetup\\.exe$|\\\\nvidia corporation\\\\nvidia app\\\\updateframework\\\\'\n\n    # MAC-Adressen im Heimnetz\n    $nachbarn = @{}\n    Get-NetNeighbor -ErrorAction SilentlyContinue |\n        Where-Object { $_.LinkLayerAddress -and $_.LinkLayerAddress -notmatch '^(00-00-00-00-00-00|FF-FF-FF-FF-FF-FF)$' } |\n        ForEach-Object { $nachbarn[[string]$_.IPAddress] = [string]$_.LinkLayerAddress }\n\n    # --- 20a: Lauschende Ports fremder Programme ---\n    Write-Host \"`n--- Lauschende Ports (von anderen Geraeten erreichbar) ---\" -ForegroundColor DarkGray\n    $listen = @()\n    Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue |\n        Where-Object { $_.LocalAddress -notmatch '^(127\\.|::1$)' } |\n        ForEach-Object { $listen += [PSCustomObject]@{ Proto='TCP'; Port=$_.LocalPort; Adr=$_.LocalAddress; ProcId=$_.OwningProcess } }\n    Get-NetUDPEndpoint -ErrorAction SilentlyContinue |\n        Where-Object { $_.LocalAddress -match '^(0\\.0\\.0\\.0|::)$' } |\n        ForEach-Object { $listen += [PSCustomObject]@{ Proto='UDP'; Port=$_.LocalPort; Adr=$_.LocalAddress; ProcId=$_.OwningProcess } }\n\n    $lauschPorts = @{}\n    $lauschFremd = @()\n    foreach ($l in $listen) {\n        $lauschPorts[\"$($l.ProcId)|$($l.Port)\"] = $true\n        if ($l.ProcId -in 0,4) { continue }\n        $p = Get-Process -Id $l.ProcId -ErrorAction SilentlyContinue\n        if (-not $p) { continue }\n        $pp = &amp; $procPfad $p\n        $si = &amp; $pruefe $pp\n        if ($si.MS) { continue }\n        $lauschFremd += [PSCustomObject]@{ Proto=$l.Proto; Port=$l.Port; Prozess=$p.Name; ProcId=$l.ProcId; Pfad=$pp; Si=$si }\n    }\n    $lauschFremd = @($lauschFremd | Group-Object { \"$($_.Proto)|$($_.Port)|$($_.ProcId)\" } | ForEach-Object { $_.Group[0] } | Sort-Object Proto, Port)\n    if ($lauschFremd.Count -gt 0) {\n        $grau = @()\n        $bunt = 0\n        foreach ($x in $lauschFremd) {\n            $col = &amp; $farbe (\"$($x.Pfad) $($x.Prozess)\") $x.Si\n            if ($col -eq 'DarkGray') { $grau += $x.Prozess; continue }\n            Write-Host (\"  {0} {1,-6} {2,-22} PID {3,-6} Sig: {4} | {5}\" -f $x.Proto, $x.Port, $x.Prozess, $x.ProcId, $x.Si.Status, $x.Si.Signierer) -ForegroundColor $col\n            Write-Host (\"         {0}\" -f $x.Pfad) -ForegroundColor DarkGray\n            $bunt++\n        }\n        if ($bunt -eq 0) { Write-Host \"  Nur bekannte, gueltig signierte Programme lauschen.\" -ForegroundColor Green }\n        if ($grau.Count -gt 0) {\n            Write-Host (\"  ({0} Ports bekannter Hersteller ausgeblendet: {1})\" -f $grau.Count, (($grau | Sort-Object -Unique) -join ', ')) -ForegroundColor DarkGray\n        }\n    } else {\n        Write-Host \"  Keine nicht-Microsoft-Programme lauschen auf einem Netzwerk-Port.\" -ForegroundColor Green\n    }\n\n    # --- 20b: Aktive Verbindungen AUS dem Heimnetz ---\n    Write-Host \"`n--- Aktive Verbindungen aus dem Heimnetz auf diesen PC (Handy -&gt; Panel) ---\" -ForegroundColor DarkGray\n    $eingehend = @(Get-NetTCPConnection -State Established -ErrorAction SilentlyContinue | Where-Object {\n        $_.RemoteAddress -match $privatNetz -and $lauschPorts.ContainsKey(\"$($_.OwningProcess)|$($_.LocalPort)\")\n    })\n    if ($eingehend.Count -gt 0) {\n        foreach ($c in $eingehend) {\n            $p   = Get-Process -Id $c.OwningProcess -ErrorAction SilentlyContinue\n            $mac = $nachbarn[[string]$c.RemoteAddress]\n            $zuf = if ($mac -and (&amp; $zufallsMac $mac)) { ' (zufaellige MAC - typisch Smartphone)' } else { '' }\n            Write-Host (\"  [!] {0} (PID {1}) Port {2}  &lt;-  {3}  MAC {4}{5}\" -f $p.Name, $c.OwningProcess, $c.LocalPort, $c.RemoteAddress, $(if ($mac) { $mac } else { '?' }), $zuf) -ForegroundColor Red\n            $pp = &amp; $procPfad $p\n            if ($pp) { Write-Host (\"      {0}\" -f $pp) -ForegroundColor DarkGray }\n        }\n        Write-Host \"  Ein anderes Geraet im Heimnetz ist gerade mit einem Programm auf diesem PC verbunden.\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"  Keine eingehende Verbindung aus dem Heimnetz aktiv.\" -ForegroundColor Green\n        Write-Host \"  (Nur waehrend der Cheat laeuft und das Handy verbunden ist sichtbar.)\" -ForegroundColor DarkGray\n    }\n\n    # Geraete im Netz mit zufaelliger MAC (Smartphones)\n    $handys = @($nachbarn.GetEnumerator() | Where-Object {\n        $_.Key -match '^(10\\.|192\\.168\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.)' -and $_.Key -notmatch '\\.255$' -and (&amp; $zufallsMac $_.Value)\n    })\n    if ($handys.Count -gt 0) {\n        Write-Host (\"  Geraete im Heimnetz mit zufaelliger MAC (meist Smartphones/Tablets): {0}\" -f (($handys | ForEach-Object { \"$($_.Key)\" }) -join ', ')) -ForegroundColor DarkGray\n    }\n\n    # --- 20c: Eingehende Firewall-Freigaben (ueberleben das Loeschen des Cheats) ---\n    Write-Host \"`n--- Eingehende Firewall-Regeln fuer Programme ausserhalb von Windows (inkl. abgelehnter Abfragen) ---\" -ForegroundColor DarkGray\n    Write-Host \"(Beim ersten Oeffnen eines Ports legt Windows eine Regel an - sie bleibt, auch wenn die EXE geloescht wird)\" -ForegroundColor DarkGray\n\n    $fwZeit = @{}\n    Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Firewall With Advanced Security/Firewall';Id=2004,2071,2097} -MaxEvents 5000 -ErrorAction SilentlyContinue | ForEach-Object {\n        $ev = $_\n        $ap = (([xml]$ev.ToXml()).Event.EventData.Data | Where-Object { $_.Name -eq 'ApplicationPath' }).'#text'\n        if ($ap) {\n            $k = $ap.ToLower()\n            if (-not $fwZeit.ContainsKey($k) -or $ev.TimeCreated -lt $fwZeit[$k]) { $fwZeit[$k] = $ev.TimeCreated }\n        }\n    }\n\n    $regeln = @()\n    $fwKey = 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\FirewallRules'\n    if (Test-Path $fwKey) {\n        $fw = Get-ItemProperty $fwKey -ErrorAction SilentlyContinue\n        foreach ($pr in $fw.PSObject.Properties) {\n            if ($pr.Name -like 'PS*') { continue }\n            $v = [string]$pr.Value\n            if ($v -notmatch '\\|Dir=In\\|') { continue }\n            $block = $v -match '\\|Action=Block\\|'\n            if ($block -and $pr.Name -notmatch '(?i)Query User') { continue }\n            if ($v -notmatch '\\|App=([^|]+)') { continue }\n            $app = [Environment]::ExpandEnvironmentVariables($matches[1])\n            if ($app -match '(?i)^[A-Z]:\\\\Windows\\\\|^System$') { continue }\n            $rName = if ($v -match '\\|Name=([^|]+)') { $matches[1] } else { $pr.Name }\n            $regeln += [PSCustomObject]@{\n                App       = $app\n                Name      = $rName\n                Aktiv     = ($v -match '\\|Active=TRUE\\|')\n                Auto      = ($pr.Name -match '(?i)Query User')\n                Block     = $block\n                Existiert = (Test-Path -LiteralPath $app)\n            }\n        }\n    }\n    $regeln = @($regeln | Group-Object { $_.App.ToLower() } | ForEach-Object { $_.Group | Sort-Object Aktiv -Descending | Select-Object -First 1 })\n\n    $bekanntN = 0\n    $restListe = @()\n    $ausgabe  = @()\n    foreach ($r in $regeln) {\n        $si   = &amp; $pruefe $r.App\n        $zeit = $fwZeit[$r.App.ToLower()]\n        if ($r.Existiert -and $si.Bekannt -and -not ($begriff -and $r.App -match $begriff)) { $bekanntN++; continue }\n        if (-not $r.Existiert) {\n            # Update-Rest: dieselbe EXE existiert in einem anderen Versionsordner (Discord app-1.0.x, EdgeWebView 15x.x)\n            if (&amp; $istUpdateRest $r.App) { $restListe += ((Split-Path $r.App -Leaf) -replace '\\s+--.*$',''); continue }\n        }\n        $col = if (-not $r.Existiert) { 'Red' } else { &amp; $farbe $r.App $si }\n        $ausgabe += [PSCustomObject]@{ R=$r; Si=$si; Zeit=$zeit; Col=$col }\n    }\n    if ($ausgabe.Count -gt 0) {\n        foreach ($a in ($ausgabe | Sort-Object { $_.R.Existiert }, { $_.Zeit } -Descending)) {\n            $flags = @()\n            if (-not $a.R.Existiert) { $flags += 'EXE GELOESCHT' }\n            if ($a.R.Auto -and -not $a.R.Block) { $flags += 'per Windows-Abfrage erlaubt' }\n            if ($a.R.Block)          { $flags += 'Windows-Abfrage ABGELEHNT (trotzdem Beweis fuer Port-Oeffnung)' }\n            if (-not $a.R.Aktiv)     { $flags += 'deaktiviert' }\n            $zeitTxt = if ($a.Zeit) { $a.Zeit.ToString('dd.MM.yyyy HH:mm') } else { 'Zeit unbekannt' }\n            Write-Host (\"  [{0}] {1}\" -f $zeitTxt, $a.R.App) -ForegroundColor $a.Col\n            Write-Host (\"        Regel: {0} | Sig: {1} | {2}\" -f $a.R.Name, $a.Si.Status, ($flags -join ', ')) -ForegroundColor DarkGray\n        }\n    } else {\n        Write-Host \"  Keine auffaelligen eingehenden Freigaben.\" -ForegroundColor Green\n    }\n    if ($bekanntN -gt 0) { Write-Host (\"  ({0} Freigaben bekannter, signierter Hersteller ausgeblendet)\" -f $bekanntN) -ForegroundColor DarkGray }\n    if ($restListe.Count -gt 0) {\n        Write-Host (\"  ({0} Regeln alter Programmversionen/defekter Pfade ausgeblendet - neuere Version existiert: {1})\" -f $restListe.Count, (($restListe | Sort-Object -Unique) -join ', ')) -ForegroundColor DarkGray\n    }\n    Write-Host \"  EXE GELOESCHT + Pfad in Temp/AppData/Downloads = Programm hat Verbindungen angenommen und ist verschwunden.\" -ForegroundColor DarkGray\n\n    # --- 20d: Ausgehende Dauerverbindungen (Cloud-Panel) ---\n    Write-Host \"`n--- Ausgehende Verbindungen unbekannter Programme ins Internet (Cloud-Panel) ---\" -ForegroundColor DarkGray\n    $dnsMap = @{}\n    Get-DnsClientCache -ErrorAction SilentlyContinue | Where-Object { $_.Data } | ForEach-Object {\n        $ip = [string]$_.Data\n        if (-not $dnsMap.ContainsKey($ip)) { $dnsMap[$ip] = [string]$_.Entry }\n    }\n    $raus = @()\n    $cheatVerb = @()\n    Get-NetTCPConnection -State Established -ErrorAction SilentlyContinue |\n        Where-Object { $_.RemoteAddress -notmatch $privatNetz -and $_.RemoteAddress -notmatch '^(127\\.|::1$|0\\.0\\.0\\.0|::$)' } |\n        ForEach-Object {\n            $p = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue\n            if (-not $p) { return }\n            $pp = &amp; $procPfad $p\n            $si = &amp; $pruefe $pp\n            $zielName = $dnsMap[[string]$_.RemoteAddress]\n            $cheatZiel = if ($zielName) { Get-CheatName $zielName } else { $null }\n            if ($cheatZiel) {\n                $cheatVerb += [PSCustomObject]@{ Prozess=$p.Name; ProcId=$p.Id; Pfad=$pp; Ziel=\"$($_.RemoteAddress):$($_.RemotePort)\"; Domain=$zielName; Name=$cheatZiel; Sig=$si.Status; Signierer=$si.Signierer }\n                return\n            }\n            if ($si.MS -or $si.Bekannt) { return }\n            $raus += [PSCustomObject]@{ Prozess=$p.Name; ProcId=$p.Id; Pfad=$pp; Ziel=\"$($_.RemoteAddress):$($_.RemotePort)\"; Domain=$dnsMap[[string]$_.RemoteAddress]; Si=$si }\n        }\n    if ($cheatVerb.Count -gt 0) {\n        Write-Host \"  [!!!] AKTIVE VERBINDUNG ZU BEKANNTER CHEAT-DOMAIN:\" -ForegroundColor Red\n        foreach ($c in $cheatVerb) {\n            Write-Host (\"      {0} (PID {1}) -&gt; {2}  {3}   [{4}]\" -f $c.Prozess, $c.ProcId, $c.Ziel, $c.Domain, $c.Name) -ForegroundColor Red\n            Write-Host (\"      {0} | Sig: {1} | {2}\" -f $c.Pfad, $c.Sig, $c.Signierer) -ForegroundColor Red\n        }\n        Write-Host \"      Ist der Prozess signiert (svchost, explorer ...), steckt der Cheat sehr wahrscheinlich als DLL darin -&gt; Punkt 21a fuer diese PID.\" -ForegroundColor DarkGray\n    }\n    if ($raus.Count -gt 0) {\n        foreach ($g in ($raus | Group-Object ProcId)) {\n            $x = $g.Group[0]\n            $col = &amp; $farbe (\"$($x.Pfad) \" + (($g.Group | ForEach-Object { $_.Domain }) -join ' ')) $x.Si\n            Write-Host (\"  {0} (PID {1}) | Sig: {2} | {3}\" -f $x.Prozess, $x.ProcId, $x.Si.Status, $x.Pfad) -ForegroundColor $col\n            $g.Group | ForEach-Object { Write-Host (\"        -&gt; {0}  {1}\" -f $_.Ziel, $(if ($_.Domain) { $_.Domain } else { '' })) -ForegroundColor DarkGray }\n        }\n    } else {\n        Write-Host \"  Keine ausgehenden Verbindungen unbekannter Programme.\" -ForegroundColor Green\n    }\n\n    if ($begriff) {\n        $dnsTreffer = @(Get-DnsClientCache -ErrorAction SilentlyContinue | Where-Object { $_.Entry -match $begriff } | Select-Object -ExpandProperty Entry -Unique)\n        if ($dnsTreffer.Count -gt 0) {\n            Write-Host (\"  [!] DNS-Cache enthaelt Suchbegriff: {0}\" -f ($dnsTreffer -join ', ')) -ForegroundColor Red\n        }\n    }\n\n    # --- 20e: Netzwerk-Umgehungen ---\n    Write-Host \"`n--- Netzwerk-Konfiguration ---\" -ForegroundColor DarkGray\n    Get-NetConnectionProfile -ErrorAction SilentlyContinue | ForEach-Object {\n        Write-Host (\"  Profil {0}: {1}\" -f $_.InterfaceAlias, $_.NetworkCategory) -ForegroundColor DarkGray\n    }\n    # Firewall ausgeschaltet? Dann gibt es gar keine Abfrage.\n    Get-NetFirewallProfile -ErrorAction SilentlyContinue | ForEach-Object {\n        $prof = $_\n        if (-not $prof.Enabled) {\n            $pk = switch ($prof.Name) { 'Domain' {'DomainProfile'} 'Private' {'StandardProfile'} default {'PublicProfile'} }\n            $zp = &amp; $keyZeit \"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\$pk\"\n            Write-Host (\"  [!] Windows-Firewall AUS fuer Profil {0} (Einstellung zuletzt geaendert: {1}) - Verbindungen ohne jede Abfrage moeglich.\" -f $prof.Name, $zp) -ForegroundColor Red\n        }\n    }\n    $fwAend = @(Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Firewall With Advanced Security/Firewall';Id=2003} -MaxEvents 15 -ErrorAction SilentlyContinue)\n    if ($fwAend.Count -gt 0) {\n        Write-Host \"  Letzte Aenderungen an Firewall-Einstellungen (z. B. Firewall ein/aus):\" -ForegroundColor DarkGray\n        $fwAend | ForEach-Object {\n            $m = ($_.Message -replace '\\s+',' ').Trim()\n            Write-Host (\"    [{0}] {1}\" -f $_.TimeCreated, $m.Substring(0,[Math]::Min(140,$m.Length))) -ForegroundColor DarkGray\n        }\n    }\n    $hotspot = @(Get-NetAdapter -IncludeHidden -ErrorAction SilentlyContinue | Where-Object {\n        $_.Status -eq 'Up' -and $_.InterfaceDescription -match '(?i)Wi-Fi Direct Virtual|Hosted Network|Virtual WiFi'\n    })\n    if ($hotspot.Count -gt 0) {\n        Write-Host \"  [!] Mobiler Hotspot / WLAN-Direct AKTIV - ein Handy kann sich direkt mit dem PC verbinden, am Router vorbei.\" -ForegroundColor Red\n        $hotspot | ForEach-Object { Write-Host (\"      {0}\" -f $_.InterfaceDescription) -ForegroundColor DarkGray }\n    } else {\n        Write-Host \"  Kein mobiler Hotspot aktiv.\" -ForegroundColor Green\n    }\n    $ppRoot = 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\PortProxy'\n    $ppEintraege = @()\n    if (Test-Path $ppRoot) {\n        Get-ChildItem $ppRoot -Recurse -ErrorAction SilentlyContinue | ForEach-Object {\n            $k = $_\n            $props = Get-ItemProperty $k.PSPath -ErrorAction SilentlyContinue\n            if ($props) {\n                foreach ($pr in $props.PSObject.Properties) {\n                    if ($pr.Name -like 'PS*') { continue }\n                    $ppEintraege += (\"{0}: {1} -&gt; {2}\" -f $k.PSChildName, $pr.Name, $pr.Value)\n                }\n            }\n        }\n    }\n    if ($ppEintraege.Count -gt 0) {\n        Write-Host \"  [!] Portweiterleitungen (netsh portproxy) eingerichtet:\" -ForegroundColor Red\n        $ppEintraege | ForEach-Object { Write-Host \"      $_\" -ForegroundColor Red }\n    } else {\n        Write-Host \"  Keine Portweiterleitungen.\" -ForegroundColor Green\n    }\n\n    # --- 20f: SRUM - Netzwerkverkehr pro Programm, rueckwirkend ---\n    Write-Host \"`n--- SRUM: Netzwerkverkehr pro Programm, rueckwirkend (auch GELOESCHTE EXEs) ---\" -ForegroundColor DarkGray\n    Write-Host \"(Windows zaehlt stuendlich pro Programm gesendete/empfangene Bytes - voellig unabhaengig von der Firewall)\" -ForegroundColor DarkGray\n    $srumTool = Get-ChildItem \"$env:USERPROFILE\\Desktop\\CTC_Tools\" -Recurse -Filter 'SrumECmd.exe' -ErrorAction SilentlyContinue | Select-Object -First 1\n    if (-not $srumTool) {\n        Write-Host \"  SrumECmd fehlt - ueber Punkt 18 (Eintrag 9) laden oder von ericzimmerman.github.io nach Desktop\\CTC_Tools legen.\" -ForegroundColor Yellow\n    } else {\n        # .NET-Laufzeit pruefen, die SrumECmd braucht (steht in dessen runtimeconfig.json)\n        $netFehlt = $false\n        $rc = Get-ChildItem $srumTool.DirectoryName -Filter '*.runtimeconfig.json' -ErrorAction SilentlyContinue | Select-Object -First 1\n        if ($rc) {\n            try {\n                $j  = Get-Content $rc.FullName -Raw | ConvertFrom-Json\n                $fw = @(@($j.runtimeOptions.framework) + @($j.runtimeOptions.frameworks) | Where-Object { $_ -and $_.name })\n                $braucht = $fw | Where-Object { $_.name -match '^Microsoft\\.(NETCore|WindowsDesktop)\\.App$' } | Select-Object -First 1\n                if ($braucht) {\n                    $major = ($braucht.version -split '\\.')[0]\n                    $da = @(Get-ChildItem \"$env:ProgramFiles\\dotnet\\shared\\$($braucht.name)\" -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -like \"$major.*\" })\n                    if ($da.Count -eq 0) {\n                        Write-Host (\"  [!] SrumECmd braucht .NET {0} ({1}), das ist nicht installiert.\" -f $major, $braucht.name) -ForegroundColor Yellow\n                        Write-Host (\"      Download: https://dotnet.microsoft.com/download/dotnet/{0}.0  -&gt;  '.NET Runtime' fuer Windows x64\" -f $major) -ForegroundColor Yellow\n                        $netFehlt = $true\n                    }\n                }\n            } catch {}\n        }\n\n        if (-not $netFehlt) {\n            $arbeit = Join-Path $env:TEMP (\"ctc_srum_\" + (Get-Date -Format 'yyyyMMddHHmmss'))\n            New-Item -ItemType Directory -Path $arbeit -Force | Out-Null\n            $kopie = Join-Path $arbeit 'SRUDB.dat'\n            Write-Host \"  Kopiere SRUM-Datenbank samt Transaktionslogs ueber Schattenkopie (Original bleibt unberuehrt)...\" -ForegroundColor DarkGray\n            Get-ChildItem \"$env:SystemRoot\\System32\\sru\" -File -Force -ErrorAction SilentlyContinue |\n                Where-Object { $_.Name -match '(?i)^SRU(DB\\.dat|.*\\.log|\\.chk)$' } | ForEach-Object {\n                    &amp; esentutl.exe /y $_.FullName /vss /d (Join-Path $arbeit $_.Name) 2&gt;&amp;1 | Out-Null\n                }\n            $erfolg = $false\n            if (-not (Test-Path $kopie)) {\n                Write-Host \"  SRUDB.dat konnte nicht kopiert werden (Volumeschattenkopie-Dienst aus?).\" -ForegroundColor Yellow\n            } else {\n                # Kopie mit den mitkopierten Logs in einen sauberen Zustand bringen (nur die Kopie!)\n                Push-Location $arbeit\n                &amp; esentutl.exe /r sru /l $arbeit /s $arbeit /d $arbeit /i 2&gt;&amp;1 | Out-Null\n                Pop-Location\n                Write-Host \"  Werte mit SrumECmd aus...\" -ForegroundColor DarkGray\n                $srOut = @(&amp; $srumTool.FullName -f $kopie --csv $arbeit 2&gt;&amp;1 | ForEach-Object { [string]$_ })\n                $csvDatei = Get-ChildItem $arbeit -Recurse -Filter '*NetworkUsage*.csv' -ErrorAction SilentlyContinue | Select-Object -First 1\n                if (-not $csvDatei) {\n                    Write-Host \"  SrumECmd hat keine Netzwerkdaten erzeugt. Letzte Ausgabe von SrumECmd:\" -ForegroundColor Yellow\n                    $srOut | Where-Object { $_.Trim() } | Select-Object -Last 8 | ForEach-Object { Write-Host \"    $_\" -ForegroundColor DarkGray }\n                    Write-Host \"  Arbeitsordner bleibt zur Pruefung erhalten: $arbeit\" -ForegroundColor Yellow\n                } else {\n                    $erfolg = $true\n                        $zeilen  = @(Import-Csv $csvDatei.FullName)\n                        $spalten = @($zeilen[0].PSObject.Properties.Name)\n                        $cApp  = $spalten | Where-Object { $_ -match '(?i)^ExeInfo$' }      | Select-Object -First 1\n                        $cZeit = $spalten | Where-Object { $_ -match '(?i)^Timestamp$' }    | Select-Object -First 1\n                        $cRx   = $spalten | Where-Object { $_ -match '(?i)BytesReceived' }  | Select-Object -First 1\n                        $cTx   = $spalten | Where-Object { $_ -match '(?i)BytesSent' }      | Select-Object -First 1\n                        $proApp = @{}\n                        foreach ($z in $zeilen) {\n                            $app = [string]$z.$cApp\n                            if (-not $app) { continue }\n                            $pfad = &amp; $konv $app\n                            $t  = [DateTime]::MinValue\n                            if ([DateTime]::TryParse([string]$z.$cZeit, [Globalization.CultureInfo]::InvariantCulture, [Globalization.DateTimeStyles]::AssumeUniversal -bor [Globalization.DateTimeStyles]::AdjustToUniversal, [ref]$t)) {\n                                $t = [DateTime]::SpecifyKind($t, 'Utc').ToLocalTime()      # SrumECmd liefert UTC - in Ortszeit umrechnen wie der Rest von CTC\n                            } else { $t = $null }\n                            $rx = [int64]0; [void][int64]::TryParse([string]$z.$cRx, [ref]$rx)\n                            $tx = [int64]0; [void][int64]::TryParse([string]$z.$cTx, [ref]$tx)\n                            if (-not $proApp.ContainsKey($pfad)) { $proApp[$pfad] = [PSCustomObject]@{ Pfad=$pfad; Erst=$t; Letzt=$t; Bytes=[int64]0; Rx=[int64]0; Tx=[int64]0; Std=0; Stunden=(New-Object System.Collections.ArrayList) } }\n                            $o = $proApp[$pfad]\n                            $o.Bytes += ($rx + $tx); $o.Rx += $rx; $o.Tx += $tx; $o.Std++\n                            if ($t -and $pfad -match '(?i)\\\\(powershell|pwsh|powershell_ise|cmd|wscript|cscript|mshta|rundll32|regsvr32|certutil|bitsadmin|curl|msiexec|installutil|regasm|regsvcs|msbuild|wmic|hh)\\.exe$') {\n                                [void]$o.Stunden.Add([PSCustomObject]@{ Zeit=$t; Rx=$rx; Tx=$tx })\n                            }\n                            if ($t -and (-not $o.Erst  -or $t -lt $o.Erst))  { $o.Erst  = $t }\n                            if ($t -and (-not $o.Letzt -or $t -gt $o.Letzt)) { $o.Letzt = $t }\n                        }\n                        $kandidaten = @()\n                        $srumUpdate = @(); $srumInst = @()\n                        foreach ($o in $proApp.Values) {\n                            if ($o.Pfad -notmatch '^[A-Z]:\\\\') { continue }\n                            $da = Test-Path -LiteralPath $o.Pfad\n                            if (-not $da) {\n                                if (&amp; $istUpdateRest $o.Pfad)          { $srumUpdate += ((Split-Path $o.Pfad -Leaf) -replace '\\s+--.*$',''); continue }\n                                if ($o.Pfad -match $installerMuster)   { $srumInst   += (Split-Path $o.Pfad -Leaf); continue }\n                            }\n                            $si = &amp; $pruefe $o.Pfad\n                            # Windows-Werkzeuge, ueber die Skripte Dateien laden, NICHT ausblenden (LOLBins)\n                            $lolbin = $o.Pfad -match '(?i)\\\\(powershell|pwsh|powershell_ise|cmd|wscript|cscript|mshta|rundll32|regsvr32|certutil|bitsadmin|curl|msiexec|installutil|regasm|regsvcs|msbuild|wmic|hh)\\.exe$'\n                            if ($da -and ($si.MS -or $si.Bekannt) -and -not $lolbin) { continue }\n                            $col = if (-not $da) { 'Red' } else { &amp; $farbe $o.Pfad $si }\n                            $kandidaten += [PSCustomObject]@{ O=$o; Da=$da; Si=$si; Col=$col }\n                        }\n                        if ($kandidaten.Count -gt 0) {\n                            Write-Host (\"  {0} Programme mit Netzwerkverkehr, die weder Microsoft noch bekannten Herstellern gehoeren:\" -f $kandidaten.Count) -ForegroundColor Yellow\n                            foreach ($k in ($kandidaten | Sort-Object { -not $_.Da }, { $_.O.Letzt } -Descending | Select-Object -First 40)) {\n                                $flag = if (-not $k.Da) { '  [EXE GELOESCHT]' } else { \"  [Sig: $($k.Si.Status)]\" }\n                                Write-Host (\"  {0}{1}\" -f $k.O.Pfad, $flag) -ForegroundColor $k.Col\n                                Write-Host (\"      aktiv {0} bis {1} | {2} Stunden-Eintraege | empfangen {3} MB / gesendet {4} MB\" -f $k.O.Erst, $k.O.Letzt, $k.O.Std, [Math]::Round($k.O.Rx/1MB, 2), [Math]::Round($k.O.Tx/1MB, 2)) -ForegroundColor DarkGray\n                                if ($k.O.Pfad -match '(?i)\\\\(powershell|pwsh|powershell_ise|cmd|wscript|cscript|mshta|rundll32|regsvr32|certutil|bitsadmin|curl|msiexec|installutil|regasm|regsvcs|msbuild|wmic|hh)\\.exe$') {\n                                    Write-Host \"      Windows-Werkzeug mit Netzwerkverkehr: Skript hat Daten geladen. Grosse Empfangsmenge = Download einer Datei (CTC selbst laedt auch ueber PowerShell).\" -ForegroundColor Yellow\n                                    if ($k.O.Pfad -match '(?i)\\\\SysWOW64\\\\') {\n                                        Write-Host \"      32-Bit-Variante: wird selten von Hand gestartet, meist von einem 32-Bit-Programm/Installer aufgerufen.\" -ForegroundColor Yellow\n                                    }\n                                    $grosse = @($k.O.Stunden | Group-Object { $_.Zeit.ToString('yyyyMMddHH') } | ForEach-Object {\n                                        [PSCustomObject]@{ Zeit=$_.Group[0].Zeit; Rx=($_.Group | Measure-Object Rx -Sum).Sum; Tx=($_.Group | Measure-Object Tx -Sum).Sum }\n                                    } | Where-Object { $_.Rx -ge 512KB } | Sort-Object Rx -Descending | Select-Object -First 6)\n                                    if ($grosse.Count -gt 0) {\n                                        Write-Host \"      Stunden mit den groessten Downloads (Zeitpunkt in Punkt 10 und 19 eingeben):\" -ForegroundColor DarkYellow\n                                        foreach ($g in ($grosse | Sort-Object Zeit -Descending)) {\n                                            Write-Host (\"        {0}  empfangen {1,8:N2} MB  gesendet {2,6:N2} MB\" -f $g.Zeit.ToString('dd.MM.yyyy HH:00'), ($g.Rx/1MB), ($g.Tx/1MB)) -ForegroundColor DarkYellow\n                                        }\n                                    }\n                                }\n                            }\n                            Write-Host \"  Rot + GELOESCHT = Programm hat Daten uebertragen und existiert nicht mehr. Zeitraum in Punkt 19 als Startzeit nutzen.\" -ForegroundColor DarkGray\n                        } else {\n                            Write-Host \"  Kein unbekanntes Programm mit Netzwerkverkehr im SRUM-Zeitraum.\" -ForegroundColor Green\n                        }\n                        if ($srumUpdate.Count -gt 0) {\n                            Write-Host (\"  ({0} alte Programmversionen ausgeblendet - neuere Version existiert: {1})\" -f $srumUpdate.Count, (($srumUpdate | Sort-Object -Unique) -join ', ')) -ForegroundColor DarkGray\n                        }\n                        if ($srumInst.Count -gt 0) {\n                            Write-Host (\"  ({0} Installer/Updater-Reste ausgeblendet, die sich selbst loeschen: {1})\" -f $srumInst.Count, (($srumInst | Sort-Object -Unique) -join ', ')) -ForegroundColor DarkGray\n                        }\n                        $vollCsv = \"$env:USERPROFILE\\Desktop\\ctc_srum_netzwerk_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv\"\n                        Copy-Item $csvDatei.FullName $vollCsv -ErrorAction SilentlyContinue\n                        Write-Host \"  Vollstaendige SRUM-Netzwerkdaten: $vollCsv  (Zeiten in der CSV sind UTC, hier oben Ortszeit)\" -ForegroundColor DarkGray\n                }\n            }\n            if ($erfolg) { Remove-Item $arbeit -Recurse -Force -ErrorAction SilentlyContinue }\n        }\n    }\n\n    Write-Host \"`nAuswertung:\" -ForegroundColor DarkGray\n    Write-Host \"  Lokales Panel : fremder Prozess lauscht + Verbindung aus dem LAN mit zufaelliger MAC = Handy steuert den PC.\" -ForegroundColor DarkGray\n    Write-Host \"  Nachtraeglich : Firewall-Freigabe fuer geloeschte EXE in Temp/AppData - Zeitpunkt in Punkt 19 als Startzeit nutzen.\" -ForegroundColor DarkGray\n    Write-Host \"  Cloud-Panel   : Dauerverbindung eines unsignierten Programms zu einer unbekannten Domain.\" -ForegroundColor DarkGray\n    Write-Host \"  Ohne Firewall : SRUM zeigt rueckwirkend jedes Programm mit Netzwerkverkehr - auch geloeschte.\" -ForegroundColor DarkGray\n    Write-Host \"  Hinweis       : 20a/20b sehen nur, was gerade laeuft - rueckwirkend zaehlen 20c (Firewall) und 20f (SRUM).\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  21 - Injection in signierte Prozesse / Dienste\n# ============================================================\nfunction Invoke-InjectionCheck {\n    param([switch]$OhneFrage)\n\n    Write-Host \"`n=== Injection in signierte Prozesse und Dienste ===\" -ForegroundColor Cyan\n    Write-Host \"(Manuell gemappter Code hat keine Datei - er liegt als privater ausfuehrbarer Speicher im Prozess)\" -ForegroundColor DarkGray\n\n    Add-Type -ErrorAction SilentlyContinue -TypeDefinition @\"\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\npublic static class CtcMem {\n    [StructLayout(LayoutKind.Sequential)]\n    public struct MBI64 {\n        public ulong BaseAddress; public ulong AllocationBase; public uint AllocationProtect; public uint Align1;\n        public ulong RegionSize; public uint State; public uint Protect; public uint Type; public uint Align2;\n    }\n    [DllImport(\"kernel32.dll\", SetLastError = true)] static extern IntPtr OpenProcess(uint access, bool inherit, int pid);\n    [DllImport(\"kernel32.dll\")] static extern bool CloseHandle(IntPtr h);\n    [DllImport(\"kernel32.dll\", SetLastError = true)] static extern IntPtr VirtualQueryEx(IntPtr h, IntPtr addr, out MBI64 mbi, IntPtr len);\n    [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool ReadProcessMemory(IntPtr h, IntPtr addr, byte[] buf, IntPtr size, out IntPtr read);\n\n    public class Bereich { public ulong Basis; public ulong Groesse; public uint Schutz; public bool MZ; public bool PE; }\n\n    public static List Scan(int pid, out string fehler) {\n        fehler = null;\n        var liste = new List();\n        IntPtr h = OpenProcess(0x0400 | 0x0010, false, pid);   // QUERY_INFORMATION | VM_READ\n        if (h == IntPtr.Zero) { fehler = \"kein Zugriff\"; return liste; }\n        try {\n            ulong addr = 0;\n            int size = Marshal.SizeOf(typeof(MBI64));\n            while (addr &lt; 0x7FFFFFFFFFFF) {\n                MBI64 m;\n                if (VirtualQueryEx(h, (IntPtr)(long)addr, out m, (IntPtr)size) == IntPtr.Zero) break;\n                bool commit = m.State == 0x1000;                 // MEM_COMMIT\n                bool exec   = (m.Protect &amp; 0xF0) != 0;           // PAGE_EXECUTE*\n                bool image  = m.Type == 0x1000000;               // MEM_IMAGE = gehoert zu einer Datei\n                bool guard  = (m.Protect &amp; 0x100) != 0;\n                if (commit &amp;&amp; exec &amp;&amp; !image &amp;&amp; !guard) {\n                    var b = new Bereich { Basis = m.BaseAddress, Groesse = m.RegionSize, Schutz = m.Protect };\n                    byte[] buf = new byte[0x400]; IntPtr gelesen;\n                    int n = (int)Math.Min((ulong)buf.Length, m.RegionSize);\n                    if (ReadProcessMemory(h, (IntPtr)(long)m.BaseAddress, buf, (IntPtr)n, out gelesen) &amp;&amp; (long)gelesen &gt;= 0x40) {\n                        if (buf[0] == 0x4D &amp;&amp; buf[1] == 0x5A) {\n                            b.MZ = true;\n                            int lfa = BitConverter.ToInt32(buf, 0x3C);\n                            if (lfa &gt; 0 &amp;&amp; lfa &lt; n - 4 &amp;&amp; buf[lfa] == 0x50 &amp;&amp; buf[lfa + 1] == 0x45 &amp;&amp; buf[lfa + 2] == 0 &amp;&amp; buf[lfa + 3] == 0) b.PE = true;\n                        }\n                    }\n                    liste.Add(b);\n                }\n                ulong next = m.BaseAddress + m.RegionSize;\n                if (next &lt;= addr) break;\n                addr = next;\n            }\n        } finally { CloseHandle(h); }\n        return liste;\n    }\n}\n\"@\n\n    $sigCache = @{}\n    $sigVon = {\n        param([string]$pfad)\n        if (-not $pfad) { return [PSCustomObject]@{ Status='?'; Signierer='-'; MS=$false } }\n        if ($sigCache.ContainsKey($pfad)) { return $sigCache[$pfad] }\n        $s = $null\n        if (Test-Path -LiteralPath $pfad) { $s = Get-AuthenticodeSignature -LiteralPath $pfad -ErrorAction SilentlyContinue }\n        $sg = if ($s -and $s.SignerCertificate) { $s.SignerCertificate.Subject -replace '^(?:.*?,\\s*)?CN=(?:\"([^\"]+)\"|([^,]+)).*$','$1$2' } else { '-' }\n        $r = [PSCustomObject]@{ Status=$(if ($s) { [string]$s.Status } else { 'fehlt' }); Signierer=$sg; MS=($s -and $s.Status -eq 'Valid' -and $sg -match '(?i)Microsoft') }\n        $sigCache[$pfad] = $r\n        $r\n    }\n    $sigRQ3 = '[DllImport(\"advapi32.dll\")]public static extern int RegQueryInfoKey(Microsoft.Win32.SafeHandles.SafeRegistryHandle h,System.Text.StringBuilder a,ref int b,int c,ref int d,ref int e,ref int f,ref int g,ref int i,ref int j,ref int k,ref long l);'\n    Add-Type -MemberDefinition $sigRQ3 -Name RK3 -Namespace W3 -ErrorAction SilentlyContinue\n    $keyZeit = {\n        param($pfad)\n        try {\n            $k = Get-Item $pfad -ErrorAction Stop\n            $t = 0L; $z = 0; $n = New-Object Text.StringBuilder 1024\n            [void][W3.RK3]::RegQueryInfoKey($k.Handle,$n,[ref]$z,0,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$z,[ref]$t)\n            [DateTime]::FromFileTime($t)\n        } catch { $null }\n    }\n\n    # ============================================================\n    # 21a: Speicher-Scan aller Prozesse\n    # ============================================================\n    Write-Host \"`n--- 21a: Privater ausfuehrbarer Speicher ohne Datei (Manual Map / Reflective Injection) ---\" -ForegroundColor DarkGray\n    Write-Host \"  Scanne Prozesse...\" -ForegroundColor DarkGray\n    $jitModule = '(?i)^(clr|coreclr|clrjit|mscorwks|libcef|chrome_elf|node|jvm|v8|msedge|chrome|electron|qt5webengine\\w*|qt6webengine\\w*|webview2loader|embeddedbrowserwebview|mono.*|luajit.*|cefsharp.*)\\.dll$'\n    $jitNamen  = '(?i)^(chrome|msedge|msedgewebview2|firefox|opera|brave|vivaldi|discord|spotify|steamwebhelper|code|slack|teams|ms-teams|powershell|pwsh|java|javaw|node|obs64|epicgameslauncher|battle\\.net|riotclientux)$'\n    $sensibel  = '(?i)^(svchost|lsass|services|winlogon|wininit|csrss|spoolsv|explorer|dwm|taskhostw|runtimebroker|sihost|dllhost|wmiprvse|searchindexer|searchhost|ctfmon|audiodg|fontdrvhost|conhost|smss|securityhealthservice|wudfhost|unsecapp)$'\n\n    # JIT anhand der EXE erkennen - funktioniert auch bei 32-Bit-Prozessen, deren Module eine 64-Bit-PowerShell nicht sieht\n    $jitCache = @{}\n    $jitDatei = {\n        param([string]$exe)\n        if (-not $exe -or -not (Test-Path -LiteralPath $exe)) { return $false }\n        $key = $exe.ToLower()\n        if ($jitCache.ContainsKey($key)) { return $jitCache[$key] }\n        $r = $false\n        $dir = Split-Path $exe -Parent\n        if (Get-ChildItem $dir -File -Recurse -Depth 2 -ErrorAction SilentlyContinue | Where-Object { $_.Name -match '(?i)^(libcef\\.dll|chrome_elf\\.dll|qt[56]webenginecore\\.dll|v8\\.dll|node\\.dll|icudtl\\.dat|coreclr\\.dll|clrjit\\.dll|mono.*\\.dll|unityplayer\\.dll|gameassembly\\.dll|jvm\\.dll)$' } | Select-Object -First 1) { $r = $true }\n        if (-not $r) {\n            try {                                             # .NET-Programm? CLR-Datenverzeichnis (Index 14) gesetzt\n                $fs = [System.IO.File]::Open($exe, 'Open', 'Read', 'ReadWrite'); $br = New-Object System.IO.BinaryReader($fs)\n                $fs.Position = 0x3C; $pe = $br.ReadInt32()\n                $fs.Position = $pe + 24; $magic = $br.ReadUInt16()\n                $dd = if ($magic -eq 0x20B) { $pe + 24 + 112 } else { $pe + 24 + 96 }\n                $fs.Position = $dd + 14 * 8\n                if ($br.ReadUInt32() -ne 0) { $r = $true }\n                $br.Close()\n            } catch {}\n        }\n        $jitCache[$key] = $r\n        $r\n    }\n\n    $dienste = @{}\n    Get-CimInstance Win32_Service -ErrorAction SilentlyContinue | Where-Object { $_.ProcessId -gt 0 } | ForEach-Object {\n        $dienste[[int]$_.ProcessId] += @($_.Name)\n    }\n\n    $funde = @()\n    $alleProz = @()\n    $keinZugriff = 0\n    foreach ($p in @(Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Id -gt 4 -and $_.Id -ne $PID })) {\n        $fehler = $null\n        $bereiche = [CtcMem]::Scan($p.Id, [ref]$fehler)\n        if ($fehler) { $keinZugriff++; continue }\n        if ($bereiche.Count -eq 0) { continue }\n\n        $peBereiche = @($bereiche | Where-Object { $_.MZ -or $_.PE })\n        $summe = [double](($bereiche | Measure-Object -Property Groesse -Sum).Sum)\n\n        $istJit = $p.Name -match $jitNamen\n        if (-not $istJit) { $istJit = &amp; $jitDatei $p.Path }\n        if (-not $istJit) {\n            try { $istJit = [bool]($p.Modules | Where-Object { $_.ModuleName -match $jitModule } | Select-Object -First 1) } catch {}\n        }\n        $istSens = $p.Name -match $sensibel\n        $alleProz += [PSCustomObject]@{ Proc=$p; Anzahl=$bereiche.Count; Summe=$summe; PE=$peBereiche; Jit=$istJit; Sens=$istSens }\n    }\n\n    # Grundlinie: dasselbe Muster (Anzahl + Groesse) in vielen verschiedenen Prozessen = systemweit (Windows,\n    # Sicherheits- oder Overlay-Software), kein Cheat. Wird ueberall abgezogen, bewertet wird nur, was darueber liegt.\n    $grundKB = 0; $grundN = 0; $grundTxt = ''\n    $haeufig = @($alleProz | Where-Object { -not $_.Jit -and $_.PE.Count -eq 0 } |\n        Group-Object { \"{0}|{1}\" -f $_.Anzahl, $_.Summe } | Sort-Object Count -Descending | Select-Object -First 1)\n    if ($haeufig.Count -gt 0 -and $haeufig[0].Count -ge 8) {\n        $bsp     = $haeufig[0].Group[0]\n        $grundKB = $bsp.Summe; $grundN = $haeufig[0].Count\n        $grundTxt = \"{0} Bereiche / {1} KB\" -f $bsp.Anzahl, [Math]::Round($bsp.Summe / 1KB)\n    }\n\n    foreach ($x in $alleProz) {\n        $netto = [Math]::Max(0, $x.Summe - $grundKB)\n        $stufe = $null\n        if ($x.PE.Count -gt 0)                                     { $stufe = 'Rot' }\n        elseif (-not $x.Jit -and $x.Sens -and $netto -ge 524288)   { $stufe = 'Rot' }\n        elseif (-not $x.Jit -and $netto -gt 65536)                 { $stufe = 'Gelb' }\n        if (-not $stufe) { continue }\n        $funde += [PSCustomObject]@{\n            Proc = $x.Proc; Stufe = $stufe; Anzahl = $x.Anzahl; KB = [Math]::Round($x.Summe / 1KB); NettoKB = [Math]::Round($netto / 1KB)\n            PE = $x.PE; Jit = $x.Jit; Dienste = $dienste[[int]$x.Proc.Id]\n        }\n    }\n    if ($grundN -gt 0) {\n        Write-Host (\"  Systemweites Grundmuster erkannt: {0} in {1} Prozessen - wird ueberall abgezogen (Windows/Sicherheits-/Overlay-Software).\" -f $grundTxt, $grundN) -ForegroundColor DarkGray\n    }\n\n    if ($funde.Count -gt 0) {\n        # Prozessdetails (Kommandozeile, Startzeit, Elternprozess) fuer die Einordnung\n        $procInfo = @{}\n        Get-CimInstance Win32_Process -ErrorAction SilentlyContinue | ForEach-Object { $procInfo[[int]$_.ProcessId] = $_ }\n        $ctcElternPid = if ($procInfo.ContainsKey([int]$PID)) { [int]$procInfo[[int]$PID].ParentProcessId } else { -1 }\n\n        foreach ($f in ($funde | Sort-Object { $_.Stufe -ne 'Rot' }, { -$_.KB })) {\n            $si  = &amp; $sigVon $f.Proc.Path\n            $col = if ($f.Stufe -eq 'Rot') { 'Red' } else { 'Yellow' }\n            $dTxt = if ($f.Dienste) { \" | Dienste: \" + (($f.Dienste | Select-Object -First 6) -join ', ') } else { '' }\n            $fw = if ($f.Proc.Path -match $MUSTER -or $f.Proc.Name -match $MUSTER) { '   &lt;-- FERNWARTUNG LAEUFT (Punkt 8: Sitzungen pruefen)' } else { '' }\n\n            $wp     = $procInfo[[int]$f.Proc.Id]\n            $cmd    = if ($wp) { [string]$wp.CommandLine } else { '' }\n            $eltern = if ($wp) { $procInfo[[int]$wp.ParentProcessId] } else { $null }\n            $herkunft = $null; $hCol = $col\n            if ($f.Proc.Name -match '(?i)^(powershell|pwsh|powershell_ise)$') {\n                $kinderCtc = @($procInfo.Values | Where-Object { [int]$_.ParentProcessId -eq [int]$f.Proc.Id -and [string]$_.CommandLine -match '(?i)ctcbydark|CTC_by_Dark' }).Count -gt 0\n                if ($cmd -match '(?i)ctcbydark|CTC_by_Dark|analystdark') {\n                    $herkunft = 'CTC (dieses Tool) - kein Befund'; $hCol = 'DarkGray'\n                } elseif ([int]$f.Proc.Id -eq $ctcElternPid -or $kinderCtc) {\n                    $herkunft = 'Konsole, aus der CTC gestartet wurde - kein Befund'; $hCol = 'DarkGray'\n                } elseif ($cmd -match '(?i)ECHO_[A-Z_]+|\\\\echo-[0-9A-F]{6}-' -or ($eltern -and [string]$eltern.Name -match '(?i)^echo-')) {\n                    $herkunft = 'ECHO (Pruef-Tool) - kein Cheat'; $hCol = 'Yellow'\n                } elseif ($cmd -match '(?i)\\s-(e|ec|en|enc|encodedcommand)\\s|-w(indowstyle)?\\s+hidden|downloadstring|downloaddata|\\biex\\b|invoke-expression|\\birm\\b|\\biwr\\b|invoke-webrequest|invoke-restmethod|frombase64|reflection\\.assembly') {\n                    $herkunft = 'VERDAECHTIG: verschleierter oder nachladender Start'; $hCol = 'Red'\n                } elseif (-not $cmd) {\n                    $herkunft = 'Kommandozeile nicht lesbar - Herkunft manuell pruefen'\n                } else {\n                    $herkunft = 'eigenstaendiges PowerShell-Fenster - wer hat es geoeffnet? (Elternprozess pruefen)'\n                }\n                if ($hCol -eq 'DarkGray' -or $hCol -eq 'Yellow') { $col = $hCol }\n            }\n\n            Write-Host (\"`n  [{0}] PID {1}{2}{3}\" -f $f.Proc.Name, $f.Proc.Id, $dTxt, $fw) -ForegroundColor $col\n            Write-Host (\"      {0} | Sig: {1} ({2})\" -f $f.Proc.Path, $si.Status, $si.Signierer) -ForegroundColor DarkGray\n            if ($wp) {\n                $eTxt = if ($eltern) { \"{0} (PID {1})\" -f $eltern.Name, $eltern.ProcessId } else { \"PID $($wp.ParentProcessId) (beendet)\" }\n                Write-Host (\"      gestartet {0} | Elternprozess: {1}\" -f $wp.CreationDate, $eTxt) -ForegroundColor DarkGray\n                if ($cmd) {\n                    $cKurz = if ($cmd.Length -gt 230) { $cmd.Substring(0,230) + ' [...]' } else { $cmd }\n                    Write-Host (\"      Kommandozeile: {0}\" -f $cKurz) -ForegroundColor DarkGray\n                }\n            }\n            if ($herkunft) { Write-Host (\"      Einordnung: {0}\" -f $herkunft) -ForegroundColor $hCol }\n            $nTxt = if ($grundKB -gt 0 -and $f.NettoKB -ne $f.KB) { \" (ueber Grundmuster: $($f.NettoKB) KB)\" } else { '' }\n            Write-Host (\"      {0} private ausfuehrbare Bereiche, zusammen {1} KB{2}{3}\" -f $f.Anzahl, $f.KB, $nTxt, $(if ($f.Jit) { ' (Prozess mit JIT-Compiler)' } else { '' })) -ForegroundColor $col\n            foreach ($b in ($f.PE | Select-Object -First 5)) {\n                $art = if ($b.PE) { 'vollstaendiger PE-Header (MZ+PE) - komplette DLL ohne Datei!' } else { 'MZ-Signatur' }\n                Write-Host (\"      [!!!] 0x{0:X} ({1} KB): {2}\" -f $b.Basis, [Math]::Round($b.Groesse / 1KB), $art) -ForegroundColor Red\n            }\n        }\n        Write-Host \"`n  Rot  = PE-Header in dateilosem Speicher ODER ueber 512 KB (ueber Grundmuster) in einem Windows-Prozess.\" -ForegroundColor DarkGray\n        Write-Host \"  Gelb = groesserer ausfuehrbarer Privatspeicher in einem Programm ohne JIT - Hersteller-Overlays/Schutzsoftware moeglich.\" -ForegroundColor DarkGray\n        Write-Host \"  Naechster Schritt: betroffene PID mit System Informer oder Hollows Hunter genauer ansehen / dumpen.\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"  Kein dateiloser ausfuehrbarer Code in Prozessen ohne JIT gefunden.\" -ForegroundColor Green\n    }\n    if ($keinZugriff -gt 0) {\n        Write-Host (\"  ({0} geschuetzte Prozesse nicht lesbar, z. B. lsass/Antivirus - normal)\" -f $keinZugriff) -ForegroundColor DarkGray\n    }\n\n    # ============================================================\n    # 21b: Einstiegswege in signierte Prozesse (rueckwirkend)\n    # ============================================================\n    Write-Host \"`n--- 21b: Einstiegswege in signierte Prozesse ---\" -ForegroundColor DarkGray\n    $weg = 0\n\n    # IFEO: Debugger / VerifierDlls / GlobalFlag\n    foreach ($ifeo in @('HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options',\n                        'HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options')) {\n        Get-ChildItem $ifeo -ErrorAction SilentlyContinue | ForEach-Object {\n            $k = $_; $pr = Get-ItemProperty $k.PSPath -ErrorAction SilentlyContinue\n            if (-not $pr) { return }\n            $zt = &amp; $keyZeit $k.PSPath\n            if ($pr.VerifierDlls) {\n                Write-Host (\"  [!!!] IFEO VerifierDlls fuer {0}: {1}  (geaendert {2}) - DLL wird in JEDEN Start geladen\" -f $k.PSChildName, $pr.VerifierDlls, $zt) -ForegroundColor Red; $weg++\n            }\n            if ($pr.Debugger) {\n                $col = if ($pr.Debugger -match '(?i)\\\\(Temp|AppData|Downloads|ProgramData|Users\\\\Public)\\\\') { 'Red' } else { 'Yellow' }\n                Write-Host (\"  [!] IFEO Debugger fuer {0}: {1}  (geaendert {2})\" -f $k.PSChildName, $pr.Debugger, $zt) -ForegroundColor $col; $weg++\n            }\n            if ($pr.GlobalFlag -and ([int64]$pr.GlobalFlag -band 0x100)) {\n                Write-Host (\"  [!] IFEO GlobalFlag mit Application Verifier fuer {0}  (geaendert {1})\" -f $k.PSChildName, $zt) -ForegroundColor Yellow; $weg++\n            }\n        }\n    }\n    # SilentProcessExit\n    Get-ChildItem 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit' -ErrorAction SilentlyContinue | ForEach-Object {\n        $pr = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue\n        if ($pr.MonitorProcess) { Write-Host (\"  [!] SilentProcessExit fuer {0} startet: {1}\" -f $_.PSChildName, $pr.MonitorProcess) -ForegroundColor Red; $weg++ }\n    }\n    # AppCertDlls\n    $acd = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCertDlls'\n    if (Test-Path $acd) {\n        (Get-ItemProperty $acd -ErrorAction SilentlyContinue).PSObject.Properties | Where-Object { $_.Name -notlike 'PS*' } | ForEach-Object {\n            Write-Host (\"  [!!!] AppCertDlls: {0} = {1}  (geaendert {2})\" -f $_.Name, $_.Value, (&amp; $keyZeit $acd)) -ForegroundColor Red; $weg++\n        }\n    }\n    # COM-Hijacking in der Benutzer-Registry (ueberschreibt systemweite COM-Klassen)\n    Get-ChildItem 'Registry::HKEY_USERS' -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -match '^S-1-5-21-[\\d-]+_Classes$' } | ForEach-Object {\n        $clsidRoot = \"Registry::HKEY_USERS\\$($_.PSChildName)\\CLSID\"\n        Get-ChildItem $clsidRoot -ErrorAction SilentlyContinue | ForEach-Object {\n            $ips = Join-Path $_.PSPath 'InprocServer32'\n            if (-not (Test-Path $ips)) { return }\n            $dll = [string](Get-ItemProperty $ips -ErrorAction SilentlyContinue).'(default)'\n            if (-not $dll) { return }\n            $dllPfad = [Environment]::ExpandEnvironmentVariables($dll.Trim('\"'))\n            $si = &amp; $sigVon $dllPfad\n            $ueberschreibt = Test-Path (\"Registry::HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\CLSID\\\" + $_.PSChildName)\n            if ($si.Status -ne 'Valid' -or ($ueberschreibt -and -not $si.MS)) {\n                $col = if ($ueberschreibt) { 'Red' } else { 'Yellow' }\n                $hin = if ($ueberschreibt) { 'UEBERSCHREIBT systemweite COM-Klasse' } else { 'nur Benutzer-COM' }\n                Write-Host (\"  [!] COM {0} -&gt; {1} | Sig: {2} | {3} (geaendert {4})\" -f $_.PSChildName, $dllPfad, $si.Status, $hin, (&amp; $keyZeit $ips)) -ForegroundColor $col; $weg++\n            }\n        }\n    }\n    if ($weg -eq 0) { Write-Host \"  Keine IFEO-, AppCert-, SilentProcessExit- oder COM-Einstiege gefunden.\" -ForegroundColor Green }\n\n    # ============================================================\n    # 21c: Verwundbare Treiber (Kernel Manual Map / BYOVD)\n    # ============================================================\n    Write-Host \"`n--- 21c: Verwundbare Treiber (Kernel Manual Map, z. B. kdmapper) ---\" -ForegroundColor DarkGray\n    $blKey = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\CI\\Config'\n    $bl = (Get-ItemProperty $blKey -ErrorAction SilentlyContinue).VulnerableDriverBlocklistEnable\n    if ($null -ne $bl -and [int]$bl -eq 0) {\n        Write-Host (\"  [!!!] Microsoft-Sperrliste fuer verwundbare Treiber ABGESCHALTET (geaendert {0})\" -f (&amp; $keyZeit $blKey)) -ForegroundColor Red\n    } elseif ($null -ne $bl) {\n        Write-Host \"  Sperrliste fuer verwundbare Treiber aktiv.\" -ForegroundColor Green\n    } else {\n        Write-Host \"  Sperrliste: kein expliziter Wert (Windows-Standard).\" -ForegroundColor DarkGray\n    }\n    $byovd = '(?i)(^|\\\\)(iqvw64e|rtcore64|rtcore32|gdrv|asrdrv\\d*|asio\\d*|asupio|capcom|mhyprot\\d*|dbutil_2_3|\\bene\\b|winring0\\w*|glckio\\d*|nvoclock|atillk64|bs_rcio\\d*|phymem\\w*|inpoutx64|zam64|kprocesshacker|procexp1\\d\\d|gmer\\d*|speedfan|hw64|cpuz\\d+)\\.sys$'\n    $trTreffer = @()\n    Get-CimInstance Win32_SystemDriver -ErrorAction SilentlyContinue | Where-Object { $_.PathName -match $byovd } | ForEach-Object {\n        $trTreffer += [PSCustomObject]@{ Quelle=\"Treiber ($($_.State))\"; Name=$_.Name; Pfad=$_.PathName }\n    }\n    Get-ItemProperty 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\*' -ErrorAction SilentlyContinue | Where-Object { [string]$_.ImagePath -match $byovd } | ForEach-Object {\n        $trTreffer += [PSCustomObject]@{ Quelle='Dienst-Registry'; Name=$_.PSChildName; Pfad=[string]$_.ImagePath }\n    }\n    $tempOrte = @(\"$env:SystemRoot\\Temp\")\n    Get-ChildItem 'C:\\Users' -Directory -ErrorAction SilentlyContinue | ForEach-Object { $tempOrte += (Join-Path $_.FullName 'AppData\\Local\\Temp') }\n    foreach ($to in $tempOrte) {\n        Get-ChildItem $to -Recurse -Depth 2 -Filter '*.sys' -File -Force -ErrorAction SilentlyContinue | ForEach-Object {\n            $trTreffer += [PSCustomObject]@{ Quelle='Treiberdatei in TEMP'; Name=$_.Name; Pfad=(\"{0}  (erstellt {1})\" -f $_.FullName, $_.CreationTime) }\n        }\n    }\n    $trTreffer = @($trTreffer | Group-Object { \"$($_.Quelle)|$($_.Name)\" } | ForEach-Object { $_.Group[0] })\n    if ($trTreffer.Count -gt 0) {\n        $trTreffer | ForEach-Object {\n            $col = if ($_.Quelle -match 'TEMP' -or $_.Name -match '(?i)iqvw64e|capcom|mhyprot|dbutil') { 'Red' } else { 'Yellow' }\n            Write-Host (\"  [!] {0}: {1} -&gt; {2}\" -f $_.Quelle, $_.Name, $_.Pfad) -ForegroundColor $col\n        }\n        Write-Host \"  Hinweis: WinRing0/CPU-Z/HWiNFO/Process Explorer nutzen einige dieser Treiber legitim. .sys in TEMP ist es nie.\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"  Keine bekannten verwundbaren Treiber und keine Treiberdateien in TEMP.\" -ForegroundColor Green\n    }\n\n    # ============================================================\n    # 21d: Side-Loading - signierte EXE + unsignierte System-DLL daneben\n    # ============================================================\n    Write-Host \"`n--- 21d: Side-Loading (signierte EXE mit gefaelschter System-DLL im selben Ordner) ---\" -ForegroundColor DarkGray\n    $sysDll = '(?i)^(version|winhttp|wininet|dbghelp|dbgcore|uxtheme|dwmapi|cryptbase|cryptsp|winmm|userenv|profapi|wtsapi32|iphlpapi|netapi32|mpr|secur32|sspicli|wldp|amsi|msimg32|oleacc|propsys|edputil|winsta|dsound|dxgi|d3d9|d3d10|d3d11|d3d12|dinput8|xinput1_3|xinput1_4|xinput9_1_0|opengl32|hid|setupapi|cfgmgr32|wer|dbgeng|srvcli|netutils|ntmarta|textshaping|mscms|winspool)\\.dll$'\n    $grafik = '(?i)^(dxgi|d3d9|d3d10|d3d11|d3d12|dinput8|opengl32|xinput1_3|xinput1_4|xinput9_1_0)\\.dll$'\n    $slOrte = @(\"$env:ProgramData\", 'C:\\Users\\Public')\n    Get-ChildItem 'C:\\Users' -Directory -ErrorAction SilentlyContinue | ForEach-Object {\n        $slOrte += @((Join-Path $_.FullName 'AppData'), (Join-Path $_.FullName 'Downloads'), (Join-Path $_.FullName 'Desktop'), (Join-Path $_.FullName 'Documents'))\n    }\n    $sl = 0\n    foreach ($o in $slOrte) {\n        if (-not (Test-Path $o)) { continue }\n        Get-ChildItem $o -Recurse -Depth 4 -Filter '*.dll' -File -Force -ErrorAction SilentlyContinue | Where-Object { $_.Name -match $sysDll } | ForEach-Object {\n            $dll = $_\n            $si = &amp; $sigVon $dll.FullName\n            if ($si.Status -eq 'Valid') { return }\n            $exes = @(Get-ChildItem $dll.DirectoryName -Filter '*.exe' -File -ErrorAction SilentlyContinue)\n            if ($exes.Count -eq 0) { return }\n            $signierteExe = @($exes | Where-Object { (&amp; $sigVon $_.FullName).Status -eq 'Valid' } | Select-Object -ExpandProperty Name)\n            $col = if ($dll.Name -match $grafik) { 'Yellow' } else { 'Red' }\n            $hin = if ($dll.Name -match $grafik) { ' (Grafik-DLL - auch ReShade/Overlays)' } else { '' }\n            Write-Host (\"  [!] {0}  [Sig: {1}, erstellt {2}]{3}\" -f $dll.FullName, $si.Status, $dll.CreationTime, $hin) -ForegroundColor $col\n            if ($signierteExe.Count -gt 0) { Write-Host (\"      Signierte EXE im selben Ordner: {0}\" -f (($signierteExe | Select-Object -First 4) -join ', ')) -ForegroundColor DarkGray }\n            $sl++\n        }\n    }\n    if ($sl -eq 0) { Write-Host \"  Keine unsignierten System-DLL-Namen neben Programmen in Benutzerordnern.\" -ForegroundColor Green }\n\n    # ============================================================\n    # 21e: Hollows Hunter als Zweitmeinung (optional)\n    # ============================================================\n    if (-not $OhneFrage) {\n        $hh = Get-ChildItem \"$env:USERPROFILE\\Desktop\\CTC_Tools\" -Recurse -Filter 'hollows_hunter*.exe' -ErrorAction SilentlyContinue | Select-Object -First 1\n        if ($hh) {\n            $w = Read-Host \"`nHollows Hunter als Zweitmeinung laufen lassen? Scannt alle Prozesse, 1-5 Min [j/N]\"\n            if ($w -match '^[jJyY]') {\n                $out = Join-Path $env:TEMP (\"ctc_hh_\" + (Get-Date -Format 'yyyyMMddHHmmss'))\n                New-Item -ItemType Directory -Path $out -Force | Out-Null\n                Write-Host \"  Hollows Hunter laeuft...\" -ForegroundColor DarkGray\n                &amp; $hh.FullName /dir $out 2&gt;&amp;1 | Out-Null\n                $verd = @(Get-ChildItem $out -Recurse -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -match '^process_(\\d+)$' })\n                if ($verd.Count -gt 0) {\n                    Write-Host (\"  [!] Hollows Hunter meldet {0} auffaellige Prozesse:\" -f $verd.Count) -ForegroundColor Red\n                    foreach ($v in $verd) {\n                        $vpid = [int]($v.Name -replace '^process_','')\n                        $vp = Get-Process -Id $vpid -ErrorAction SilentlyContinue\n                        Write-Host (\"      PID {0}  {1}  {2}\" -f $vpid, $(if ($vp) { $vp.Name } else { '(beendet)' }), $(if ($vp) { $vp.Path } else { '' })) -ForegroundColor Red\n                    }\n                    Write-Host \"  Berichte und Dumps: $out\" -ForegroundColor DarkGray\n                    Write-Host \"  Hinweis: Hooks von Antivirus/Overlays (Malwarebytes, NVIDIA, Discord) loesen ebenfalls aus - mit 21a abgleichen.\" -ForegroundColor DarkGray\n                } else {\n                    Write-Host \"  Hollows Hunter: keine auffaelligen Prozesse.\" -ForegroundColor Green\n                    Remove-Item $out -Recurse -Force -ErrorAction SilentlyContinue\n                }\n            }\n        } else {\n            Write-Host \"`n  (Hollows Hunter nicht gefunden - ueber Punkt 18, Eintrag 8, fuer eine Zweitmeinung laden.)\" -ForegroundColor DarkGray\n        }\n    }\n\n    Write-Host \"`nAuswertung:\" -ForegroundColor DarkGray\n    Write-Host \"  21a findet den Cheat nur, solange er geladen ist - bei einem Dienst meist dauerhaft, also auch ohne laufendes Spiel.\" -ForegroundColor DarkGray\n    Write-Host \"  21b-21d finden den Einstieg auch rueckwirkend. Zeitstempel der Aenderung in Punkt 19 als Startzeit nutzen.\" -ForegroundColor DarkGray\n    Write-Host \"  Grenze: Ein Cheat ohne PE-Header in einem JIT-Prozess (Browser, Discord) ist per Speicherscan kaum zu trennen.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  22 - DLL-Historie aus Prefetch (rueckwirkend, auch geloeschte DLLs)\n# ============================================================\nfunction Invoke-DllHistory {\n    Write-Host \"`n=== DLL-Historie: welche DLLs haben Programme beim Start geladen (Prefetch) ===\" -ForegroundColor Cyan\n    Write-Host \"(Windows speichert pro Programm die Dateien der ersten ~10 Sekunden - auch DLLs, die heute geloescht sind)\" -ForegroundColor DarkGray\n\n    Add-Type -ErrorAction SilentlyContinue -TypeDefinition @\"\nusing System;\nusing System.IO;\nusing System.Text;\nusing System.Runtime.InteropServices;\npublic static class CtcPf {\n    [DllImport(\"ntdll.dll\")] static extern uint RtlGetCompressionWorkSpaceSize(ushort fmt, out uint bufWs, out uint fragWs);\n    [DllImport(\"ntdll.dll\")] static extern uint RtlDecompressBufferEx(ushort fmt, byte[] outBuf, int outSize, byte[] inBuf, int inSize, out int finalSize, byte[] work);\n\n    static byte[] Entpacke(byte[] d) {\n        if (d.Length &lt; 8) return null;\n        if (d[0] == 0x4D &amp;&amp; d[1] == 0x41 &amp;&amp; d[2] == 0x4D) {            // 'MAM' = komprimiert (Windows 10/11)\n            ushort fmt = (ushort)(d[3] &amp; 0x0F);\n            int start = ((d[3] &amp; 0x80) != 0) ? 12 : 8;                  // optionale CRC\n            int groesse = BitConverter.ToInt32(d, 4);\n            if (groesse &lt;= 0 || groesse &gt; 64 * 1024 * 1024) return null;\n            uint ws, fs;\n            if (RtlGetCompressionWorkSpaceSize(fmt, out ws, out fs) != 0) return null;\n            byte[] work = new byte[Math.Max(ws, fs)];\n            byte[] ein = new byte[d.Length - start];\n            Array.Copy(d, start, ein, 0, ein.Length);\n            byte[] aus = new byte[groesse];\n            int fertig;\n            if (RtlDecompressBufferEx(fmt, aus, groesse, ein, ein.Length, out fertig, work) != 0) return null;\n            return aus;\n        }\n        return d;                                                        // unkomprimiert (aeltere Windows)\n    }\n\n    public static string[] Dateien(string pfad) {\n        try {\n            byte[] d = Entpacke(File.ReadAllBytes(pfad));\n            if (d == null || d.Length &lt; 0x70) return new string[0];\n            if (d[4] != 0x53 || d[5] != 0x43 || d[6] != 0x43 || d[7] != 0x41) return new string[0];   // 'SCCA'\n            int off = BitConverter.ToInt32(d, 0x64);\n            int len = BitConverter.ToInt32(d, 0x68);\n            if (off &lt;= 0 || len &lt;= 0 || (long)off + len &gt; d.Length) return new string[0];\n            return Encoding.Unicode.GetString(d, off, len).Split(new[] { '\\0' }, StringSplitOptions.RemoveEmptyEntries);\n        } catch { return new string[0]; }\n    }\n}\n\"@\n\n    $pfOrdner = \"$env:SystemRoot\\Prefetch\"\n    $pfs = @(Get-ChildItem \"$pfOrdner\\*.pf\" -ErrorAction SilentlyContinue)\n    if ($pfs.Count -eq 0) {\n        Write-Host \"  Keine Prefetch-Dateien - Prefetch ist deaktiviert oder wurde geleert. Das ist selbst ein Befund (siehe Punkt 2).\" -ForegroundColor Red\n        return\n    }\n\n    $bekannteSigner = '(?i)Valve|NVIDIA|Discord|Spotify|Google|Razer|Logitech|Corsair|Elgato|Adobe|Malwarebytes|Epic Games|Riot|Electronic Arts|Ubisoft|Rockstar|Cfx|Intel|Advanced Micro|Realtek|Mozilla|Opera|Brave|Microsoft|Apple|Dropbox|Zoom|TeamSpeak|Overwolf|SteelSeries|Turtle Beach|Nahimic|ASUSTeK|Micro-Star|Gigabyte|Medal|OBS Project|TC-Helicon|Oracle|Python|Igor Pavlov|Notepad\\+\\+|WinRAR|win\\.rar'\n    $sysDllName     = '(?i)\\\\(version|winhttp|wininet|dbghelp|dbgcore|uxtheme|dwmapi|cryptbase|cryptsp|winmm|userenv|profapi|wtsapi32|iphlpapi|netapi32|mpr|secur32|sspicli|wldp|amsi|msimg32|oleacc|propsys|edputil|winsta|dsound|hid|setupapi|cfgmgr32|wer|dbgeng|srvcli|netutils|ntmarta|mscms|winspool)\\.dll$'\n    $phantom        = '(?i)\\\\WptsExtensions\\.dll$|\\\\wbem\\\\(WaaSMedicSvc|wlbsctrl)\\.dll$'\n    $benutzerOrt    = '(?i)\\\\(Temp|Downloads|Desktop)\\\\|\\\\AppData\\\\|\\\\ProgramData\\\\|\\\\Users\\\\Public\\\\'\n\n    $sigCache = @{}\n    $sigVon = {\n        param([string]$pfad)\n        if ($sigCache.ContainsKey($pfad)) { return $sigCache[$pfad] }\n        $s  = Get-AuthenticodeSignature -LiteralPath $pfad -ErrorAction SilentlyContinue\n        $sg = if ($s -and $s.SignerCertificate) { $s.SignerCertificate.Subject -replace '^(?:.*?,\\s*)?CN=(?:\"([^\"]+)\"|([^,]+)).*$','$1$2' } else { '-' }\n        $ok = $s -and $s.Status -eq 'Valid'\n        $r  = [PSCustomObject]@{ Status=$(if ($s) { [string]$s.Status } else { '?' }); Signierer=$sg; MS=($ok -and $sg -match '(?i)Microsoft'); Bekannt=($ok -and $sg -match $bekannteSigner) }\n        $sigCache[$pfad] = $r\n        $r\n    }\n    $versionWild = {\n        param([string]$pfad)\n        $w = $pfad -replace '(?i)\\\\([a-z_]+-)?\\d+(\\.\\d+)+\\\\', '\\*\\'\n        $w = $w    -replace '(?i)\\\\[^\\\\]*_amd64_[0-9a-f]{16}\\\\', '\\*\\'\n        $w -replace '(?i)\\\\[0-9a-f]{12,}\\\\', '\\*\\'\n    }\n\n    # \\VOLUME{...}\\PFAD -&gt; Laufwerksbuchstabe (Prefetch speichert Volumes, keine Buchstaben)\n    $laufwerke = @(Get-PSDrive -PSProvider FileSystem -ErrorAction SilentlyContinue | Where-Object { $_.Root -match '^[A-Z]:\\\\$' } | ForEach-Object { $_.Root.Substring(0,2) })\n    $aufgeloest = @{}\n    $aufloesen = {\n        param([string]$roh)\n        if ($aufgeloest.ContainsKey($roh)) { return $aufgeloest[$roh] }\n        $rest = $roh -replace '^\\\\VOLUME\\{[^}]*\\}','' -replace '(?i)^\\\\DEVICE\\\\HARDDISKVOLUME\\d+',''\n        $r = $null\n        foreach ($lw in $laufwerke) { if (Test-Path -LiteralPath ($lw + $rest)) { $r = [PSCustomObject]@{ Pfad=($lw + $rest); Da=$true }; break } }\n        if (-not $r) { $r = [PSCustomObject]@{ Pfad=('C:' + $rest); Da=$false } }\n        $aufgeloest[$roh] = $r\n        $r\n    }\n\n    # --- Sammeln ---\n    Write-Host (\"  Lese {0} Prefetch-Dateien...\" -f $pfs.Count) -ForegroundColor DarkGray\n    $dll = @{}\n    $leer = 0; $n = 0\n    foreach ($pf in $pfs) {\n        $n++\n        if ($n % 40 -eq 0) { Write-Progress -Activity 'CTC Prefetch-Auswertung' -Status \"$n / $($pfs.Count)\" -PercentComplete ($n / $pfs.Count * 100) }\n        $wirt  = $pf.BaseName -replace '-[0-9A-F]{8}$',''\n        $liste = [CtcPf]::Dateien($pf.FullName)\n        if ($liste.Count -eq 0) { $leer++; continue }\n        $wirtPfad = $liste | Where-Object { $_ -like \"*\\$wirt\" } | Select-Object -First 1\n        $winWirt  = [string]$wirtPfad -match '(?i)\\\\WINDOWS\\\\'\n        foreach ($roh in $liste) {\n            if ($roh -notmatch '(?i)\\.dll$') { continue }\n            $a = &amp; $aufloesen $roh\n            $k = $a.Pfad.ToLower()\n            if (-not $dll.ContainsKey($k)) {\n                $dll[$k] = [PSCustomObject]@{ Pfad=$a.Pfad; Da=$a.Da; Wirte=@{}; WinWirt=$false; Erst=$pf.CreationTime; Letzt=$pf.LastWriteTime }\n            }\n            $o = $dll[$k]\n            $o.Wirte[$wirt] = $true\n            if ($winWirt) { $o.WinWirt = $true }\n            if ($pf.CreationTime  -lt $o.Erst)  { $o.Erst  = $pf.CreationTime }\n            if ($pf.LastWriteTime -gt $o.Letzt) { $o.Letzt = $pf.LastWriteTime }\n        }\n    }\n    Write-Progress -Activity 'CTC Prefetch-Auswertung' -Completed\n    Write-Host (\"  {0} verschiedene DLLs in den Ladelisten gefunden.\" -f $dll.Count) -ForegroundColor DarkGray\n\n    # --- Bewerten ---\n    $funde = @(); $bekanntN = 0; $updateN = 0\n    $installerOrdner = '(?i)\\\\(ns[a-z0-9]+\\.tmp|7zs[0-9a-f]+\\.tmp|is-[a-z0-9]{5}\\.tmp|tlsfx[0-9a-f]+|ts3import|[^\\\\]+\\.tmp)\\\\|\\\\\\{[0-9a-f-]{36}\\}\\\\\\.ba\\\\'\n    $installerWirt   = '(?i)setup|install|_inst|redist|sfx|driver|dotnet-runtime|update|\\.tmp$'\n    $installerWirte  = @{}; $installerN = 0\n    $addTypeZeiten   = @()\n    foreach ($o in $dll.Values) {\n        $p = $o.Pfad\n        $stufe = $null; $grund = ''\n        $wirte = @($o.Wirte.Keys)\n        $cn = Get-CheatName (\"{0} {1}\" -f $p, ($wirte -join ' '))\n        if ($cn) { $funde += [PSCustomObject]@{ O=$o; Stufe='Rot'; Grund=\"BEKANNTER CHEAT-NAME: $cn\" }; continue }\n\n        # PowerShell Add-Type: csc.exe kompiliert C#-Code nach TEMP\\xxxxxxxx\\xxxxxxxx.dll (macht auch CTC selbst)\n        if ($wirte -contains 'CSC.EXE' -and $p -match '(?i)\\\\Temp\\\\([a-z0-9]{8})\\\\\\1\\.dll$') { $addTypeZeiten += $o.Letzt; continue }\n        # Installer entpacken DLLs nach Temp, laden sie und loeschen sie wieder\n        $alleInstaller = @($wirte | Where-Object { $_ -notmatch $installerWirt }).Count -eq 0\n        if ($p -match '(?i)\\\\Temp\\\\' -and ($p -match $installerOrdner -or $alleInstaller)) {\n            $installerN++; foreach ($w in $wirte) { $installerWirte[$w] = $true }; continue\n        }\n\n        if ($p -match $phantom) {\n            $stufe = 'Rot'; $grund = 'Phantom-DLL - gehoert nicht an diesen Ort (Hijacking)'\n        }\n        elseif ($p -match '(?i)^[A-Z]:\\\\WINDOWS\\\\') {\n            if ($p -match '(?i)\\\\(WinSxS|assembly|Microsoft\\.NET|SoftwareDistribution|servicing|System32\\\\DriverStore|SysWOW64\\\\DriverStore)\\\\') { continue }\n            if ($p -match '(?i)^[A-Z]:\\\\WINDOWS\\\\(System32|SysWOW64)\\\\[^\\\\]+\\.dll$') { continue }   # System32-Wurzel prueft Punkt 16\n            if ($p -match '(?i)\\\\WINDOWS\\\\Temp\\\\') { $stufe = 'Rot'; $grund = 'aus C:\\Windows\\Temp geladen' }\n            elseif (-not $o.Da) {\n                if ((&amp; $versionWild $p) -ne $p -and (Test-Path (&amp; $versionWild $p))) { $updateN++; continue }\n                $stufe = 'Gelb'; $grund = 'im Windows-Ordner, heute GELOESCHT'\n            } else {\n                $si = &amp; $sigVon $p\n                if (-not $si.MS) {\n                    if ($si.Bekannt) { $bekanntN++; continue }\n                    $stufe = 'Rot'; $grund = \"im Windows-Ordner, aber NICHT von Microsoft signiert ($($si.Status) / $($si.Signierer))\"\n                }\n            }\n        }\n        else {\n            if (-not $o.Da) {\n                $w = &amp; $versionWild $p\n                if ($w -ne $p -and (Test-Path $w)) { $updateN++; continue }\n                if ($p -match '(?i)\\\\(Temp|Downloads|Desktop)\\\\') { $stufe = 'Rot'; $grund = 'aus Temp/Downloads/Desktop geladen, heute GELOESCHT' }\n                elseif ($o.WinWirt)                              { $stufe = 'Rot'; $grund = 'von einem Windows-Prozess geladen, heute GELOESCHT' }\n                elseif ($p -match $sysDllName)                   { $stufe = 'Rot'; $grund = 'System-DLL-Name ausserhalb von Windows (Side-Loading), heute GELOESCHT' }\n            } else {\n                $pruefen = $o.WinWirt -or ($p -match $sysDllName) -or ($p -match '(?i)\\\\Temp\\\\')\n                if ($pruefen) {\n                    $si = &amp; $sigVon $p\n                    if ($si.MS -or $si.Bekannt) { $bekanntN++; continue }\n                    if ($p -match $sysDllName -and $si.Status -ne 'Valid') { $stufe = 'Rot';  $grund = \"System-DLL-Name ausserhalb von Windows, unsigniert (Side-Loading)\" }\n                    elseif ($si.Status -ne 'Valid')                        { $stufe = 'Rot';  $grund = \"unsigniert ($($si.Status)), geladen von Windows-Prozess oder aus Temp\" }\n                    elseif ($o.WinWirt)                                     { $stufe = 'Gelb'; $grund = \"Windows-Prozess laedt DLL eines unbekannten Herstellers ($($si.Signierer))\" }\n                }\n            }\n        }\n        if ($stufe) { $funde += [PSCustomObject]@{ O=$o; Stufe=$stufe; Grund=$grund } }\n    }\n\n    # --- Ausgabe ---\n    if ($funde.Count -gt 0) {\n        Write-Host (\"`n  {0} auffaellige DLL-Ladevorgaenge:\" -f $funde.Count) -ForegroundColor Yellow\n        foreach ($f in ($funde | Sort-Object { $_.Stufe -ne 'Rot' }, { $_.O.Letzt } -Descending | Select-Object -First 60)) {\n            $col = if ($f.Stufe -eq 'Rot') { 'Red' } else { 'Yellow' }\n            Write-Host (\"`n  [{0}] {1}\" -f $f.O.Letzt.ToString('dd.MM.yyyy HH:mm'), $f.O.Pfad) -ForegroundColor $col\n            Write-Host (\"      {0}\" -f $f.Grund) -ForegroundColor $col\n            Write-Host (\"      geladen von: {0}\" -f (($f.O.Wirte.Keys | Sort-Object | Select-Object -First 8) -join ', ')) -ForegroundColor DarkGray\n        }\n        Write-Host \"`n  Zeit = letzter Start des ladenden Programms (Prefetch). Diesen Zeitpunkt in Punkt 19 als Startzeit nutzen.\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"  Keine auffaelligen DLL-Ladevorgaenge in den Prefetch-Ladelisten.\" -ForegroundColor Green\n    }\n    if ($addTypeZeiten.Count -gt 0) {\n        $zeiten = @($addTypeZeiten | Sort-Object -Descending | ForEach-Object { $_.ToString('dd.MM.yyyy HH:mm') } | Select-Object -Unique -First 6)\n        Write-Host (\"`n  [!] PowerShell hat C#-Code kompiliert (Add-Type), {0} DLLs, zuletzt: {1}\" -f $addTypeZeiten.Count, ($zeiten -join ' | ')) -ForegroundColor Yellow\n        Write-Host \"      CTC macht das selbst. Zeitpunkte AUSSERHALB eines CTC-Laufs = ein PowerShell-Skript hat C#-Code geladen (typisch fuer Loader).\" -ForegroundColor DarkGray\n    }\n    if ($installerN -gt 0) {\n        Write-Host (\"  ({0} DLLs von Installern entpackt und wieder geloescht - Installer: {1})\" -f $installerN, (($installerWirte.Keys | Sort-Object | Select-Object -First 12) -join ', ')) -ForegroundColor DarkGray\n        Write-Host \"   Unbekannter Installer-Name in dieser Liste = pruefen, was da installiert wurde.\" -ForegroundColor DarkGray\n    }\n    if ($bekanntN -gt 0) { Write-Host (\"  ({0} DLLs bekannter, signierter Hersteller ausgeblendet)\" -f $bekanntN) -ForegroundColor DarkGray }\n    if ($updateN  -gt 0) { Write-Host (\"  ({0} geloeschte DLLs alter Programmversionen ausgeblendet - neuere Version existiert)\" -f $updateN) -ForegroundColor DarkGray }\n    if ($leer -gt 0)     { Write-Host (\"  ({0} Prefetch-Dateien nicht lesbar)\" -f $leer) -ForegroundColor DarkGray }\n\n    Write-Host \"`nAuswertung:\" -ForegroundColor DarkGray\n    Write-Host \"  Rot bei einem Windows-Prozess (svchost, WmiPrvSE, explorer ...) = eine fremde DLL wurde in einen signierten Prozess geladen.\" -ForegroundColor DarkGray\n    Write-Host \"  Grenze: Prefetch erfasst nur die ersten ~10 Sekunden nach Programmstart und max. 1024 Programme.\" -ForegroundColor DarkGray\n    Write-Host \"  Eine DLL, die spaeter per Injection nachgeladen wird, steht hier nicht - dafuer Punkt 21a (Speicher) und 19 (USN).\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  23 - Web: Cheat-Seiten, Download-Herkunft, DNS\n# ============================================================\nfunction Invoke-WebCheck {\n    Write-Host \"`n=== Web: Cheat-Seiten, Download-Herkunft, DNS ===\" -ForegroundColor Cyan\n    Write-Host \"(Nur Treffer auf Cheat-Merkmale - kein vollstaendiger Verlauf, keine Passwoerter, Cookies oder Token)\" -ForegroundColor DarkGray\n\n    # ---- Eigene Listen (vom Team pflegen) ----\n    # Begriffe in Domains, Adressen, Suchanfragen und Dateinamen\n    $cheatBegriffe = '(?i)cheat|hack|spoof|bypass|aimbot|wallhack|triggerbot|silent.?aim|undetect|injector|\\bloader\\b|hwid|\\bdma\\b|fuser|kmbox|makcu|pcileech|mod.?menu|executor|\\besp\\b'\n    $shopAuth  = '(?i)keyauth\\.|sellix\\.io|sell\\.app|shoppy\\.gg|sellpass\\.io|selly\\.(gg|io)|sellauth\\.'\n    $hoster    = '(?i)gofile\\.io|mediafire\\.com|mega\\.nz|pixeldrain\\.com|workupload\\.com|anonfiles|transfer\\.sh|filebin\\.net|send\\.cm'\n    $ausfDatei = '(?i)\\.(exe|dll|sys|zip|rar|7z|bat|ps1|msi|scr|iso)(\\?|&amp;|$)'\n\n    # Datei kopieren (auch wenn der Browser laeuft) und alle URLs herausziehen\n    $urlsAus = {\n        param([string]$datei)\n        $tmp = Join-Path $env:TEMP (\"ctc_web_\" + [guid]::NewGuid().ToString('N'))\n        try {\n            try { Copy-Item -LiteralPath $datei -Destination $tmp -ErrorAction Stop }\n            catch { &amp; esentutl.exe /y $datei /vss /d $tmp 2&gt;&amp;1 | Out-Null }\n            if (-not (Test-Path $tmp)) { return @() }\n            $raw = [System.IO.File]::ReadAllText($tmp, [Text.Encoding]::GetEncoding('ISO-8859-1'))\n            @([regex]::Matches($raw, 'https?://[\\x21-\\x7E]{4,400}') | ForEach-Object { $_.Value.TrimEnd('\"', \"'\", ')', ',', ';') })\n        } catch { @() } finally { Remove-Item $tmp -Force -ErrorAction SilentlyContinue }\n    }\n    $bewerte = {\n        param([string]$u)\n        $h = ''; if ($u -match '^https?://([^/:?#]+)') { $h = $matches[1] }\n        $dek = $u; try { $dek = [uri]::UnescapeDataString(($u -replace '\\+',' ')) } catch {}\n        $cn = Get-CheatName $dek\n        if ($cn)                                                     { return @('Rot',  \"BEKANNTER CHEAT-NAME: $cn\") }\n        if ($h -match $cheatBegriffe)                                { return @('Rot',  'Cheat-Begriff in der Domain') }\n        if ($h -match $shopAuth) {\n            $st = if ($u -match $cheatBegriffe) { 'Rot' } else { 'Gelb' }\n            return @($st, 'Shop-/Lizenzplattform, die Cheat-Verkaeufer nutzen')\n        }\n        if ($h -match $hoster) {\n            $st = if ($u -match $ausfDatei) { 'Rot' } else { 'Gelb' }\n            return @($st, 'Datei-Hoster')\n        }\n        if ($u -match '[?&amp;](q|query|search_query|p|text)=([^&amp;#]+)') {\n            $q = $matches[2]\n            try { $q = [uri]::UnescapeDataString(($q -replace '\\+',' ')) } catch {}\n            if ($q -match $cheatBegriffe) { return @('Gelb', \"Suche: $q\") }\n        }\n        if ($u -match $cheatBegriffe -and $h -notmatch '(?i)(^|\\.)(google|bing|youtube|reddit|duckduckgo|yahoo)\\.') { return @('Gelb', 'Cheat-Begriff in der Adresse') }\n        return $null\n    }\n    $ausgabe = {\n        param($treffer, [int]$max)\n        foreach ($x in ($treffer | Sort-Object { $_.Stufe -ne 'Rot' }, Url | Select-Object -First $max)) {\n            $col = if ($x.Stufe -eq 'Rot') { 'Red' } else { 'Yellow' }\n            $u = $x.Url; if ($u.Length -gt 160) { $u = $u.Substring(0,160) + ' [...]' }\n            Write-Host (\"  [{0}] {1}\" -f $x.Grund, $u) -ForegroundColor $col\n            if ($x.Quelle) { Write-Host (\"      Quelle: {0}\" -f $x.Quelle) -ForegroundColor DarkGray }\n        }\n    }\n\n    $benutzer = @(Get-ChildItem 'C:\\Users' -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -notmatch '^(Public|Default|Default User|All Users)$' })\n\n    # ============================================================\n    # 23a: Browserverlauf\n    # ============================================================\n    Write-Host \"`n--- 23a: Browserverlauf (nur Cheat-Merkmale) ---\" -ForegroundColor DarkGray\n    $webTreffer = @{}\n    $gelesen = 0\n    foreach ($u in $benutzer) {\n        $loc = Join-Path $u.FullName 'AppData\\Local'; $roam = Join-Path $u.FullName 'AppData\\Roaming'\n        $chromium = [ordered]@{\n            'Chrome'  = \"$loc\\Google\\Chrome\\User Data\";  'Edge'    = \"$loc\\Microsoft\\Edge\\User Data\"\n            'Brave'   = \"$loc\\BraveSoftware\\Brave-Browser\\User Data\"; 'Vivaldi' = \"$loc\\Vivaldi\\User Data\"\n            'Opera'   = \"$roam\\Opera Software\\Opera Stable\"; 'OperaGX' = \"$roam\\Opera Software\\Opera GX Stable\"\n        }\n        foreach ($b in $chromium.Keys) {\n            $root = $chromium[$b]\n            if (-not (Test-Path $root)) { continue }\n            $hist = @(Get-ChildItem $root -Recurse -Depth 2 -Filter 'History' -File -Force -ErrorAction SilentlyContinue)\n            foreach ($hf in $hist) {\n                $gelesen++\n                $profil = Split-Path (Split-Path $hf.FullName -Parent) -Leaf\n                foreach ($url in (&amp; $urlsAus $hf.FullName)) {\n                    if ($webTreffer.ContainsKey($url)) { continue }\n                    $bw = &amp; $bewerte $url\n                    if ($bw) { $webTreffer[$url] = [PSCustomObject]@{ Url=$url; Stufe=$bw[0]; Grund=$bw[1]; Quelle=\"$b/$profil ($($u.Name))\" } }\n                }\n            }\n        }\n        $ff = Join-Path $roam 'Mozilla\\Firefox\\Profiles'\n        if (Test-Path $ff) {\n            foreach ($pl in @(Get-ChildItem $ff -Recurse -Depth 1 -Filter 'places.sqlite' -File -ErrorAction SilentlyContinue)) {\n                $gelesen++\n                foreach ($url in (&amp; $urlsAus $pl.FullName)) {\n                    if ($webTreffer.ContainsKey($url)) { continue }\n                    $bw = &amp; $bewerte $url\n                    if ($bw) { $webTreffer[$url] = [PSCustomObject]@{ Url=$url; Stufe=$bw[0]; Grund=$bw[1]; Quelle=\"Firefox ($($u.Name))\" } }\n                }\n            }\n        }\n    }\n    if ($gelesen -eq 0) {\n        Write-Host \"  Kein Browserverlauf gefunden (kein Browser, geloescht oder portable Browser).\" -ForegroundColor Yellow\n    } elseif ($webTreffer.Count -gt 0) {\n        Write-Host (\"  {0} Treffer in {1} Verlaufsdatei(en):\" -f $webTreffer.Count, $gelesen) -ForegroundColor Yellow\n        &amp; $ausgabe $webTreffer.Values 60\n    } else {\n        Write-Host (\"  Keine Cheat-Merkmale in {0} Verlaufsdatei(en).\" -f $gelesen) -ForegroundColor Green\n    }\n    Write-Host \"  (Verlauf enthaelt keine Uhrzeit in dieser Auswertung - Zeitbezug ueber 23c und Punkt 19)\" -ForegroundColor DarkGray\n\n    # ============================================================\n    # 23c: Download-Herkunft (Zone.Identifier)\n    # ============================================================\n    Write-Host \"`n--- 23c: Herkunft heruntergeladener Dateien (Zone.Identifier) ---\" -ForegroundColor DarkGray\n    $dlTreffer = @(); $dlSonst = 0\n    foreach ($u in $benutzer) {\n        foreach ($sub in @('Downloads','Desktop','Documents','AppData\\Local\\Temp')) {\n            $d = Join-Path $u.FullName $sub\n            if (-not (Test-Path $d)) { continue }\n            Get-ChildItem $d -Recurse -Depth 2 -File -Force -ErrorAction SilentlyContinue |\n                Where-Object { $_.Name -match '(?i)\\.(exe|dll|sys|zip|rar|7z|msi|bat|ps1|scr|iso)$' } | ForEach-Object {\n                    $zi = @(Get-Content -LiteralPath $_.FullName -Stream Zone.Identifier -ErrorAction SilentlyContinue)\n                    if ($zi.Count -eq 0) { return }\n                    $hostUrl = ($zi | Where-Object { $_ -like 'HostUrl=*' }     | Select-Object -First 1) -replace '^HostUrl=',''\n                    $refUrl  = ($zi | Where-Object { $_ -like 'ReferrerUrl=*' } | Select-Object -First 1) -replace '^ReferrerUrl=',''\n                    $bw = $null\n                    $cn = Get-CheatName (\"{0} {1} {2}\" -f $_.Name, $hostUrl, $refUrl)\n                    if ($cn) { $bw = @('Rot', \"BEKANNTER CHEAT-NAME: $cn\") }\n                    if (-not $bw -and $hostUrl) { $bw = &amp; $bewerte $hostUrl }\n                    if (-not $bw -and $refUrl) { $bw = &amp; $bewerte $refUrl }\n                    if (-not $bw -and $_.Name -match $cheatBegriffe) { $bw = @('Rot','Cheat-Begriff im Dateinamen') }\n                    if ($bw) {\n                        $dlTreffer += [PSCustomObject]@{ Datei=$_.FullName; Zeit=$_.CreationTime; Von=$hostUrl; Ref=$refUrl; Stufe=$bw[0]; Grund=$bw[1] }\n                    } else { $dlSonst++ }\n                }\n        }\n    }\n    if ($dlTreffer.Count -gt 0) {\n        foreach ($x in ($dlTreffer | Sort-Object Zeit -Descending | Select-Object -First 40)) {\n            $col = if ($x.Stufe -eq 'Rot') { 'Red' } else { 'Yellow' }\n            Write-Host (\"  [{0}] {1}\" -f $x.Zeit.ToString('dd.MM.yyyy HH:mm'), $x.Datei) -ForegroundColor $col\n            Write-Host (\"      {0} | von: {1}\" -f $x.Grund, $(if ($x.Von) { $x.Von } else { '-' })) -ForegroundColor DarkGray\n            if ($x.Ref) { Write-Host (\"      Verweis-Seite: {0}\" -f $x.Ref) -ForegroundColor DarkGray }\n        }\n        Write-Host \"  Download-Zeit = Startzeit fuer Punkt 19.\" -ForegroundColor DarkGray\n    } else {\n        Write-Host \"  Keine heruntergeladenen Dateien aus Cheat-Quellen gefunden.\" -ForegroundColor Green\n    }\n    if ($dlSonst -gt 0) { Write-Host (\"  ({0} weitere Downloads von unauffaelligen Quellen)\" -f $dlSonst) -ForegroundColor DarkGray }\n\n    # ============================================================\n    # 23d: DNS-Cache (seit dem letzten Neustart)\n    # ============================================================\n    Write-Host \"`n--- 23d: DNS-Cache (aufgerufene Domains seit dem letzten Neustart) ---\" -ForegroundColor DarkGray\n    $dns = @(Get-DnsClientCache -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Entry -Unique | Where-Object {\n        $_ -match $cheatBegriffe -or $_ -match $shopAuth -or $_ -match $hoster -or [bool](Get-CheatName $_)\n    })\n    if ($dns.Count -gt 0) {\n        $dns | ForEach-Object {\n            $cn  = Get-CheatName $_\n            $col = if ($cn -or $_ -match $cheatBegriffe) { 'Red' } else { 'Yellow' }\n            Write-Host (\"  {0}{1}\" -f $_, $(if ($cn) { \"   &lt;-- BEKANNTER CHEAT-NAME: $cn\" } else { '' })) -ForegroundColor $col\n        }\n    } else {\n        Write-Host \"  Keine Cheat-, Shop- oder Hoster-Domains im DNS-Cache.\" -ForegroundColor Green\n    }\n\n    Write-Host \"`nAuswertung:\" -ForegroundColor DarkGray\n    Write-Host \"  Staerkste Spur: Downloads, deren Herkunft eine Cheat-Seite, ein Shop oder ein Datei-Hoster ist.\" -ForegroundColor DarkGray\n    Write-Host \"  Shops/Hoster allein sind kein Beweis - viele legitime Verkaeufer nutzen sie. Immer im Zusammenhang werten.\" -ForegroundColor DarkGray\n    Write-Host \"  Geloeschter Verlauf / Inkognito hinterlaesst hier nichts - dann bleiben DNS-Cache, Zone.Identifier und Punkt 19.\" -ForegroundColor DarkGray\n}\n\n# ============================================================\n#  Menue\n# ============================================================\nfunction Show-Menu {\n    Write-Host \"\"\n    Write-Host \"  ============================================\" -ForegroundColor Cyan\n    Write-Host \"    CTC by Dark - CatchTheCheat               \" -ForegroundColor Cyan\n    Write-Host \"  ============================================\" -ForegroundColor Cyan\n\n    Write-Host \"`n  [H] HARDWARE &amp; DMA\" -ForegroundColor Yellow\n    Write-Host \"     3  PCI/PCIe-Geraete (VEN/DEV, Registry-Abgleich)\"\n    Write-Host \"     4  Entfernte Geraete (Zeitfenster)\"\n    Write-Host \"     6  USB-Historie + MAKCU/Arduino/ESP32\"\n    Write-Host \"    15  HVCI, Secure Boot, IOMMU/VT-d (DMA-Schutz), Testsigning\"\n    Write-Host \"    17  DMA Fuser / Zweiter PC / HDMI-Splitter\"\n\n    Write-Host \"`n  [L] LOGS &amp; SPUREN\" -ForegroundColor Yellow\n    Write-Host \"     1  PnP-Ereignisse (411 / 400 / 410 / 420)\"\n    Write-Host \"     2  Log-Integritaet / Amcache / USN / Prefetch\"\n    Write-Host \"     5  Datentraeger-Historie (Partition-Log)\"\n    Write-Host \"    10  PowerShell-History / ScriptBlock / EID 600\"\n    Write-Host \"    19  Session-Timeline: was lief nach der Fernwartung?\"\n\n    Write-Host \"`n  [B] BYPASS &amp; INJECTION\" -ForegroundColor Yellow\n    Write-Host \"     9  Unsignierte Treiber &amp; Prozesse\"\n    Write-Host \"    12  PE Binary Inspector (einzelne Datei)\"\n    Write-Host \"    13  DLL Hijacking (wbem, Phantom-DLLs)\"\n    Write-Host \"    14  Systemprozesse / AppInit / LSA / Winlogon\"\n    Write-Host \"    16  Signatur-Scan + Tiefenanalyse jeder DLL/EXE/SYS (mit HTML-Bericht)\"\n    Write-Host \"    21  Injection in signierte Prozesse (Speicher, IFEO, COM, Treiber)\"\n    Write-Host \"    22  DLL-Historie aus Prefetch (auch geloeschte DLLs)\"\n\n    Write-Host \"`n  [R] REMOTE &amp; IDENTITAET\" -ForegroundColor Yellow\n    Write-Host \"     7  Fernwartungssoftware (AnyDesk, RustDesk...)\"\n    Write-Host \"     8  Fernwartung: Sitzungen &amp; Uebertragungen\"\n    Write-Host \"    20  Handy-/Fernsteuerung: Ports, LAN, Firewall, SRUM\"\n\n    Write-Host \"`n  [W] WEB\" -ForegroundColor Yellow\n    Write-Host \"    23  Cheat-Seiten im Browserverlauf, Download-Herkunft, DNS\"\n\n    Write-Host \"`n  [T] WERKZEUGE\" -ForegroundColor Yellow\n    Write-Host \"    18  Forensische Tools herunterladen\"\n\n    Write-Host \"`n  ----------------------------------------------\" -ForegroundColor DarkGray\n    Write-Host \"  H / L / B / R / W = ganze Kategorie ausfuehren\" -ForegroundColor DarkGray\n    Write-Host \"  A               = Alles (ohne 12, 16, 18, 19)\" -ForegroundColor DarkGray\n    Write-Host \"  P               = Protokoll starten/stoppen\" -ForegroundColor DarkGray\n    Write-Host \"  Q               = Beenden\" -ForegroundColor DarkGray\n    Write-Host \"  ============================================\" -ForegroundColor Cyan\n}\n\n# ------------------------------------------------------------\nif (-not (Test-Admin)) {\n    Write-Host \"WARNUNG: Nicht als Administrator gestartet.\" -ForegroundColor Red\n    Write-Host \"Das Kernel-PnP-Log ist so nicht lesbar.\" -ForegroundColor Red\n    Write-Host \"\"\n}\n\n$protokoll = $false\n\ndo {\n    Show-Menu\n    $wahl = (Read-Host \"Auswahl\").Trim().ToUpper()\n\n    switch ($wahl) {\n        '1' { Invoke-PnpEvents }\n        '2' { Invoke-LogIntegrity }\n        '3' { Invoke-PciDevices }\n        '4' {\n              $h = Read-Host \"Zeitfenster in Stunden (Enter = 1)\"\n              if ([string]::IsNullOrWhiteSpace($h)) { $h = 1 }\n              Invoke-RemovedDevices -Stunden ([int]$h)\n            }\n        '5' { Invoke-DiskHistory }\n        '6' { Invoke-UsbHistory }\n        '7' { Invoke-RemoteTools }\n        '8' { Invoke-RemoteSessions }\n        '9' { Invoke-Unsigned }\n        '10' { Invoke-PSHistory }\n        '12' { Invoke-PEInspector }\n        '13' { Invoke-DLLHijackCheck }\n        '14' { Invoke-SystemProcessCheck }\n        '15' { Invoke-HVCICheck }\n        '16' { Invoke-System32Check }\n        '17' { Invoke-FuserCheck }\n        '18' { Invoke-ToolDownload }\n        '19' { Invoke-SessionTimeline }\n        '20' { Invoke-RemoteControlCheck }\n        '21' { Invoke-InjectionCheck }\n        '22' { Invoke-DllHistory }\n        '23' { Invoke-WebCheck }\n        'W'  {\n              Write-Host \"`n&gt;&gt;&gt; KATEGORIE: WEB &lt;&lt;&lt;\" -ForegroundColor Yellow\n              Invoke-WebCheck\n            }\n        'H' {\n              Write-Host \"`n&gt;&gt;&gt; KATEGORIE: HARDWARE &amp; DMA &lt;&lt;&lt;\" -ForegroundColor Yellow\n              Invoke-PciDevices\n              Invoke-RemovedDevices -Stunden 24\n              Invoke-UsbHistory\n              Invoke-HVCICheck\n              Invoke-FuserCheck\n            }\n        'L' {\n              Write-Host \"`n&gt;&gt;&gt; KATEGORIE: LOGS &amp; SPUREN &lt;&lt;&lt;\" -ForegroundColor Yellow\n              Invoke-LogIntegrity\n              Invoke-PnpEvents\n              Invoke-DiskHistory\n              Invoke-PSHistory\n            }\n        'B' {\n              Write-Host \"`n&gt;&gt;&gt; KATEGORIE: BYPASS &amp; INJECTION &lt;&lt;&lt;\" -ForegroundColor Yellow\n              Invoke-Unsigned\n              Invoke-DLLHijackCheck\n              Invoke-SystemProcessCheck\n              Invoke-InjectionCheck -OhneFrage\n              Invoke-DllHistory\n              Write-Host \"`n[12 und 16 sind Einzelchecks - manuell starten]\" -ForegroundColor DarkGray\n            }\n        'R' {\n              Write-Host \"`n&gt;&gt;&gt; KATEGORIE: REMOTE &amp; IDENTITAET &lt;&lt;&lt;\" -ForegroundColor Yellow\n              Invoke-RemoteTools\n              Invoke-RemoteSessions\n              Invoke-RemoteControlCheck -OhneFrage\n            }\n        'A' {\n              Invoke-LogIntegrity\n              Invoke-PnpEvents\n              Invoke-PciDevices\n              Invoke-RemovedDevices -Stunden 24\n              Invoke-DiskHistory\n              Invoke-UsbHistory\n              Invoke-RemoteTools\n              Invoke-RemoteSessions\n              Invoke-Unsigned\n              Invoke-PSHistory\n              Invoke-DLLHijackCheck\n              Invoke-SystemProcessCheck\n              Invoke-HVCICheck\n              Invoke-FuserCheck\n              Invoke-RemoteControlCheck -OhneFrage\n              Invoke-InjectionCheck -OhneFrage\n              Invoke-DllHistory\n              Invoke-WebCheck\n              Write-Host \"`n[Uebersprungen: 12, 16, 18, 19 - Einzeldatei, Laufzeit bzw. Eingaben noetig - manuell starten]\" -ForegroundColor DarkGray\n            }\n        'P' {\n              if ($protokoll) {\n                  try { Stop-Transcript | Out-Null } catch {}\n                  $protokoll = $false\n                  Write-Host \"Protokoll gestoppt.\" -ForegroundColor Yellow\n              } else {\n                  $pfad = \"$env:USERPROFILE\\Desktop\\ctc_by_dark_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt\"\n                  try {\n                      Start-Transcript -Path $pfad | Out-Null\n                      $protokoll = $true\n                      Write-Host \"Protokoll laeuft: $pfad\" -ForegroundColor Green\n                  } catch {\n                      Write-Host \"Protokoll konnte nicht gestartet werden.\" -ForegroundColor Red\n                  }\n              }\n            }\n        'Q' { }\n        default { Write-Host \"Ungueltige Eingabe.\" -ForegroundColor Yellow }\n    }\n\n    if ($wahl -ne 'Q') {\n        Write-Host \"\"\n        Read-Host \"Enter fuer Menue\"\n        Clear-Host\n    }\n\n} while ($wahl -ne 'Q')\n\nif ($protokoll) { try { Stop-Transcript | Out-Null } catch {} }\nWrite-Host \"Beendet.\" -ForegroundColor Cyan", "url": "https://gist.github.com/analystdark/f70b483d398735a0a7a1e380bbf01e87"}]}
