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:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
runs-on: windows-2022
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [x64, x86, ARM64]
|
||||
|
||||
@@ -43,7 +43,7 @@ Download the [latest](https://github.com/es3n1n/defendnot/releases/latest) relea
|
||||
## Usage
|
||||
|
||||
```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:
|
||||
-h, --help prints help message and exits
|
||||
@@ -51,6 +51,7 @@ Optional arguments:
|
||||
-n, --name av display name [default: "dnot.sh"]
|
||||
-d, --disable disable defendnot
|
||||
-v, --verbose verbose logging
|
||||
--firewall also register a fake firewall
|
||||
--silent do not allocate console
|
||||
--autorun-as-user create autorun task as currently logged in user
|
||||
--disable-autorun disable autorun task creation
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "shared/util.hpp"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
namespace shared {
|
||||
constexpr std::size_t kMaxNameLength = 128;
|
||||
constexpr std::string_view kCtxPath = "ctx.bin";
|
||||
@@ -28,6 +29,7 @@ namespace shared {
|
||||
State state = State::ON;
|
||||
bool verbose = false;
|
||||
std::array<char, kMaxNameLength + 1> name = {0}; // +1 for the nullterm
|
||||
bool register_firewall = false;
|
||||
|
||||
void serialize() const {
|
||||
std::ofstream stream(detail::ctx_path(), std::ios::binary);
|
||||
@@ -50,3 +52,4 @@ namespace shared {
|
||||
|
||||
static_assert(std::is_trivially_copyable_v<Context>);
|
||||
} // namespace shared
|
||||
#pragma pack(pop)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "shared/ctx.hpp"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace loader {
|
||||
@@ -16,9 +18,17 @@ namespace loader {
|
||||
bool disable;
|
||||
bool alloc_console;
|
||||
bool verbose;
|
||||
bool register_firewall;
|
||||
bool from_autorun;
|
||||
AutorunType autorun_type;
|
||||
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);
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace {
|
||||
|
||||
shared::ctx.state = config.disable ? shared::State::OFF : shared::State::ON;
|
||||
shared::ctx.verbose = config.verbose;
|
||||
shared::ctx.register_firewall = config.register_firewall;
|
||||
std::ranges::copy(config.name, shared::ctx.name.data());
|
||||
|
||||
/// 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("-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("--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("--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);
|
||||
@@ -120,6 +122,7 @@ int main(int argc, char* argv[]) try {
|
||||
.disable = program.get<bool>("-d"),
|
||||
.alloc_console = !program.get<bool>("--silent"),
|
||||
.verbose = program.get<bool>("-v"),
|
||||
.register_firewall = program.get<bool>("--firewall"),
|
||||
.from_autorun = program.get<bool>("--from-autorun"),
|
||||
.autorun_type = program.get<bool>("--autorun-as-user") ? /// As system on boot is the default value
|
||||
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
|
||||
if (config.from_autorun) {
|
||||
shared::ctx.deserialize();
|
||||
config.verbose = shared::ctx.verbose;
|
||||
config = shared::ctx;
|
||||
}
|
||||
|
||||
if (!config.alloc_console && config.verbose) {
|
||||
|
||||
@@ -8,27 +8,41 @@
|
||||
|
||||
namespace defendnot {
|
||||
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>
|
||||
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
|
||||
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);
|
||||
if (shared::ctx.state == shared::State::OFF) {
|
||||
if (!should_register) {
|
||||
return;
|
||||
}
|
||||
|
||||
/// Register and activate
|
||||
logln("{}_register: {:#x}", log_prefix, com::checked(inst->Register(name, name, 0, 0)));
|
||||
logln("{}_update: {:#x}", log_prefix, com::checked(inst->UpdateStatus(WSCSecurityProductState::ON, static_cast<BOOL>(true))));
|
||||
|
||||
/// Update the substatuses, if the interface supports this
|
||||
if constexpr (std::is_same_v<Ty, IWscAVStatus4>) {
|
||||
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)));
|
||||
}
|
||||
const auto step = [&](const std::string_view what, const HRESULT hr) -> void {
|
||||
logln("{}_{}: {:#x}", log_prefix, what, com::checked(hr));
|
||||
};
|
||||
step("register", inst->Register(name, name, 0, 0));
|
||||
activate(step, inst.get());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -45,12 +59,14 @@ namespace defendnot {
|
||||
|
||||
/// Convert to BSTR
|
||||
auto name = SysAllocString(name_w.c_str());
|
||||
defer->void {
|
||||
defer {
|
||||
SysFreeString(name);
|
||||
};
|
||||
|
||||
/// Register our stuff in the WSC interfaces
|
||||
apply<IWscASStatus>("IWscASStatus", name);
|
||||
apply<IWscAVStatus4>("IWscAVStatus4", name);
|
||||
const bool enabled = shared::ctx.state != shared::State::OFF;
|
||||
apply<IWscASStatus>("IWscASStatus", name, enabled);
|
||||
apply<IWscAVStatus4>("IWscAVStatus4", name, enabled);
|
||||
apply<IWscFWStatus2>("IWscFWStatus2", name, enabled && shared::ctx.register_firewall);
|
||||
}
|
||||
} // namespace defendnot
|
||||
|
||||
@@ -69,4 +69,14 @@ namespace defendnot {
|
||||
virtual HRESULT COM_CALLCONV Unregister() = 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
|
||||
|
||||
Reference in New Issue
Block a user