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: on:
push: push:
workflow_dispatch: workflow_dispatch:
inputs:
tag:
description: 'Tag for the release'
required: true
permissions:
contents: write
jobs: jobs:
build: build:
@@ -57,6 +64,43 @@ jobs:
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: binaries-${{ matrix.platform }} name: ${{ matrix.platform }}
path: artifacts/${{ matrix.platform }} path: artifacts/${{ matrix.platform }}
retention-days: 7 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) ![](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 ## 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. 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 :( 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 ## Writeup
[How I ruined my vacation by reverse engineering WSC](https://blog.es3n1n.eu/posts/how-i-ruined-my-vacation/) [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 kVictimProcess = "Taskmgr.exe";
constexpr std::string_view kDllName = "defendnot.dll"; 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 } // namespace names

View File

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

View File

@@ -11,7 +11,7 @@
namespace { namespace {
void setup_window(const loader::Config& config) { 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(); shared::alloc_console();
} }
} }
@@ -68,7 +68,7 @@ namespace {
std::println("thanks for using {}", names::kProjectName); std::println("thanks for using {}", names::kProjectName);
std::println("please don't forget to leave a star at {}", names::kRepoUrl); 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"); 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("-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("-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("-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("--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("--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); 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{ auto config = loader::Config{
.name = program.get<std::string>("-n"), .name = program.get<std::string>("-n"),
.disable = program.get<bool>("-d"), .disable = program.get<bool>("-d"),
.alloc_console = !program.get<bool>("--silent"),
.verbose = program.get<bool>("-v"), .verbose = program.get<bool>("-v"),
.from_autorun = program.get<bool>("--from-autorun"), .from_autorun = program.get<bool>("--from-autorun"),
.autorun_type = program.get<bool>("--autorun-as-user") ? /// As system on boot is the default value .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"), .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_window(config);
setup_context(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