Jump to content

DLL-инъекция

В компьютерном программировании внедрение DLL — это метод, используемый для запуска кода в адресном пространстве другого процесса путем принудительной загрузки библиотеки динамической компоновки . [1] Внедрение DLL часто используется внешними программами для влияния на поведение другой программы таким образом, которого ее авторы не ожидали или не намеревались. [1] [2] [3] Например, внедренный код может перехватывать вызовы системных функций, [4] [5] или прочитать содержимое текстовых полей паролей , что невозможно сделать обычным способом. [6] Программа, используемая для внедрения произвольного кода в произвольные процессы, называется инжектором DLL .

Подходы в Microsoft Windows

[ редактировать ]

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

  • DLL, перечисленные в реестра записи HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs загружаются в каждый процесс, который загружает User32.dll во время первоначального вызова этой DLL. [7] [8] [9] Начиная с Windows Vista , AppInit_DLL по умолчанию отключены. [10] Начиная с Windows 7, инфраструктура AppInit_DLL поддерживает подписывание кода . Начиная с Windows 8 , вся функциональность AppInit_DLL отключается при безопасной загрузке независимо от подписи кода или настроек реестра. включенной [11]
  • DLL, перечисленные в разделе реестра HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs загружаются в каждый процесс, который вызывает Win32 API функции CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW и WinExec. Это правильный способ легального внедрения DLL в текущей версии Windows — Windows 10. DLL должна быть подписана действительным сертификатом.
  • Функции манипулирования процессами, такие как CreateRemoteThread или методы внедрения кода , такие как AtomBombing, [12] может использоваться для внедрения DLL в программу после ее запуска. [5] [6] [13] [14] [15] [16]
    1. Откройте дескриптор целевого процесса. Это можно сделать, создав процесс [17] [18] или отключив что-то, созданное этим процессом, о существовании которого известно — например, окно с предсказуемым заголовком, [19] или получив список запущенных процессов [20] и сканирование имени файла целевого исполняемого файла . [21]
    2. Выделите немного памяти в целевом процессе, [22] и в него записывается имя внедряемой DLL. [13] [23]
      Этот шаг можно пропустить, если подходящее имя DLL уже доступно в целевом процессе. Например, если процесс ссылается на User32.dll , GDI32.dll , Kernel32.dll или любую другую библиотеку, имя которой заканчивается на 32.dll, можно было бы загрузить библиотеку с именем 32.dll[ нужна ссылка ] . В прошлом было продемонстрировано, что этот метод эффективен против метода защиты процессов от внедрения DLL. [24]
    3. Создайте новый поток в целевом процессе [25] с начальным адресом потока, установленным как адрес LoadLibrary и аргумент установлен на адрес строки, только что загруженной в цель. [13] [26]
      Вместо того, чтобы записывать имя загружаемой DLL в цель и запускать новый поток с LoadLibrary, можно записать код, который будет выполняться, в цель и запустить поток с этого кода. [6]
    4. Затем операционная система вызывает процедуру инициализации внедренной DLL. [13] [27]
    Обратите внимание, что без принятия мер предосторожности этот подход может быть обнаружен целевым процессом из-за DLL_THREAD_ATTACH уведомления, отправляемые каждому загруженному модулю при запуске потока. [27]
  • Windows перехватывает вызовы, такие как SetWindowsHookEx. [2] [5] [6] [28] [29] [30]
  • Используйте SuspendThread или NtSuspendThread функцию для приостановки всех потоков, а затем используйте SetThreadContext или NtSetContextThread функция для изменения контекста существующего потока в приложении для выполнения внедренного кода, который, в свою очередь, может загрузить DLL. [4] [31] [32]
  • Используйте ограничения дизайна в Windows и приложениях, вызывающих LoadLibrary или LoadLibraryEx без указания полного пути к загружаемой DLL. [33] [34] [35]
  • уровня операционной системы Прокладки .
  • Замена DLL, специфичной для приложения, мошеннической заменой, которая реализует тот же экспорт функций, что и оригинал. [36]

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

[ редактировать ]

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

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

LD_PRELOAD="./test.so" prog

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

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

DYLD_INSERT_LIBRARIES="./test.dylib" DYLD_FORCE_FLAT_NAMESPACE=1 prog

В Unix-подобных системах также можно использовать методы, основанные на отладчике. [41]

Пример кода

[ редактировать ]

Копирование DLL, загруженной LoadLibrary, в удаленный процесс

[ редактировать ]

Поскольку нет LoadLibrary() Чтобы загрузить DLL во внешний процесс, вам необходимо скопировать локально загруженную DLL в удаленно выделенную память. Следующий код с комментариями показывает, как это сделать.

#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <memory>
#include <system_error>
#include <charconv>
#include <vector>
#include <cassert>

#if defined(_MSC_VER)
	#pragma warning(disable: 6387)
#endif

using namespace std;

using XHANDLE = unique_ptr<void, decltype([]( void *h ) { h && h != INVALID_HANDLE_VALUE && CloseHandle( (HANDLE)h ); })>;
using XHMODULE = unique_ptr<remove_reference_t<decltype(*HMODULE())>, decltype([]( HMODULE hm ) { hm && FreeLibrary( hm); })>;

MODULEENTRY32W getModuleDescription( HMODULE hmModule );
size_t maxReadableRange( void *pRegion );
string getAbsolutePathA( char const *fileName, char const *err );
DWORD dumbParseDWORD( wchar_t const *str );
wstring getAbsolutePath( wchar_t const *makeAbsolute, char const *errStr );
[[noreturn]]
void throwSysErr( char const *str );

constexpr wchar_t const *LOADER_DLL_NAME = L"loaderDll.dll";
constexpr char const *LOADER_THREAD_PROC = "loadLibraryThread";

int wmain( int argc, wchar_t **argv )
{
	try
	{
		if( argc < 3 )
			return EXIT_FAILURE;
		wchar_t const
			*processId = argv[1],
			*remoteLoadedDll = argv[2],
			*initData = argc >= 4 ? argv[3] : L"";
		DWORD dwProcessId = dumbParseDWORD( processId );
		XHANDLE xhProcess( OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessId ) );
		if( !xhProcess.get() )
			throwSysErr( "can't open remote process with unlimited access" );
		XHMODULE xhmLocalLoader;
		MODULEENTRY32W meLocalLoader;
		for( ; ; )
		{
			xhmLocalLoader.reset( LoadLibraryW( LOADER_DLL_NAME ) );
			if( !xhmLocalLoader.get() )
				throwSysErr( "can't locally load loader DLL" );
			// get module starting address and size
			meLocalLoader = getModuleDescription( (HMODULE)xhmLocalLoader.get() );
			// try to allocate memory range in the foreign process with the same size the DLL in our process occupies
			if( VirtualAllocEx( xhProcess.get(), meLocalLoader.modBaseAddr, meLocalLoader.modBaseSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE ) )
				break;
			// allocation failed, free library
			xhmLocalLoader.reset( nullptr );
			// try to reserve address range which the library occupied before to prevent
			// recycling of that address range with the next LoadLibrary() call.
			if( !VirtualAlloc( meLocalLoader.modBaseAddr, meLocalLoader.modBaseSize, MEM_RESERVE, PAGE_NOACCESS ) )
				throwSysErr( "can't reserve address range of previously mapped DLL" );
		}
		LPTHREAD_START_ROUTINE loaderThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress( (HMODULE)xhmLocalLoader.get(), ::LOADER_THREAD_PROC );
		if( !loaderThreadProc )
			throwSysErr( "can't get procedure entry point" );
		// coppy all readable DLL-contents to the destination process
		if( SIZE_T copied; !WriteProcessMemory( xhProcess.get(), meLocalLoader.modBaseAddr, meLocalLoader.modBaseAddr, meLocalLoader.modBaseSize, &copied ) && GetLastError() != ERROR_PARTIAL_COPY )
			throwSysErr( "can't copy loader DLL to remote process" );
		// create two concatenated C strings that contain the DLL to load as well as the parameter
		// given to the remotely loaded DLL
		wstring data( getAbsolutePath( remoteLoadedDll, "can't get absolute path to DLL to be remotely loaded" ) );
		data += L'\0';
		data += initData;
		data += L'\0';
		size_t dataSize = data.size() * sizeof(wchar_t);
		auto initStrErr = []() { throwSysErr( "failed to copy initialization data to loader DLL" ); };
		void *remoteData;
		// remotely allocate memory large enough to hold at least our both strings
		if( !(remoteData = VirtualAllocEx( xhProcess.get(), nullptr, dataSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)) )
			initStrErr();
		// write our both strings to remote memory
		if( SIZE_T copied; !WriteProcessMemory( xhProcess.get(), remoteData, data.data(), dataSize, &copied )
			|| copied != dataSize )
			initStrErr();
		// create a remote DLL loader thread; the given entry point has the same address in our process as well as the remote address
		// give this thread the address of our both remotely copied strings
		XHANDLE xhRemoteInitThread( CreateRemoteThread( xhProcess.get(), nullptr, 0, loaderThreadProc, remoteData, 0, nullptr ) );
		if( !xhRemoteInitThread.get() )
			throwSysErr( "failed to create remote initializaton thread" );
		// wait on our remote loader thread to finish
		// it should that very soon as its only task is to copy the strings for the remotely loaded DLL and load this DLL itself
		if( WaitForSingleObject( xhRemoteInitThread.get(), INFINITE ) == WAIT_FAILED )
			throwSysErr( "can't wait for remote initialization thread" );
		DWORD dwInitThreadExitCode;
		if( !GetExitCodeThread( xhRemoteInitThread.get(), &dwInitThreadExitCode ) )
			throwSysErr( "can't get initialization thread's success code" );
		// check for remote loader's exit-code, it should be NO_ERROR (0)
		if( dwInitThreadExitCode != NO_ERROR )
			throw system_error( (int)dwInitThreadExitCode, system_category(), "LoadLibrary() error in remote loader dll" );
	}
	catch( exception const &se )
	{
		cout << se.what() << endl;
	}
}

MODULEENTRY32W getModuleDescription( HMODULE hmModule )
{
	// returns the absolute path to for a given module handle
	auto getModulePath = []( HMODULE hm, char const *err ) -> wstring
	{
		wchar_t modulePath[MAX_PATH];
		if( DWORD dwRet = GetModuleFileNameW( hm, modulePath, MAX_PATH ); !dwRet || dwRet >= MAX_PATH )
			throwSysErr( err );
		return modulePath;
	};
	// local DLL's module path
	wstring moduleAbsolute( getModulePath( hmModule , "can't get absolute path for local loader DLL" ) );
	XHANDLE xhToolHelp( CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, GetCurrentProcessId() ) );
	auto toolHelpErr = []() { throwSysErr( "can't list modules in injecting process" ); };
	if( xhToolHelp.get() == INVALID_HANDLE_VALUE )
		toolHelpErr();
	MODULEENTRY32W me;
	me.dwSize = sizeof me;
	if( !Module32FirstW( xhToolHelp.get(), &me ) )
		toolHelpErr();
	for( ; ; )
	{
		// has the current image in the snapshot the same path like the DLL which is given by the module handle
		// no need to compare case insensitive because we got both paths from the kernel so that they should exactly match
		if( getModulePath( me.hModule, "can't get absolute path for toolhelp-enumerated DLL name" ) == moduleAbsolute )
			return me;
		me.dwSize = sizeof me;
		if( !Module32NextW( xhToolHelp.get(), &me ) )
			toolHelpErr();
	}
}

[[noreturn]]
void throwSysErr( char const *str )
{
	throw system_error( (int)GetLastError(), system_category(), str );
}

DWORD dumbParseDWORD( wchar_t const *str )
{
	// idiot's from_chars because there's no from_chars for unicode characters
	DWORD dwRet = 0;
	while( *str )
		dwRet = dwRet * 10 + (unsigned char)(*str++ - L'0');
	return dwRet;
}

wstring getAbsolutePath( wchar_t const *makeAbsolute, char const *errStr )
{
	// get absolute path of a given relative path
	wstring path( MAX_PATH, L'\0' );
	DWORD dwLength;
	if( !(dwLength = GetFullPathNameW( makeAbsolute, MAX_PATH, path.data(), nullptr )) )
		throwSysErr( errStr );
	// if deRet == MAX_PATH we might miss a zero-termination character, treat this as an error
	else if( dwLength >= MAX_PATH )
		throw invalid_argument( errStr );
	path.resize( dwLength );
	return path;
}

Основная проблема, решаемая здесь, заключается в том, что локально загружаемая DLL, скопированная в удаленный процесс, должна занимать те же адреса, что и в процессе внедрения. Приведенный выше код делает это путем выделения памяти для того же диапазона адресов, который был занят ранее в процессе внедрения. Если это не удается, DLL освобождается локально, прежний диапазон адресов помечается как зарезервированный, а LoadLibrary() звонок повторяется. Резервируя прежний диапазон адресов, код предотвращает появление следующего LoadLibrary() попытка назначит тот же диапазон адресов, который использовался ранее.

Основным недостатком этого подхода является то, что DLL, скопированная во внешний процесс, заключается в отсутствии каких-либо других зависимостей библиотеки DLL от этой DLL, загруженной во внешнее адресное пространство, или указателей, например вызовов функций, на библиотеки DLL, загруженные внешним процессом. корректируется в соответствии с зависимостями скопированной DLL. К счастью, библиотеки DLL обычно имеют предпочтительные адреса загрузки, которые учитываются загрузчиком ядра . Некоторые библиотеки DLL, такие как kernel32.dll надежно загружаются в самом начале, когда адресное пространство процесса занято исполняемым образом и зависимыми от него DLL. Обычно они имеют надежные и неконфликтные адреса. Таким образом, скопированная DLL может использовать любую kernel32.dll вызовы, например, для загрузки другой DLL с полными преимуществами локально загруженной DLL, т.е. имеющей все относительные зависимости от библиотеки. Путь к этой DLL копируется во внешнее адресное пространство и передается в качестве параметра void функции потока. Вышеупомянутая реализация также позволяет иметь дополнительные параметры, которые передаются в удаленно скопированную DLL после того, как строка с удаленно загружаемой DLL передается в эту DLL.

Следующий код является источником удаленно скопированной библиотеки DLL-загрузчика, которая выполняет только kernel32.dll звонки:

#include <Windows.h>
#include <atomic>

using namespace std;

BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
	return TRUE;
}

DWORD WINAPI loadLibraryThread( LPVOID lpvThreadParam );

// MSVC / clang-cl mangling
#if defined(_M_IX86)
	#pragma comment(linker, "/export:loadLibraryThread=?loadLibraryThread@@YGKPAX@Z")
#elif defined(_M_X64)
	#pragma comment(linker, "/export:loadLibraryThread=?loadLibraryThread@@YAKPEAX@Z")
#else
	#error unsupported platform
#endif

DWORD WINAPI loadLibraryThread( LPVOID lpvThreadParam )
{
	// use atomics to prevent the "optimizer" from replacing my code with
	// wsclen or memcpy library calls to external addresses actually not valid
	// with this copied DLL
	// ignore any atomic load barriers since this hasn't to be fast
	atomic_wchar_t const
		// path to the library to load from inside
		*libPath = (atomic_wchar_t *)lpvThreadParam,
		// pointer to the parameters given to this library
		*data = libPath;
	// advance data to the actual parameters
	while( *data++ );
	HANDLE hOutboundEvent;
	// create named event to notify the remote DLL that data has already copied 
	// necessary because the remote DLL execution begins directly after LoadLibrary()S
	if( !(hOutboundEvent = CreateEventA( nullptr, FALSE, FALSE, "nasty hackers" )) )
		return GetLastError();
	// size of the paramers given to the DLL
	size_t dataSize = 0;
	while( data[dataSize++] );
	if( dataSize >= MAX_PATH )
		return ERROR_INVALID_PARAMETER;
	// clean LoadLibrary() with all DLL-dependencies
	HMODULE hm = LoadLibraryW( (wchar_t *)libPath );
	if( !hm )
		return GetLastError();
	// get address of parameters export from the loaded DLL
	wchar_t volatile (&initData)[MAX_PATH] = *(wchar_t (*)[MAX_PATH])GetProcAddress( hm, "initData" );
	// the loaded DLL doesn't provide such an export, i.e. its not relying on parameters ?
	if( !initData )
		return NO_ERROR;
	// copy parameters to the DLL
	for( size_t i = 0; i != dataSize; initData[i] = data[i], ++i );
	// notify that parameters available
	if( !SetEvent( hOutboundEvent ) )
		return GetLastError();
	return NO_ERROR;
}

Последний код показывает пример DLL, загружаемой DLL-загрузчиком, которая печатает параметры в файл.

#include <Windows.h>
#include <fstream>
#include <atomic>

using namespace std;

#if defined(_MSC_VER)
	#pragma warning(disable: 6387) // returned handle could be null
#endif

#if defined(_M_IX86)
	#pragma comment(linker, "/export:DllMain=_DllMain@12")
#elif defined(_M_X64)
	#pragma comment(linker, "/export:DllMain=_DllMain@12")
#else
	#error unsupported platform
#endif

using namespace std;

DWORD WINAPI myThread( LPVOID lpvThreadParam );

BOOL APIENTRY DllMain( HMODULE hModule, DWORD dwReason, LPVOID lpReserved )
{
	switch( dwReason )
	{
	case DLL_PROCESS_ATTACH:
		// create thread since there is no export called from the loader DLL
		CreateThread( nullptr, 0, myThread, nullptr, 0, nullptr );
	default:
		break;
	}
	return TRUE;
}

extern "C"
__declspec(dllexport)
wchar_t initData[MAX_PATH] = { 0 };

DWORD WINAPI myThread( LPVOID lpvThreadParam )
{
	// wait for initData to be filled by loader DLL
	// skip that if you don't rely on any initData
	// as the named event "nasty hackers" has been created by our own DLL's
	// LoadLibrary() we're just connecting to a named event, but not creating one
	if( WaitForSingleObject( CreateEventA( nullptr, FALSE, FALSE, "nasty hackers" ), INFINITE ) != WAIT_OBJECT_0 )
		return 0;
	// write parameters in a file to test function
	// the following code doesn't work when the DLL is non-statically linked for unknown reasons
	wofstream wofs;
	wofs.open( "c:\\Users\\xxx\\test.txt", ofstream::out | ofstream::trunc );
	wofs << initData << endl;
	return 0;
}

Важным фактом является то, что экспорт не вызывается из DLL-загрузчика, вместо этого вся инициализация выполняется из DllMain. Единственный экспорт – это initData, который получает параметры, заданные в процессе внедрения через DLL-загрузчик. И нужно знать, что поток, созданный из функции DllMain, не планируется до тех пор, пока он не будет выполнен. DLL_THREAD_ATTACH-функция выполнена успешно. Так что синхронизации изнутри может не быть DllMain с созданной веткой.

  1. ^ Перейти обратно: а б Джеймс Шьюмейкер (2006). «Анализ внедрения DLL» (PDF) . GSM-презентация . Блюнотч. Архивировано из оригинала (PDF) 3 декабря 2008 г. Проверено 31 августа 2008 г.
  2. ^ Перейти обратно: а б Ицелион (август 2002 г.). «Урок 24: Хуки Windows» . Домашняя страница сборки Win32 компании Iczelion . Архивировано из оригинала 1 августа 2008 года . Проверено 31 августа 2008 г.
  3. ^ Рокки Шкив (19 мая 2005 г.). «Расширение диспетчера задач с помощью внедрения DLL» . КодПроект . Архивировано из оригинала 6 февраля 2009 года . Проверено 1 сентября 2008 г.
  4. ^ Перейти обратно: а б Насер Р. Роухани (23 октября 2003 г.). «Учебное пособие по внедрению DLL и перехвату функций» . КодПроект . Архивировано из оригинала 15 апреля 2018 года . Проверено 31 августа 2008 г.
  5. ^ Перейти обратно: а б с Иво Иванов (2 декабря 2002 г.). «Обнаружено перехват API» . КодПроект . Проверено 31 августа 2008 г.
  6. ^ Перейти обратно: а б с д Роберт Кастер (20 августа 2003 г.). «Три способа внедрить ваш код в другой процесс» . КодПроект . Проверено 31 августа 2008 г.
  7. ^ «Работа со значением реестра AppInit_DLLs» . Справка и поддержка Microsoft . Майкрософт. 21 ноября 2006 года . Проверено 31 августа 2008 г.
  8. ^ Раймонд Чен (13 декабря 2007 г.). «AppInit_DLLs следует переименовать в Deadlock_Or_Crash_Randomly_DLLs» . Старая новая вещь . Майкрософт . Проверено 31 августа 2008 г.
  9. ^ "dllmain.c" . РеактОС . Фонд ReactOS. 8 июля 2008 года . Проверено 31 августа 2008 г. [ постоянная мертвая ссылка ]
  10. ^ AppInit_DLL в Windows 7 и Windows Server 2008 R2.
  11. ^ «AppInit DLL и безопасная загрузка» . MSDN . Проверено 29 марта 2016 г.
  12. ^ « Атомная бомбардировка Microsoft Windows посредством внедрения кода» . Мрачное чтение . Проверено 20 апреля 2017 г.
  13. ^ Перейти обратно: а б с д Трент Уоддингтон. «Инжекдлл» . Архивировано из оригинала 30 декабря 2019 года . Проверено 31 августа 2008 г.
  14. ^ «Dll-инъекция» . DreamInCode.net . МедиаГруппа1. 4 мая 2006 г. Архивировано из оригинала 2 сентября 2008 г. Проверено 31 августа 2008 г.
  15. ^ Грег Дженкинс (ноябрь 2007 г.). «Среда внедрения DLL» . Ринг3 Цирк . WordPress. Архивировано из оригинала 28 июня 2020 года . Проверено 31 августа 2008 г.
  16. ^ Дрю Бентон (17 августа 2007 г.). «Более полное решение для внедрения DLL с использованием CreateRemoteThread» . КодПроект . Проверено 1 сентября 2008 г.
  17. ^ «СоздатьПроцесс» . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  18. ^ "ПРОЦЕСС_ИНФОРМАЦИЯ" . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  19. ^ «Функция GetWindowThreadProcessId» . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  20. ^ «ПеречислениеПроцессов» . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  21. ^ «Получитьимя_модуля» . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  22. ^ «ВиртуальныйАллокекс» . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  23. ^ «НаписатьПроцессПамять» . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  24. ^ «Обход самозащиты Outpost с помощью расширенного внедрения DLL с кражей уязвимости» . Матусек . 1 декабря 2006. Архивировано из оригинала 6 февраля 2009 года . Проверено 31 августа 2008 г.
  25. ^ «СоздатьRemoteThread» . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  26. ^ «Загрузить библиотеку» . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  27. ^ Перейти обратно: а б «DllMain» . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  28. ^ «Функция SetWindowsHookEx» . Платформенный SDK для Windows XP SP2 . Майкрософт . Проверено 31 августа 2008 г.
  29. ^ «Значение реестра AppInit_DLLs и Windows 95» . Справка и поддержка Microsoft . Майкрософт. 1 марта 2005 года . Проверено 31 августа 2008 г.
  30. ^ «Внедрение Dll с использованием метода SetWindowsHookEx()» . Реверс игры . 3 апреля 2008 года . Проверено 1 сентября 2008 г.
  31. ^ «Внедрение DLL SetThreadContext» . 16 января 2007. Архивировано из оригинала 23 августа 2011 года . Проверено 1 сентября 2008 г.
  32. ^ Бен Ботто (6 сентября 2008 г.). «DLL-инжектор» . Архивировано из оригинала 7 февраля 2009 года . Проверено 1 сентября 2008 г.
  33. ^ «Небезопасная загрузка библиотеки может привести к удаленному выполнению кода» . Майкрософт . 10 июня 2011 года . Проверено 20 апреля 2016 г.
  34. ^ «Безопасная загрузка библиотек для предотвращения атак с предварительной загрузкой DLL» . Майкрософт . 10 июня 2011 года . Проверено 8 августа 2012 г.
  35. ^ «Рекомендации Microsoft по безопасности: небезопасная загрузка библиотеки может привести к удаленному выполнению кода» . Майкрософт . 10 июня 2011 года . Проверено 20 апреля 2016 г.
  36. ^ Николя Фаллиер (26 сентября 2010 г.). «Заражение Stuxnet проектов Step 7» . Симантек.
  37. ^ Линус Торвальдс ; Дэвид Энгель; Эрик Янгдейл; Питер Макдональд; Хунцзю Лу; Ларс Вирзениус; Митч Д'Суза (14 марта 1998 г.). «ld.so/ld-linux.so – динамический компоновщик/загрузчик» . Справочные страницы UNIX . Архивировано из оригинала 6 февраля 2009 года . Проверено 31 августа 2008 г.
  38. ^ «Параметры генерации кода» . Использование коллекции компиляторов GNU (GCC) . Фонд свободного программного обеспечения . Проверено 31 августа 2008 г. -fpic Сгенерируйте позиционно-независимый код (PIC), подходящий для использования в общей библиотеке, если она поддерживается целевой машиной. кв.кв.
  39. ^ «Параметры ссылки» . Использование коллекции компиляторов GNU (GCC) . Фонд свободного программного обеспечения . Проверено 31 августа 2008 г. -shared Создайте общий объект, который затем можно будет связать с другими объектами для формирования исполняемого файла. кв.кв.
  40. ^ «Трюк с LD_PRELOAD» . Питер Голдсборо . Проверено 17 мая 2017 г.
  41. ^ Григорий Шпитальник (12 февраля 2009 г.). «Внедрение кода в работающее приложение Linux» . Код проекта . Проверено 18 ноября 2010 г.
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: e2d6e3db038e70474d1070d6b52c5cbc__1722005460
URL1:https://arc.ask3.ru/arc/aa/e2/bc/e2d6e3db038e70474d1070d6b52c5cbc.html
Заголовок, (Title) документа по адресу, URL1:
DLL injection - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)