mirror of
https://github.com/es3n1n/defendnot.git
synced 2026-10-01 10:01:36 +00:00
feat: add --firewall (#57)
This commit is contained in:
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -13,7 +13,7 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: windows-latest
|
runs-on: windows-2022
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
platform: [x64, x86, ARM64]
|
platform: [x64, x86, ARM64]
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Download the [latest](https://github.com/es3n1n/defendnot/releases/latest) relea
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```commandline
|
```commandline
|
||||||
Usage: defendnot-loader [--help] [--version] [--name VAR] [--disable] [--verbose] [--silent] [--autorun-as-user] [--disable-autorun]
|
Usage: defendnot-loader [--help] [--version] [--name VAR] [--disable] [--verbose] [--firewall] [--silent] [--autorun-as-user] [--disable-autorun]
|
||||||
|
|
||||||
Optional arguments:
|
Optional arguments:
|
||||||
-h, --help prints help message and exits
|
-h, --help prints help message and exits
|
||||||
@@ -51,6 +51,7 @@ Optional arguments:
|
|||||||
-n, --name av display name [default: "dnot.sh"]
|
-n, --name av display name [default: "dnot.sh"]
|
||||||
-d, --disable disable defendnot
|
-d, --disable disable defendnot
|
||||||
-v, --verbose verbose logging
|
-v, --verbose verbose logging
|
||||||
|
--firewall also register a fake firewall
|
||||||
--silent do not allocate console
|
--silent do not allocate console
|
||||||
--autorun-as-user create autorun task as currently logged in user
|
--autorun-as-user create autorun task as currently logged in user
|
||||||
--disable-autorun disable autorun task creation
|
--disable-autorun disable autorun task creation
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "shared/util.hpp"
|
#include "shared/util.hpp"
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
namespace shared {
|
namespace shared {
|
||||||
constexpr std::size_t kMaxNameLength = 128;
|
constexpr std::size_t kMaxNameLength = 128;
|
||||||
constexpr std::string_view kCtxPath = "ctx.bin";
|
constexpr std::string_view kCtxPath = "ctx.bin";
|
||||||
@@ -28,6 +29,7 @@ namespace shared {
|
|||||||
State state = State::ON;
|
State state = State::ON;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
std::array<char, kMaxNameLength + 1> name = {0}; // +1 for the nullterm
|
std::array<char, kMaxNameLength + 1> name = {0}; // +1 for the nullterm
|
||||||
|
bool register_firewall = false;
|
||||||
|
|
||||||
void serialize() const {
|
void serialize() const {
|
||||||
std::ofstream stream(detail::ctx_path(), std::ios::binary);
|
std::ofstream stream(detail::ctx_path(), std::ios::binary);
|
||||||
@@ -50,3 +52,4 @@ namespace shared {
|
|||||||
|
|
||||||
static_assert(std::is_trivially_copyable_v<Context>);
|
static_assert(std::is_trivially_copyable_v<Context>);
|
||||||
} // namespace shared
|
} // namespace shared
|
||||||
|
#pragma pack(pop)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "shared/ctx.hpp"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
namespace loader {
|
namespace loader {
|
||||||
@@ -16,9 +18,17 @@ namespace loader {
|
|||||||
bool disable;
|
bool disable;
|
||||||
bool alloc_console;
|
bool alloc_console;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
|
bool register_firewall;
|
||||||
bool from_autorun;
|
bool from_autorun;
|
||||||
AutorunType autorun_type;
|
AutorunType autorun_type;
|
||||||
bool enable_autorun;
|
bool enable_autorun;
|
||||||
|
|
||||||
|
Config& operator=(const shared::Context& ctx) {
|
||||||
|
verbose = ctx.verbose;
|
||||||
|
register_firewall = ctx.register_firewall;
|
||||||
|
name = ctx.name.data();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] HANDLE inject(std::string_view dll_path, std::string_view proc_name);
|
[[nodiscard]] HANDLE inject(std::string_view dll_path, std::string_view proc_name);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace {
|
|||||||
|
|
||||||
shared::ctx.state = config.disable ? shared::State::OFF : shared::State::ON;
|
shared::ctx.state = config.disable ? shared::State::OFF : shared::State::ON;
|
||||||
shared::ctx.verbose = config.verbose;
|
shared::ctx.verbose = config.verbose;
|
||||||
|
shared::ctx.register_firewall = config.register_firewall;
|
||||||
std::ranges::copy(config.name, shared::ctx.name.data());
|
std::ranges::copy(config.name, shared::ctx.name.data());
|
||||||
|
|
||||||
/// No need to overwrite ctx if we are called from autorun
|
/// No need to overwrite ctx if we are called from autorun
|
||||||
@@ -100,6 +101,7 @@ int main(int argc, char* argv[]) try {
|
|||||||
program.add_argument("-n", "--name").help("av display name").default_value(std::string(strings::kDefaultAVName)).nargs(1);
|
program.add_argument("-n", "--name").help("av display name").default_value(std::string(strings::kDefaultAVName)).nargs(1);
|
||||||
program.add_argument("-d", "--disable").help(std::format("disable {}", strings::kProjectName)).default_value(false).implicit_value(true);
|
program.add_argument("-d", "--disable").help(std::format("disable {}", strings::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("--firewall").help("also register a fake firewall").default_value(false).implicit_value(true);
|
||||||
program.add_argument("--silent").help("do not allocate console").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);
|
||||||
@@ -120,6 +122,7 @@ int main(int argc, char* argv[]) try {
|
|||||||
.disable = program.get<bool>("-d"),
|
.disable = program.get<bool>("-d"),
|
||||||
.alloc_console = !program.get<bool>("--silent"),
|
.alloc_console = !program.get<bool>("--silent"),
|
||||||
.verbose = program.get<bool>("-v"),
|
.verbose = program.get<bool>("-v"),
|
||||||
|
.register_firewall = program.get<bool>("--firewall"),
|
||||||
.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
|
||||||
loader::AutorunType::AS_CURRENT_USER_ON_LOGIN :
|
loader::AutorunType::AS_CURRENT_USER_ON_LOGIN :
|
||||||
@@ -130,7 +133,7 @@ int main(int argc, char* argv[]) try {
|
|||||||
/// When running from autorun, we'll be missing all the cli arguments, so lets load some relevant ones
|
/// When running from autorun, we'll be missing all the cli arguments, so lets load some relevant ones
|
||||||
if (config.from_autorun) {
|
if (config.from_autorun) {
|
||||||
shared::ctx.deserialize();
|
shared::ctx.deserialize();
|
||||||
config.verbose = shared::ctx.verbose;
|
config = shared::ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.alloc_console && config.verbose) {
|
if (!config.alloc_console && config.verbose) {
|
||||||
|
|||||||
@@ -8,27 +8,41 @@
|
|||||||
|
|
||||||
namespace defendnot {
|
namespace defendnot {
|
||||||
namespace {
|
namespace {
|
||||||
|
void activate(const auto& step, IWscASStatus* inst) {
|
||||||
|
step("update", inst->UpdateStatus(WSCSecurityProductState::ON, TRUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate(const auto& step, IWscAVStatus4* inst) {
|
||||||
|
step("update", inst->UpdateStatus(WSCSecurityProductState::ON, TRUE));
|
||||||
|
step("scan_update", inst->UpdateScanSubstatus(WSCSecurityProductSubStatus::NO_ACTION));
|
||||||
|
step("settings_update", inst->UpdateSettingsSubstatus(WSCSecurityProductSubStatus::NO_ACTION));
|
||||||
|
step("prot_update", inst->UpdateProtectionUpdateSubstatus(WSCSecurityProductSubStatus::NO_ACTION));
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate(const auto& step, IWscFWStatus2* inst) {
|
||||||
|
step("update", inst->UpdateStatus(WSCSecurityProductState::ON));
|
||||||
|
step("domain_update", inst->UpdateDomainProfileSubstatus(WSCSecurityProductSubStatus::NO_ACTION));
|
||||||
|
step("private_update", inst->UpdatePrivateProfileSubstatus(WSCSecurityProductSubStatus::NO_ACTION));
|
||||||
|
step("public_update", inst->UpdatePublicProfileSubstatus(WSCSecurityProductSubStatus::NO_ACTION));
|
||||||
|
}
|
||||||
|
|
||||||
template <com::ComObject Ty>
|
template <com::ComObject Ty>
|
||||||
void apply(const std::string_view log_prefix, const BSTR name) {
|
void apply(const std::string_view log_prefix, const BSTR name, const bool should_register) {
|
||||||
/// Get the WSC interface
|
/// Get the WSC interface
|
||||||
auto inst = com::query<Ty>();
|
auto inst = com::query<Ty>();
|
||||||
|
|
||||||
/// This can fail if we dont have any products registered so no com_checked
|
/// This can fail if we dont have any products registered so no com::checked
|
||||||
logln("{}_unregister: {:#x}", log_prefix, com::retry_while_pending([&inst]() -> HRESULT { return inst->Unregister(); }) & 0xFFFFFFFF);
|
logln("{}_unregister: {:#x}", log_prefix, com::retry_while_pending([&inst]() -> HRESULT { return inst->Unregister(); }) & 0xFFFFFFFF);
|
||||||
if (shared::ctx.state == shared::State::OFF) {
|
if (!should_register) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register and activate
|
/// Register and activate
|
||||||
logln("{}_register: {:#x}", log_prefix, com::checked(inst->Register(name, name, 0, 0)));
|
const auto step = [&](const std::string_view what, const HRESULT hr) -> void {
|
||||||
logln("{}_update: {:#x}", log_prefix, com::checked(inst->UpdateStatus(WSCSecurityProductState::ON, static_cast<BOOL>(true))));
|
logln("{}_{}: {:#x}", log_prefix, what, com::checked(hr));
|
||||||
|
};
|
||||||
/// Update the substatuses, if the interface supports this
|
step("register", inst->Register(name, name, 0, 0));
|
||||||
if constexpr (std::is_same_v<Ty, IWscAVStatus4>) {
|
activate(step, inst.get());
|
||||||
logln("{}_scan_update: {:#x}", log_prefix, com::checked(inst->UpdateScanSubstatus(WSCSecurityProductSubStatus::NO_ACTION)));
|
|
||||||
logln("{}_settings_update: {:#x}", log_prefix, com::checked(inst->UpdateSettingsSubstatus(WSCSecurityProductSubStatus::NO_ACTION)));
|
|
||||||
logln("{}_prot_update: {:#x}", log_prefix, com::checked(inst->UpdateProtectionUpdateSubstatus(WSCSecurityProductSubStatus::NO_ACTION)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@@ -45,12 +59,14 @@ namespace defendnot {
|
|||||||
|
|
||||||
/// Convert to BSTR
|
/// Convert to BSTR
|
||||||
auto name = SysAllocString(name_w.c_str());
|
auto name = SysAllocString(name_w.c_str());
|
||||||
defer->void {
|
defer {
|
||||||
SysFreeString(name);
|
SysFreeString(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Register our stuff in the WSC interfaces
|
/// Register our stuff in the WSC interfaces
|
||||||
apply<IWscASStatus>("IWscASStatus", name);
|
const bool enabled = shared::ctx.state != shared::State::OFF;
|
||||||
apply<IWscAVStatus4>("IWscAVStatus4", name);
|
apply<IWscASStatus>("IWscASStatus", name, enabled);
|
||||||
|
apply<IWscAVStatus4>("IWscAVStatus4", name, enabled);
|
||||||
|
apply<IWscFWStatus2>("IWscFWStatus2", name, enabled && shared::ctx.register_firewall);
|
||||||
}
|
}
|
||||||
} // namespace defendnot
|
} // namespace defendnot
|
||||||
|
|||||||
@@ -69,4 +69,14 @@ namespace defendnot {
|
|||||||
virtual HRESULT COM_CALLCONV Unregister() = 0;
|
virtual HRESULT COM_CALLCONV Unregister() = 0;
|
||||||
virtual HRESULT COM_CALLCONV UpdateStatus(WSCSecurityProductState state, BOOL unk) = 0;
|
virtual HRESULT COM_CALLCONV UpdateStatus(WSCSecurityProductState state, BOOL unk) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IWscFWStatus2 : public com::IBaseObject<detail::CLSID_WscIsv, detail::IID_IWscFWStatus2> {
|
||||||
|
public:
|
||||||
|
virtual HRESULT COM_CALLCONV Register(BSTR path_to_signed_product_exe, BSTR display_name, std::uint32_t, std::uint32_t) = 0;
|
||||||
|
virtual HRESULT COM_CALLCONV Unregister() = 0;
|
||||||
|
virtual HRESULT COM_CALLCONV UpdateStatus(WSCSecurityProductState state) = 0;
|
||||||
|
virtual HRESULT COM_CALLCONV UpdateDomainProfileSubstatus(WSCSecurityProductSubStatus status) = 0;
|
||||||
|
virtual HRESULT COM_CALLCONV UpdatePrivateProfileSubstatus(WSCSecurityProductSubStatus status) = 0;
|
||||||
|
virtual HRESULT COM_CALLCONV UpdatePublicProfileSubstatus(WSCSecurityProductSubStatus status) = 0;
|
||||||
|
};
|
||||||
} // namespace defendnot
|
} // namespace defendnot
|
||||||
|
|||||||
Reference in New Issue
Block a user