initial commit
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
# Antivirus false positives — what is actually happening and what to do about it
|
||||
|
||||
LiveWall is flagged by a handful of engines out of seventy. This page explains why, what has already
|
||||
been done about it, in what order to fix the rest, and what to tell users in the meantime.
|
||||
|
||||
Last reviewed: 2026-11-04, for `LiveWall-Setup-1.8.0.exe`.
|
||||
|
||||
---
|
||||
|
||||
## 1. What the scan actually said
|
||||
|
||||
VirusTotal, first submission 2026-11-04, **3 of 71 engines**:
|
||||
|
||||
| Engine | Verdict | What that engine is telling you |
|
||||
|---|---|---|
|
||||
| SecureAge (APEX) | `Malicious` | Reputation/heuristic verdict; APEX is well known for flagging new, unsigned, low-prevalence files. |
|
||||
| Trapmine | `Malicious.high.ml.score` | A pure machine-learning score. No signature, no analyst: "this file shape looks like things we have seen". |
|
||||
| VBA32 | `TScope.Malware-Cryptor.SB` | "SB" = **solid block**. VBA32 scores the NSIS solid archive as a crypter. |
|
||||
|
||||
Undetected: **Microsoft Defender, Kaspersky, BitDefender, ESET, Avast/AVG, Malwarebytes, Sophos,
|
||||
Symantec, Trend Micro, McAfee, GData, Ikarus, ClamAV, DrWeb, CrowdStrike, SentinelOne, Palo Alto,
|
||||
Fortinet, Webroot**, and 50 more.
|
||||
|
||||
Facts from the report that explain the three verdicts:
|
||||
|
||||
* **File is not signed.** No Authenticode signature, no publisher.
|
||||
* **First submission = last submission.** Prevalence zero. Reputation engines have nothing to go on,
|
||||
so they fall back to heuristics — and the fallback is "guilty until seen a lot".
|
||||
* **DetectItEasy: `Installer: Nullsoft Scriptable Install System (3.11-1) [zlib,solid]`.** NSIS is the
|
||||
single most abused installer format in the world, and `/SOLID` hides each file's structure behind
|
||||
one compressed stream. That is exactly what the VBA32 and Trapmine scores are reacting to.
|
||||
* Nothing else: no packer (UPX), entropy of `.text` is 6.09 (normal), imports are ordinary, the file
|
||||
has proper version info (Product, Description, File Version, Copyright).
|
||||
|
||||
**This is not a detection of behaviour in the app.** The three engines never ran it — these are static
|
||||
or reputation verdicts on an unsigned installer stub.
|
||||
|
||||
---
|
||||
|
||||
## 2. Why a wallpaper app trips heuristics at all
|
||||
|
||||
Beyond "unsigned + unknown", the app's own behaviour looks like the shape of a threat to a scanner:
|
||||
|
||||
| The app does | Scanners see |
|
||||
|---|---|
|
||||
| Finds `WorkerW`, re-parents a hidden window into the shell desktop | "hides a window inside Explorer" |
|
||||
| Registers global hotkeys | "installs system-wide input handling" |
|
||||
| Optionally starts with Windows (HKCU `Run`) | "persistence" — **off by default** in LiveWall |
|
||||
| Loads .NET assemblies from `%APPDATA%\LiveWall\plugins` | "executes code from a user-writable directory" — **off by default**, needs two explicit consents, hash-pinned |
|
||||
| Ships WebView2 and plays YouTube | "network access" |
|
||||
|
||||
None of that is malicious, and none of it is unique to LiveWall — every live-wallpaper app does the
|
||||
first two. But it means the app will be *judged on reputation*, not on inspection. That is why the
|
||||
answer is not "make the code cleaner", it is "get a signature and get seen".
|
||||
|
||||
Things that were already right (keep them that way): no bundled offers, no telemetry, no admin rights
|
||||
(`RequestExecutionLevel user`), per-user install, real version metadata on both the installer and the
|
||||
binaries, uninstaller registered, no obfuscation, no UPX.
|
||||
|
||||
---
|
||||
|
||||
## 3. Fixes, in order of how much they actually help
|
||||
|
||||
### 3.1 Sign everything with Authenticode (the only real fix)
|
||||
|
||||
An unsigned download is *the* variable here. It is also what every vendor replies with when you file a
|
||||
false-positive report ("please sign your binaries").
|
||||
|
||||
* **EV code-signing certificate** (~$300–500/year, hardware token/HSM): SmartScreen and Defender
|
||||
reputation trust it immediately, and heuristics weight signed files far higher.
|
||||
* **OV code-signing certificate** (~$100–300/year): works, but reputation accumulates over weeks of
|
||||
downloads. Expect fewer and fewer flags as it builds.
|
||||
* **Self-signed certificate: do not bother.** An untrusted signature is worth no more than no
|
||||
signature, and sometimes less.
|
||||
* Sign **both** the published binaries and the installer, and let NSIS sign the uninstaller it
|
||||
generates (`installer/sign.ps1` and the `SIGNTOOL` hook in `LiveWall.nsi` do all of this). Always
|
||||
timestamp (RFC 3161) so signatures survive certificate expiry.
|
||||
|
||||
```powershell
|
||||
# after signing, every file reports a publisher instead of "Unknown publisher"
|
||||
.\installer\sign.ps1 -Thumbprint <sha1-of-cert> # or -Pfx .\codesign.pfx
|
||||
```
|
||||
|
||||
### 3.2 Report the false positive — every one of the three
|
||||
|
||||
Vendors fix these in days when you tell them. Submit the file (or its hash), say what it is, and ask
|
||||
for a reclassification. Use the "Contact vendor" link on the VirusTotal page for each detection, and:
|
||||
|
||||
| Vendor | Where |
|
||||
|---|---|
|
||||
| **Microsoft** (even though it currently passes — keeps Defender's cloud verdict clean) | <https://www.microsoft.com/en-us/wdsi/filesubmission> → *Software developer* → "I believe this file is incorrectly detected" |
|
||||
| **SecureAge** | support@secureage.com, or the contact form on secureage.com — attach the VT link |
|
||||
| **Trapmine** | Trapmine support (contact form / support@trapmine.com) — quote the exact ML verdict |
|
||||
| **VBA32** | virus@vba32.com (their sample/FP mailbox) |
|
||||
|
||||
Text that works — it gives the analyst everything they need in one screen:
|
||||
|
||||
> Subject: False positive — LiveWall 1.8.0 installer (NSIS), unsigned open-source wallpaper app
|
||||
>
|
||||
> Hello,
|
||||
>
|
||||
> Your engine reports `<verdict>` for SHA-256
|
||||
> `7242a2a3fd6fc142279aecf2ea83f02501af4df3fdd1ecfe7c481bf6aa7a1764`
|
||||
> (`LiveWall-Setup-1.8.0.exe`, VirusTotal: <link>).
|
||||
>
|
||||
> LiveWall is a free live-wallpaper app for Windows 11 (GIF/video/YouTube on the desktop). The file is
|
||||
> an NSIS 3.11 installer built by our own script from our own source; it installs per-user into
|
||||
> `%LOCALAPPDATA%\Programs\LiveWall`, needs no admin rights, contains no bundled offers, no telemetry,
|
||||
> no obfuscation and no downloader. It is currently unsigned while certification is in progress.
|
||||
>
|
||||
> The detection looks like a heuristic on the NSIS solid archive rather than on behaviour. Please
|
||||
> reclassify. I can provide the source, the build script, signed builds, or any further sample you
|
||||
> need.
|
||||
>
|
||||
> Thank you.
|
||||
|
||||
Also worth doing once: create a **VirusTotal account** and use *Reanalyze* after reporting, and keep the
|
||||
VT link in the release notes so users see the same picture you do.
|
||||
|
||||
### 3.3 Change the container, not the app
|
||||
|
||||
Two variants are built from the same source specifically for this:
|
||||
|
||||
| Build | Command | Why |
|
||||
|---|---|---|
|
||||
| `LiveWall-Setup-1.8.0.exe` | `bash installer/build-installer.sh` | solid LZMA, smallest (709 KB) |
|
||||
| `LiveWall-Setup-1.8.0-lzma.exe` | `COMPRESS=lzma OUT_SUFFIX=-lzma bash installer/build-installer.sh` | no solid block, one stream per file (809 KB) |
|
||||
| `LiveWall-Setup-1.8.0-zlib.exe` | `COMPRESS=zlib OUT_SUFFIX=-zlib bash installer/build-installer.sh` | no solid block, no LZMA at all (972 KB) |
|
||||
| `LiveWall-1.8.0-portable.zip` | `.\build.ps1 -Task portable` | **no executable container at all** — a plain zip of the app |
|
||||
|
||||
Upload the variants to VirusTotal and keep the one that scores cleanest. The zlib build is the one to
|
||||
try first if VBA32/Trapmine are the only remaining flags: "solid" and "lzma" are exactly what those two
|
||||
score. The ZIP walks around the whole class of problems — nothing to unpack, nothing to score as a
|
||||
self-extracting stub — and is a perfectly good distribution format for a 2.7 MB app that needs the
|
||||
.NET 8 Desktop Runtime anyway.
|
||||
|
||||
Longer term, a **signed MSI (WiX)** or **MSIX** is the most "boring" container Windows offers, at the
|
||||
cost of more build work. Not worth it before signing.
|
||||
|
||||
### 3.4 Build reputation
|
||||
|
||||
* Publish from **one identity, consistently**: same certificate, same publisher name in the version
|
||||
resources (`Company`, `LegalCopyright`, `OriginalFilename`), same download host.
|
||||
* Get real download volume — GitHub Releases, winget (`winget-pkgs`), Chocolatey, PortableApps,
|
||||
Scoop. High prevalence is itself an allow-list for every ML engine.
|
||||
* Keep the source public and linked from the download page. Analysts and users both use it.
|
||||
* Don't re-release new hashes constantly: every build resets file reputation. Batch fixes.
|
||||
|
||||
### 3.5 Keep the plugin system's shape defensible
|
||||
|
||||
The plugin system is the most "malware-shaped" feature in the app (loading arbitrary .NET assemblies
|
||||
from `%APPDATA%`). It is already as gated as a design can be, and it is worth saying so in any
|
||||
submission or user-facing explanation:
|
||||
|
||||
* the system is **off by default** (`Plugins.Enabled = false`);
|
||||
* enabling it shows a mandatory third-party-code warning that must be acknowledged;
|
||||
* each plugin is hashed (SHA-256) and shows its hash, publisher and permissions in its own warning
|
||||
before a single line of it runs;
|
||||
* the approved hash is pinned — a changed DLL is unverified again and stops loading;
|
||||
* nothing is ever downloaded or executed automatically, and there is no network component in the loader.
|
||||
|
||||
---
|
||||
|
||||
## 4. What to tell users right now
|
||||
|
||||
Wording that is honest and de-escalates:
|
||||
|
||||
> **Heads-up about antivirus warnings.** `LiveWall-Setup-1.8.0.exe` is currently flagged by 3 of 71
|
||||
> engines on VirusTotal (SecureAge, Trapmine, VBA32) and is clean on the other 68, including Microsoft
|
||||
> Defender, Kaspersky, BitDefender, ESET and Malwarebytes. The three are reputation/ML verdicts on an
|
||||
> installer that is not yet code-signed — not behaviour detections. The installer is built from the
|
||||
> source in this repository, installs per-user without admin rights, and contains no telemetry, no
|
||||
> bundled offers and no downloader.
|
||||
>
|
||||
> * Check it yourself: VirusTotal link, SHA-256 `…` (matches the file you downloaded).
|
||||
> * Vendor reports filed on 2026-11-04; these verdicts typically clear within a few days.
|
||||
> * Prefer no installer at all? Use the portable ZIP: unpack it and run `LiveWall.exe`.
|
||||
> * If your AV quarantines it anyway: send me the engine name and the detection name, and add an
|
||||
> exclusion only if you are comfortable doing so.
|
||||
|
||||
Two rules for that message: never tell users to "just disable your antivirus", and always give them a
|
||||
hash they can verify.
|
||||
|
||||
---
|
||||
|
||||
## 5. Checklist per release
|
||||
|
||||
- [ ] `.\build.ps1 -Task publish`
|
||||
- [ ] `bash installer/build-installer.sh` (and optionally the `-zlib` variant)
|
||||
- [ ] `.\installer\sign.ps1 -Thumbprint <cert>` — verify every file has a publisher
|
||||
- [ ] Upload the installer + `LiveWall.exe` to VirusTotal, check the score
|
||||
- [ ] Publish the SHA-256 of every downloadable file in the release notes
|
||||
- [ ] `.\build.ps1 -Task portable` as the fallback download
|
||||
- [ ] If a new engine flags it: report with the template above, then *Reanalyze* a day later
|
||||
- [ ] Keep a note of who flagged which version, so you can tell whether a change helped
|
||||
|
||||
## 6. Tracking
|
||||
|
||||
| Version | File | Result | Notes |
|
||||
|---|---|---|---|
|
||||
| 1.8.0 | `3d472fa6…3deba` | 3/71 — SecureAge, Trapmine (ML), VBA32 (TScope.Malware-Cryptor.SB) | unsigned, solid LZMA, first seen today |
|
||||
| 1.8.0 (rebuild) | `7242a2a3…a1764` | to be measured | version-info improvements; same container |
|
||||
| 1.8.0 (zlib) | `78cde58c…fc4b` | to be measured | no solid block — expected to clear VBA32/Trapmine |
|
||||
| 1.8.2 | `843425a9…f321c` | to be measured | input-shield + cursor fixes; same container as 1.8.0 (unsigned, solid LZMA) |
|
||||
| 1.8.2 (zlib) | `cb175d79…023a9` | to be measured | non-solid variant |
|
||||
| 1.8.2 portable ZIP | `016c5793…7652e` | to be measured | no installer stub at all |
|
||||
| 1.8.3 | `ce642909…a5d06` | to be measured | redesigned installer (same NSIS container, same compressor) |
|
||||
| 1.8.4 | `d2de043f…906e4` | to be measured | side-menu layout fix; same container |
|
||||
|
||||
Also worth uploading to VirusTotal, because engines inspect them once the installer has run:
|
||||
`prebuilt\LiveWall.exe` (SHA-256 `7ecaa8e2ada4833ce4b84388f17da0b5605e87cb4c3348577b23e26476c953cc` before the
|
||||
last rebuild) and `LiveWall.Sdk.dll`. If those come back clean while the installer does not, that alone
|
||||
proves the verdict is about the NSIS container.
|
||||
|
||||
Portable fallback for this build: `LiveWall-1.8.0-portable.zip`,
|
||||
SHA-256 `83ce64aed61232afd6e5a39d55bf8856b4630d958de37cdc42386b92f43ab506`.
|
||||
Reference in New Issue
Block a user