mirror of
https://github.com/es3n1n/defendnot.git
synced 2026-08-02 10:32:01 +00:00
initial
This commit is contained in:
177
defendnot-loader/core/autorun.cpp
Normal file
177
defendnot-loader/core/autorun.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
#include "core/core.hpp"
|
||||
|
||||
#include "shared/ctx.hpp"
|
||||
#include "shared/defer.hpp"
|
||||
#include "shared/names.hpp"
|
||||
|
||||
#include <print>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <comdef.h>
|
||||
#include <taskschd.h>
|
||||
|
||||
#pragma comment(lib, "taskschd.lib")
|
||||
#pragma comment(lib, "comsupp.lib")
|
||||
#pragma comment(lib, "ole32.lib")
|
||||
|
||||
namespace loader {
|
||||
namespace {
|
||||
constexpr std::string_view kTaskName = names::kProjectName;
|
||||
|
||||
template <typename Callable>
|
||||
[[nodiscard]] bool with_service(Callable&& callback) {
|
||||
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
CoUninitialize();
|
||||
};
|
||||
|
||||
ITaskService* service = nullptr;
|
||||
hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, reinterpret_cast<void**>(&service));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
service->Release();
|
||||
};
|
||||
|
||||
hr = service->Connect(VARIANT{}, VARIANT{}, VARIANT{}, VARIANT{});
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ITaskFolder* root_folder = nullptr;
|
||||
hr = service->GetFolder(BSTR(L"\\"), &root_folder);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
root_folder->Release();
|
||||
};
|
||||
|
||||
root_folder->DeleteTask(BSTR(kTaskName.data()), 0);
|
||||
return callback(service, root_folder);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
[[nodiscard]] bool add_to_autorun() {
|
||||
const auto bin_path = shared::get_this_module_path();
|
||||
|
||||
return with_service([bin_path](ITaskService* service, ITaskFolder* folder) -> bool {
|
||||
ITaskDefinition* task = nullptr;
|
||||
auto hr = service->NewTask(0, &task);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
task->Release();
|
||||
};
|
||||
|
||||
IRegistrationInfo* reg_info = nullptr;
|
||||
hr = task->get_RegistrationInfo(®_info);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
reg_info->Release();
|
||||
};
|
||||
reg_info->put_Author(_bstr_t(names::kRepoUrl.data()));
|
||||
|
||||
IPrincipal* pPrincipal = nullptr;
|
||||
hr = task->get_Principal(&pPrincipal);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
pPrincipal->Release();
|
||||
};
|
||||
|
||||
ITriggerCollection* trigger_collection = nullptr;
|
||||
hr = task->get_Triggers(&trigger_collection);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
trigger_collection->Release();
|
||||
};
|
||||
|
||||
ITrigger* trigger = nullptr;
|
||||
hr = trigger_collection->Create(TASK_TRIGGER_LOGON, &trigger);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
trigger->Release();
|
||||
};
|
||||
|
||||
IActionCollection* action_collection = nullptr;
|
||||
hr = task->get_Actions(&action_collection);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
action_collection->Release();
|
||||
};
|
||||
|
||||
IAction* action = nullptr;
|
||||
hr = action_collection->Create(TASK_ACTION_EXEC, &action);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
action->Release();
|
||||
};
|
||||
|
||||
IExecAction* exec_action = nullptr;
|
||||
hr = action->QueryInterface(IID_IExecAction, (void**)&exec_action);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
exec_action->Release();
|
||||
};
|
||||
|
||||
ITaskSettings* settings = nullptr;
|
||||
hr = task->get_Settings(&settings);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defer->void {
|
||||
settings->Release();
|
||||
};
|
||||
|
||||
pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
|
||||
settings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
|
||||
settings->put_StopIfGoingOnBatteries(VARIANT_FALSE);
|
||||
exec_action->put_Path(_bstr_t(bin_path.string().c_str()));
|
||||
exec_action->put_Arguments(_bstr_t("--from-autorun"));
|
||||
|
||||
IRegisteredTask* registered_task = nullptr;
|
||||
hr = folder->RegisterTaskDefinition(_bstr_t(kTaskName.data()), task, TASK_CREATE_OR_UPDATE, VARIANT{}, VARIANT{}, TASK_LOGON_INTERACTIVE_TOKEN,
|
||||
_variant_t(L""), ®istered_task);
|
||||
|
||||
defer->void {
|
||||
registered_task->Release();
|
||||
};
|
||||
return SUCCEEDED(hr);
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] bool remove_from_autorun() {
|
||||
return with_service([]<typename... TArgs>(TArgs...) -> bool { return true; });
|
||||
}
|
||||
} // namespace loader
|
||||
19
defendnot-loader/core/core.hpp
Normal file
19
defendnot-loader/core/core.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace loader {
|
||||
struct Config {
|
||||
public:
|
||||
std::string name;
|
||||
bool disable;
|
||||
bool verbose;
|
||||
bool from_autorun;
|
||||
};
|
||||
|
||||
[[nodiscard]] HANDLE inject(std::string_view dll_path, std::string_view proc_name);
|
||||
[[nodiscard]] bool add_to_autorun();
|
||||
[[nodiscard]] bool remove_from_autorun();
|
||||
} // namespace loader
|
||||
58
defendnot-loader/core/inject.cpp
Normal file
58
defendnot-loader/core/inject.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "core/core.hpp"
|
||||
|
||||
#include "shared/defer.hpp"
|
||||
#include <print>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace loader {
|
||||
[[nodiscard]] HANDLE inject(std::string_view dll_path, std::string_view proc_name) {
|
||||
STARTUPINFOA si = {
|
||||
.cb = sizeof(si),
|
||||
};
|
||||
PROCESS_INFORMATION pi = {
|
||||
0,
|
||||
};
|
||||
SECURITY_ATTRIBUTES sa = {
|
||||
.nLength = sizeof(sa),
|
||||
.bInheritHandle = TRUE,
|
||||
};
|
||||
|
||||
std::println("** booting {}", proc_name);
|
||||
if (!CreateProcessA(nullptr, const_cast<char*>(proc_name.data()), &sa, &sa, FALSE, CREATE_SUSPENDED, nullptr, nullptr, &si, &pi)) {
|
||||
throw std::runtime_error(std::format("unable to create process: {}", GetLastError()));
|
||||
}
|
||||
|
||||
defer->void {
|
||||
CloseHandle(pi.hThread);
|
||||
/// Not closing hProcess because we return it
|
||||
};
|
||||
|
||||
LPVOID mem = VirtualAllocEx(pi.hProcess, nullptr, dll_path.size() + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
if (mem == nullptr) {
|
||||
throw std::runtime_error(std::format("unable to allocate memory: {}", GetLastError()));
|
||||
}
|
||||
|
||||
defer->void {
|
||||
VirtualFreeEx(pi.hProcess, mem, 0, MEM_RELEASE);
|
||||
};
|
||||
|
||||
if (!WriteProcessMemory(pi.hProcess, mem, dll_path.data(), dll_path.size() + 1, nullptr)) {
|
||||
throw std::runtime_error(std::format("unable to write memory: {}", GetLastError()));
|
||||
}
|
||||
|
||||
HANDLE thread = CreateRemoteThread(pi.hProcess, nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(LoadLibraryA), mem, 0, nullptr);
|
||||
if (thread == NULL) {
|
||||
throw std::runtime_error(std::format("unable to create thread: {}", GetLastError()));
|
||||
}
|
||||
|
||||
defer->void {
|
||||
CloseHandle(thread);
|
||||
};
|
||||
|
||||
/// Wait for DllMain to complete
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
return pi.hProcess;
|
||||
}
|
||||
} // namespace loader
|
||||
Reference in New Issue
Block a user