This commit is contained in:
es3n1n
2025-05-07 17:01:09 +09:00
commit a49f027fde
33 changed files with 2609 additions and 0 deletions

View 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(&reg_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""), &registered_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

View 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

View 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