Что еще, например нам нужно скрыть процесс от Task Manager'a(Диспетчера задач) и любопытных глаз пользователя/админа. Делаем инжект в программу которая постоянно висит в памяти и не вызывает подозрений - PROFIT! Далее, на основе инжектов можно писать ботов для программ и игр. Например перехватив управление некоторыми функциями DirectX можно рисовать внутри игры какие нибуть нужные и полезные данные. Ну и конечно еще можно перехватывать некие данные, например пароли и логины в программах перехватывая функцию ввода с клавиатуры/мыши.
Но я отвлекся, продолжим первую часть
Остановились мы на том, что написали жертву и написали сам инжектор, а осталась сама DLL которая будет подгружаться.
Тут у меня кончилось воображение, по этому DLL будет называться просто test.dll
Повторим задачи этой длл.
1. Найти PE заголовок основного процесса.
2. В PE заголовке найти таблицу Data Directories
3. В таблице Data Directories найти ссылку на таблицу импорта(IAT)
4. Найти ту функцию которую будем подменять у нас она называется MessageBoxA
5. Подменить этот адрес своей функцией.
6. Както обработать данные полученные функцией MessageBoxA я заменю слово "Message" на "Successful inject!"
Ну и наконец код DLL с коментариями:
.386 .model flat, stdcall ;32 bit memory model option casemap :none ;case sensitive include test.inc .code start: LibMain proc instance:dword,reason:dword,reserved:dword .IF reason == DLL_PROCESS_ATTACH ; проверяем процесс приатачился? invoke GetFuncIAT ; ищем функцию MessageBoxA .if eax != -1 ; invoke MessageBox, 0, addr userdll, addr userdll,MB_OK ; тестовый мессадж бокс, который покажет что инжект произошел mov ebx, DWORD PTR [eax] ; получаем ссылку на MessageBoxA mov oldAMes, ebx ; сохраняем адрес MessageBoxA, он нам пригодится push eax ; сохраним eax в стеке invoke VirtualProtect, eax, 4,PAGE_READWRITE, addr op ; переводим кусок памяти в запись иначе сработает исключение pop eax ; восстанавливаем адрес в в eax mov ebx, offset Intercept_MessageBoxA ; запишем в ebx адрес своей функции mov DWORD PTR [eax], ebx ; а теперь его в таблицу IAT invoke VirtualProtect, eax, 4, op, NULL ; вернем права на память как було! .endif .endif mov eax,1 ; системе вренем 1, указывая, что дллка успешно загружена ret LibMain endp GetFuncIAT proc uses ebx ecx invoke GetModuleHandle, NULL ; получаем начало проекции процесса в котором мы находимся, так называемую базу mov hMod, eax ; сохраним его в hMod add eax, 3ch ; сдвинимся на 3ch, чтобы узнать где начинается NT Headers xor ebx, ebx ; обнулим ebx mov bl, BYTE PTR [eax] ; узнаем по какому смещению начинается NT Headers add ebx, hMod ; прибавим к нему базу .if WORD PTR [ebx] != 4550h ; проверим, это вообще PE? jmp errorExit ; если нет - выход .endif add ebx, 6 ; прибавим 6 байт, чтобы узнать сколько секций, зачем я это сделал незнаю, но пусть будет xor eax, eax ; обнуляем eax mov ax, WORD PTR [ebx] ; получим количество секций mov cSec, eax ; запишем в cSec add ebx, 14 ; прибавим еще 14 байт xor eax, eax ; обнуляем eax mov ax, WORD PTR [ebx] ; получим размер заголовка Optional Header, тоже незнаю зачем это сделал - привычка похоже mov sizeOpt, eax ; сохраним размер заголовка Optional Header в sizeOpt, add ebx, 4 ; прибавим 4 байта и окажемся в начале Optional Header mov hOpt, ebx ; сохраним это знание в hOpt add ebx, 104 ; прибавим 104 байта и окажемся в Data Directories на строчке Import Directory RVA mov eax, DWORD PTR [ebx] ; указатель запишем в eax add eax, hMod ; прибавим базу mov import, eax ; это и есть таблицы IAT указывающая на первую DLL в списке nextlib: mov curDll, eax ; сохраним eax в переменной curDll add eax, 12 ; прибавим 12 байтов mov ebx, DWORD PTR [eax] ; получим указатель без базы на название DLL add ebx, hMod ; прибавим базу invoke lstrcmp, ebx, offset userdll ; сравним, а не та ли дллка по имени user32.dll которую мы ищем .if eax != 0 ; ежели не та mov eax, import ; в eax записываем начальный адрес импорта add eax, 20 ; прибавляем к нему 20 байт, чтобы перейти на следующую DLL mov import, eax ; записываем в переменную import .if DWORD PTR [eax] == 0 ; ежели по эту адресу 0 jmp errorExit ; то IAT закончилась - аварийный выход .endif jmp nextlib ; прыгаем на метку nextlib .endif mov eax, curDll ; в eax пишем ссылку на список функций mov ebx, DWORD PTR [eax] ; в ebx записываем адрес на начало списка add ebx, hMod ; прибавляем базу xor ecx, ecx ; обнуляем счетчик ecx nextfunc: mov curFunc, ebx ; в переменной curFunc сохраняем ссылку на текущее имя функции mov eax, DWORD PTR [ebx] ; получаем адрес строки с именем функции add eax, hMod ; прибавляем базу add eax, 2 ; прибавляем 2 байта, чтобы получить начало имени и отрезать техническую инфу push ecx ; сохраним счетчик, он нам пригодится invoke lstrcmp, eax, offset func ; сравниваем, а не та ли это функция MessageBoxA pop ecx ; восстанавливаем ecx .if eax != 0 ; ежели не та mov ebx, curFunc ; в ebx восстанавливаем ссылку на адреса функций add ebx, 4 ; смещаемся на 4 байта .if DWORD PTR [ebx] == 0 ; если там 0, то список функций кончился jmp errorExit ; аварийный выход .endif inc ecx ; если не ноль добавляем к ecx 1 jmp nextfunc и прыгаем на обработку следующей функции .endif mov eax, curDll ; восстанавливаем данные в переменной curDll add eax, 16 ; прибавляем 16 и получим указатель на список указателей на функции mov ebx, DWORD PTR [eax] ; получаем указатель на начало указателей на функции add ebx, hMod ; прибавляем к нему базу imul ecx, ecx, 4 ; вычисляем на какой позиции в списке указателей на функции находится наш add ebx, ecx ; прибавляем к началу списка указателей на функции mov eax, ebx ; скопируем в eax дабы вернуть указатель ret errorExit: mov eax, -1 ; аварийный выход, в eax подставим -1 ret GetFuncIAT endp Intercept_MessageBoxA proc ; фейковый MEssageBoxA pop ebx ; сохраним точку возврата, она нам еще понадобится mov eax, offset newStr ; получим адрес новой строчки которая выведется в MessageBoxA mov DWORD PTR [esp+4], eax ; запишем адрес новой строчки в стек, где находится старая "Message" делая собственно подмен на "Successful inject!" mov eax, oldAMes ; всопмним оригинальный адрес MessageBoxA call eax ; вызываем MessageBoxA, но уже с подмененным текстом сообщения push ebx ; восстанавливаем точку возврата ret Intercept_MessageBoxA endp end LibMain
Работает это следующим образом, test.dll кладется рядом с inject.exe, запускается victim.exe, если потыкать кнопку ОК, то видно что окошко со словом "Message" после чего не закрывая victim.exe, запускается inject.exe, если после этого потыкать на кнопку ОК, то сообщение уже будет "Successful inject!". Если оно появилось, то значит инжект сработал.
Вот в принципе и все, как видно - абсолютно ничего сложно, все достаточно элементарно.
Сегодня на pastebin выкладывать ничего не буду, ибо лень мне что то копипастой заниматься, все исходники и работающие программы можно скачать на депозите.
Удачи в дальнейшем иследовнии :)
Комментариев нет:
Отправить комментарий