16 Commits

Author SHA1 Message Date
Arsenii es3n1n
f57189d1b7 Merge pull request #20 from es3n1n/bump-1-2-0
build: bump version to v1.2.0
2025-05-20 15:36:09 +09:00
es3n1n
dfaae57077 build: bump version 2025-05-20 15:35:36 +09:00
Arsenii es3n1n
62c2f33d04 Merge pull request #19 from es3n1n/powershell-fix-newline
refactor(installer): change install loc to program files
2025-05-20 15:33:59 +09:00
es3n1n
7fc202497e refactor(installer): change install loc to program files 2025-05-20 15:33:08 +09:00
Arsenii es3n1n
a2d0f0c84d Merge pull request #18 from es3n1n/powershell-oneliner
feat(installer): add powershell installer
2025-05-20 15:23:08 +09:00
es3n1n
c159dbe324 refactor: minor cleanup 2025-05-20 15:16:32 +09:00
es3n1n
448b1ced98 docs(readme): update installer script url 2025-05-20 15:01:04 +09:00
es3n1n
897ed9c0eb docs(readme): update advanced usage notes 2025-05-20 12:09:56 +09:00
es3n1n
bf9d21b626 docs(readme): make advanced usage examples shorter 2025-05-20 12:08:01 +09:00
es3n1n
3d969605fd docs(readme): update advanced installer usage 2025-05-20 12:07:19 +09:00
es3n1n
3bfc312587 refactor(installer): minor installer cleanup 2025-05-20 12:01:22 +09:00
es3n1n
a11a1fe7b6 feat(installer): add powershell installer 2025-05-20 11:58:22 +09:00
Arsenii es3n1n
cc2b52b86a Merge pull request #16 from es3n1n/ci-release
ci: add auto release in workflow_dispatch
2025-05-19 22:06:16 +09:00
es3n1n
3bb18ef533 ci: add auto release in workflow_dispatch 2025-05-19 22:03:24 +09:00
Arsenii es3n1n
18aff7944e Merge pull request #15 from es3n1n/add-silent-arg
feat(loader): add --silent
2025-05-19 22:01:54 +09:00
es3n1n
53144b6b12 feat(loader): add --silent 2025-05-19 21:01:04 +09:00
6 changed files with 152 additions and 18 deletions

View File

@@ -1,8 +1,15 @@
name: Build Solution
name: Build/Release
on:
push:
workflow_dispatch:
inputs:
tag:
description: 'Tag for the release'
required: true
permissions:
contents: write
jobs:
build:
@@ -57,6 +64,43 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: binaries-${{ matrix.platform }}
name: ${{ matrix.platform }}
path: artifacts/${{ matrix.platform }}
retention-days: 7
create-release:
needs: build
if: github.event_name == 'workflow_dispatch' && github.event.inputs.tag != ''
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: release-artifacts
- name: Zip Artifacts
run: |
mkdir -p zipped-artifacts
cd release-artifacts
for platform in */; do
platform_name=${platform%/}
echo "Zipping $platform_name"
(cd "$platform_name" && zip -r "../../zipped-artifacts/$platform_name.zip" .)
done
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ github.event.inputs.tag }}
name: ${{ github.event.inputs.tag }}
draft: false
prerelease: false
files: zipped-artifacts/*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -6,6 +6,49 @@ Defendnot is a successor of [no-defender](https://github.com/es3n1n/no-defender)
![](https://i.imgur.com/VGE8g6a.jpeg)
## Installation
### One-liner
Open the powershell as administrator and execute any of these:
```powershell
# Example 1: Basic installation
irm https://dnot.sh/ | iex
# Example 2: With custom AV name
& ([ScriptBlock]::Create((irm https://dnot.sh/))) --name "Custom AV name"
# Example 3: Without allocating console
& ([ScriptBlock]::Create((irm https://dnot.sh/))) --silent
```
> [!NOTE]
> As seen in examples 2 and 3, you can pass the commandline arguments to the installer script and it will forward them to `defendnot-loader`. For reference what commandline arguments are allowed, see the `Usage` section below.
> [!NOTE]
> You can also directly use the 'longer' version of installer script url, which is `https://raw.githubusercontent.com/es3n1n/defendnot/refs/heads/master/install.ps1`
### Manual
Download the [latest](https://github.com/es3n1n/defendnot/releases/latest) release, extract it somewhere and launch `defendnot-loader`.
## Usage
```commandline
Usage: defendnot-loader [--help] [--version] [--name VAR] [--disable] [--verbose] [--silent] [--autorun-as-user] [--disable-autorun]
Optional arguments:
-h, --help prints help message and exits
--version shows version and exits
-n, --name av display name [default: "https://github.com/es3n1n/defendnot"]
-d, --disable disable defendnot
-v, --verbose verbose logging
--silent do not allocate console
--autorun-as-user create autorun task as currently logged in user
--disable-autorun disable autorun task creation
```
## How it works
There's a WSC (Windows Security Center) service in Windows which is used by antiviruses to let Windows know that there's some other antivirus in the hood and it should disable Windows Defender.
@@ -17,19 +60,6 @@ The initial implementation of [no-defender](https://github.com/es3n1n/no-defende
Sadly, to keep this WSC stuff even after reboot, defendnot adds itself to the autorun. Thus, you would need to keep the defendnot binaries on your disk :(
## Usage
```commandline
Usage: defendnot-loader [--help] [--version] [--name VAR] [--disable] [--verbose]
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits
-n, --name av display name [default: "https://github.com/es3n1n/defendnot"]
-d, --disable disable defendnot
-v, --verbose verbose logging
```
## Writeup
[How I ruined my vacation by reverse engineering WSC](https://blog.es3n1n.eu/posts/how-i-ruined-my-vacation/)

View File

@@ -8,5 +8,5 @@ namespace names {
constexpr std::string_view kVictimProcess = "Taskmgr.exe";
constexpr std::string_view kDllName = "defendnot.dll";
constexpr std::string_view kVersion = "1.1.0";
constexpr std::string_view kVersion = "1.2.0";
} // namespace names

View File

@@ -14,6 +14,7 @@ namespace loader {
public:
std::string name;
bool disable;
bool alloc_console;
bool verbose;
bool from_autorun;
AutorunType autorun_type;

View File

@@ -11,7 +11,7 @@
namespace {
void setup_window(const loader::Config& config) {
if (!config.from_autorun || config.verbose) {
if ((!config.from_autorun || config.verbose) && config.alloc_console) {
shared::alloc_console();
}
}
@@ -68,7 +68,7 @@ namespace {
std::println("thanks for using {}", names::kProjectName);
std::println("please don't forget to leave a star at {}", names::kRepoUrl);
if (!config.from_autorun) {
if (!config.from_autorun && config.alloc_console) {
system("pause");
}
}
@@ -100,6 +100,7 @@ int main(int argc, char* argv[]) try {
program.add_argument("-n", "--name").help("av display name").default_value(std::string(names::kRepoUrl)).nargs(1);
program.add_argument("-d", "--disable").help(std::format("disable {}", names::kProjectName)).default_value(false).implicit_value(true);
program.add_argument("-v", "--verbose").help("verbose logging").default_value(false).implicit_value(true);
program.add_argument("--silent").help("do not allocate console").default_value(false).implicit_value(true);
program.add_argument("--autorun-as-user").help("create autorun task as currently logged in user").default_value(false).implicit_value(true);
program.add_argument("--disable-autorun").help("disable autorun task creation").default_value(false).implicit_value(true);
program.add_argument("--from-autorun").hidden().default_value(false).implicit_value(true);
@@ -117,6 +118,7 @@ int main(int argc, char* argv[]) try {
auto config = loader::Config{
.name = program.get<std::string>("-n"),
.disable = program.get<bool>("-d"),
.alloc_console = !program.get<bool>("--silent"),
.verbose = program.get<bool>("-v"),
.from_autorun = program.get<bool>("--from-autorun"),
.autorun_type = program.get<bool>("--autorun-as-user") ? /// As system on boot is the default value
@@ -125,6 +127,10 @@ int main(int argc, char* argv[]) try {
.enable_autorun = !program.get<bool>("--disable-autorun"),
};
if (!config.alloc_console && config.verbose) {
fatal_print("--silent flag can not be used in combination with --verbose");
}
setup_window(config);
setup_context(config);

53
install.ps1 Normal file
View File

@@ -0,0 +1,53 @@
#Requires -RunAsAdministrator
$ErrorActionPreference = "Stop"
$InstallPath = "$env:ProgramFiles\defendnot"
switch -Wildcard ($env:PROCESSOR_ARCHITECTURE) {
"AMD64" { $arch = "x64" }
"x86" { $arch = "x86" }
"ARM64" { $arch = "ARM64" }
default {
Write-Error "Unknown architecture: $($env:PROCESSOR_ARCHITECTURE)"
exit 1
}
}
$repo = "es3n1n/defendnot"
$apiReleaseUrl = "https://api.github.com/repos/$repo/releases/latest"
$headers = @{ 'User-Agent'="defendnot-install/1.0" }
try {
$release = Invoke-RestMethod -Uri $apiReleaseUrl -Headers $headers
} catch {
Write-Error "Failed to get latest release info: $_"
exit 2
}
$zipAsset = $release.assets | Where-Object { $_.name -ieq "$arch.zip" }
if (-not $zipAsset) {
Write-Error "Release does not contain asset for $arch"
exit 3
}
$zipUrl = $zipAsset.browser_download_url
$zipPath = Join-Path $env:TEMP "defendnot-$arch.zip"
Write-Host "Downloading $($zipAsset.name)..."
Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath
if (Test-Path $InstallPath) {
Write-Host "Removing previous installation..."
Remove-Item $InstallPath -Force -Recurse -ErrorAction SilentlyContinue
}
New-Item -Type Directory -Path $InstallPath -ErrorAction SilentlyContinue | Out-Null
Write-Host "Extracting to $InstallPath..."
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipPath, $InstallPath)
Remove-Item $zipPath
Write-Host "Installed to $InstallPath"
Write-Host "Starting..."
Write-Host "Args: $args"
& "$InstallPath\defendnot-loader.exe" @args