DLL injection

Last updated

In computer programming, DLL injection is a technique used for running code within the address space of another process by forcing it to load a dynamic-link library. [1] DLL injection is often used by external programs to influence the behavior of another program in a way its authors did not anticipate or intend. [1] [2] [3] For example, the injected code could hook system function calls, [4] [5] or read the contents of password textboxes, which cannot be done the usual way. [6] A program used to inject arbitrary code into arbitrary processes is called a DLL injector.

Contents

Approaches on Microsoft Windows

There are multiple ways on Microsoft Windows to force a process to load and execute code in a DLL that the authors did not intend:

Approaches on Unix-like systems

On Unix-like operating systems with the dynamic linker based on ld.so (on BSD) and ld-linux.so (on Linux), arbitrary libraries can be linked to a new process by giving the library's pathname in the LD_PRELOAD environment variable, that can be set globally or individually for a single process. [37]

For example, on a Linux system, this command launches the command "prog" with the shared library from file "test.so" linked into it at the launchtime:

LD_PRELOAD="./test.so"prog 

Such a library can be created in the same way as other shared objects. With GCC, this involves compiling the source file containing the new globals to be linked, with the -fpic or -fPIC option, [38] and linking with the -shared option. [39] The library has access to external symbols declared in the program like any other library.

On macOS, the following command launches the command "prog" with the shared library from file "test.dylib" linked into it at the launchtime: [40]

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

It is also possible to use debugger-based techniques on Unix-like systems. [41]

Sample code

Copying a LoadLibrary-loaded DLL to a remote process

As there is no LoadLibrary() call to load a DLL into a foreign process you have to copy a locally loaded DLL into remotely allocated memory. The following commented code shows how to do that.

#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)#endifusingnamespacestd;usingXHANDLE=unique_ptr<void,decltype([](void*h){h&&h!=INVALID_HANDLE_VALUE&&CloseHandle((HANDLE)h);})>;usingXHMODULE=unique_ptr<remove_reference_t<decltype(*HMODULE())>,decltype([](HMODULEhm){hm&&FreeLibrary(hm);})>;MODULEENTRY32WgetModuleDescription(HMODULEhmModule);size_tmaxReadableRange(void*pRegion);stringgetAbsolutePathA(charconst*fileName,charconst*err);DWORDdumbParseDWORD(wchar_tconst*str);wstringgetAbsolutePath(wchar_tconst*makeAbsolute,charconst*errStr);[[noreturn]]voidthrowSysErr(charconst*str);constexprwchar_tconst*LOADER_DLL_NAME=L"loaderDll.dll";constexprcharconst*LOADER_THREAD_PROC="loadLibraryThread";intwmain(intargc,wchar_t**argv){try{if(argc<3)returnEXIT_FAILURE;wchar_tconst*processId=argv[1],*remoteLoadedDll=argv[2],*initData=argc>=4?argv[3]:L"";DWORDdwProcessId=dumbParseDWORD(processId);XHANDLExhProcess(OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId));if(!xhProcess.get())throwSysErr("can't open remote process with unlimited access");XHMODULExhmLocalLoader;MODULEENTRY32WmeLocalLoader;for(;;){xhmLocalLoader.reset(LoadLibraryW(LOADER_DLL_NAME));if(!xhmLocalLoader.get())throwSysErr("can't locally load loader DLL");// get module starting address and sizemeLocalLoader=getModuleDescription((HMODULE)xhmLocalLoader.get());// try to allocate memory range in the foreign process with the same size the DLL in our process occupiesif(VirtualAllocEx(xhProcess.get(),meLocalLoader.modBaseAddr,meLocalLoader.modBaseSize,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE))break;// allocation failed, free libraryxhmLocalLoader.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_ROUTINEloaderThreadProc=(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 processif(SIZE_Tcopied;!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 DLLwstringdata(getAbsolutePath(remoteLoadedDll,"can't get absolute path to DLL to be remotely loaded"));data+=L'\0';data+=initData;data+=L'\0';size_tdataSize=data.size()*sizeof(wchar_t);autoinitStrErr=[](){throwSysErr("failed to copy initialization data to loader DLL");};void*remoteData;// remotely allocate memory large enough to hold at least our both stringsif(!(remoteData=VirtualAllocEx(xhProcess.get(),nullptr,dataSize,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE)))initStrErr();// write our both strings to remote memoryif(SIZE_Tcopied;!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 stringsXHANDLExhRemoteInitThread(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 itselfif(WaitForSingleObject(xhRemoteInitThread.get(),INFINITE)==WAIT_FAILED)throwSysErr("can't wait for remote initialization thread");DWORDdwInitThreadExitCode;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)throwsystem_error((int)dwInitThreadExitCode,system_category(),"LoadLibrary() error in remote loader dll");}catch(exceptionconst&se){cout<<se.what()<<endl;}}MODULEENTRY32WgetModuleDescription(HMODULEhmModule){// returns the absolute path to for a given module handleautogetModulePath=[](HMODULEhm,charconst*err)->wstring{wchar_tmodulePath[MAX_PATH];if(DWORDdwRet=GetModuleFileNameW(hm,modulePath,MAX_PATH);!dwRet||dwRet>=MAX_PATH)throwSysErr(err);returnmodulePath;};// local DLL's module pathwstringmoduleAbsolute(getModulePath(hmModule,"can't get absolute path for local loader DLL"));XHANDLExhToolHelp(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId()));autotoolHelpErr=[](){throwSysErr("can't list modules in injecting process");};if(xhToolHelp.get()==INVALID_HANDLE_VALUE)toolHelpErr();MODULEENTRY32Wme;me.dwSize=sizeofme;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 matchif(getModulePath(me.hModule,"can't get absolute path for toolhelp-enumerated DLL name")==moduleAbsolute)returnme;me.dwSize=sizeofme;if(!Module32NextW(xhToolHelp.get(),&me))toolHelpErr();}}[[noreturn]]voidthrowSysErr(charconst*str){throwsystem_error((int)GetLastError(),system_category(),str);}DWORDdumbParseDWORD(wchar_tconst*str){// idiot's from_chars because there's no from_chars for unicode charactersDWORDdwRet=0;while(*str)dwRet=dwRet*10+(unsignedchar)(*str++-L'0');returndwRet;}wstringgetAbsolutePath(wchar_tconst*makeAbsolute,charconst*errStr){// get absolute path of a given relative pathwstringpath(MAX_PATH,L'\0');DWORDdwLength;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 errorelseif(dwLength>=MAX_PATH)throwinvalid_argument(errStr);path.resize(dwLength);returnpath;}

The main issue solved here is that a locally loaded DLL copied to a remote process must occupy the same addresses as in the injecting process. The above code does this by allocating memory for the same address range as occupied before in the injecting process. If this fails the DLL is locally freed, the former address range is marked as reserved, and the LoadLibrary() call is tried again. By reserving the former address range the code prevents that the next LoadLibrary() attempt will assign the same address range as used before.

The main drawback with that approach is that the DLL copied into the foreign process is that there aren't any other DLL library dependencies of that DLL loaded into the foreign address space or pointers, f.e. function calls, to DLLs loaded by the foreign process are adjusted according to the dependencies of the copied DLL. Luckily DLLs usually have preferred loading addresses which are honored by the kernel's loader. Some DLLs like kernel32.dll are reliably loaded in the early beginning when the process address space is occupied by the executable image and its depending DLLs. These normally have reliable and non-conflicting addresses. So the copied DLL can use any kernel32.dll calls, f.e. to load another DLL with full advantages of a locally loaded DLL, i.e. having all relative library-dependencies. The path to that DLL is copied to the foreign address space and given as a void-parameter to the thread-function. The above implementation also allows to have additional parameters, which are passed to the remotely copied DLL after the string with the DLL to remotely loaded to passed to that DLL.

The following code is the source of the remotely copied loader DLL which only does kernel32.dll calls:

#include<Windows.h>#include<atomic>usingnamespacestd;BOOLAPIENTRYDllMain(HMODULEhModule,DWORDul_reason_for_call,LPVOIDlpReserved){returnTRUE;}DWORDWINAPIloadLibraryThread(LPVOIDlpvThreadParam);// 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#endifDWORDWINAPIloadLibraryThread(LPVOIDlpvThreadParam){// 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 fastatomic_wchar_tconst// 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 parameterswhile(*data++);HANDLEhOutboundEvent;// create named event to notify the remote DLL that data has already copied // necessary because the remote DLL execution begins directly after LoadLibrary()Sif(!(hOutboundEvent=CreateEventA(nullptr,FALSE,FALSE,"nasty hackers")))returnGetLastError();// size of the paramers given to the DLLsize_tdataSize=0;while(data[dataSize++]);if(dataSize>=MAX_PATH)returnERROR_INVALID_PARAMETER;// clean LoadLibrary() with all DLL-dependenciesHMODULEhm=LoadLibraryW((wchar_t*)libPath);if(!hm)returnGetLastError();// get address of parameters export from the loaded DLLwchar_tvolatile(&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)returnNO_ERROR;// copy parameters to the DLLfor(size_ti=0;i!=dataSize;initData[i]=data[i],++i);// notify that parameters availableif(!SetEvent(hOutboundEvent))returnGetLastError();returnNO_ERROR;}

The last code shows an example of a DLL loaded by the loader DLL which prints the parameters to a file.

#include<Windows.h>#include<fstream>#include<atomic>usingnamespacestd;#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#endifusingnamespacestd;DWORDWINAPImyThread(LPVOIDlpvThreadParam);BOOLAPIENTRYDllMain(HMODULEhModule,DWORDdwReason,LPVOIDlpReserved){switch(dwReason){caseDLL_PROCESS_ATTACH:// create thread since there is no export called from the loader DLLCreateThread(nullptr,0,myThread,nullptr,0,nullptr);default:break;}returnTRUE;}extern"C"__declspec(dllexport)wchar_tinitData[MAX_PATH]={0};DWORDWINAPImyThread(LPVOIDlpvThreadParam){// 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 oneif(WaitForSingleObject(CreateEventA(nullptr,FALSE,FALSE,"nasty hackers"),INFINITE)!=WAIT_OBJECT_0)return0;// write parameters in a file to test function// the following code doesn't work when the DLL is non-statically linked for unknown reasonswofstreamwofs;wofs.open("c:\\Users\\xxx\\test.txt",ofstream::out|ofstream::trunc);wofs<<initData<<endl;return0;}

One important fact is that there are no exports called from the loader DLL, but instead all initialization is done from DllMain. The only export is that of initData, which receives the parameters given by the injecting process through the loader DLL. And one must be aware that the thread created from a DllMain-function isn't scheduled until after its DLL_THREAD_ATTACH-function has succeeded. So there may not be any synchronization from inside DllMain with the created thread.

Related Research Articles

In computing, DLL Hell is a term for the complications that arise when one works with dynamic-link libraries (DLLs) used with Microsoft Windows operating systems, particularly legacy 16-bit editions, which all run in a single memory space.

A shared library or shared object is a computer file that contains executable code designed to be used by multiple computer programs or other libraries at runtime.

The Portable Executable (PE) format is a file format for executables, object code, DLLs and others used in 32-bit and 64-bit versions of Windows operating systems, and in UEFI environments. The PE format is a data structure that encapsulates the information necessary for the Windows OS loader to manage the wrapped executable code. This includes dynamic library references for linking, API export and import tables, resource management data and thread-local storage (TLS) data. On NT operating systems, the PE format is used for EXE, DLL, SYS, MUI and other file types. The Unified Extensible Firmware Interface (UEFI) specification states that PE is the standard executable format in EFI environments.

<span class="mw-page-title-main">Library (computing)</span> Collection of resources used to develop a computer program

In computer science, a library is a collection of read-only resources that is leveraged during software development to implement a computer program.

In computing, a loadable kernel module (LKM) is an object file that contains code to extend the running kernel, or so-called base kernel, of an operating system. LKMs are typically used to add support for new hardware and/or filesystems, or for adding system calls. When the functionality provided by an LKM is no longer required, it can be unloaded in order to free memory and other resources.

In computer systems a loader is the part of an operating system that is responsible for loading programs and libraries. It is one of the essential stages in the process of starting a program, as it places programs into memory and prepares them for execution. Loading a program involves either memory-mapping or copying the contents of the executable file containing the program instructions into memory, and then carrying out other required preparatory tasks to prepare the executable for running. Once loading is complete, the operating system starts the program by passing control to the loaded program code.

In computing, position-independent code (PIC) or position-independent executable (PIE) is a body of machine code that, being placed somewhere in the primary memory, executes properly regardless of its absolute address. PIC is commonly used for shared libraries, so that the same library code can be loaded at a location in each program's address space where it does not overlap with other memory in use by, for example, other shared libraries. PIC was also used on older computer systems that lacked an MMU, so that the operating system could keep applications away from each other even within the single address space of an MMU-less system.

<span class="mw-page-title-main">Multilingual User Interface</span> Integrated localization feature in modern Windows systems

Multilingual User Interface (MUI) enables the localization of the user interface of an application.

In computer science, a static library or statically linked library is a set of routines, external functions and variables which are resolved in a caller at compile-time and copied into a target application by a compiler, linker, or binder, producing an object file and a stand-alone executable. This executable and the process of compiling it are both known as a static build of the program. Historically, libraries could only be static. Static libraries are either merged with other static libraries and object files during building/linking to form a single executable or loaded at run-time into the address space of their corresponding executable at a static memory offset determined at compile-time/link-time.

A dynamic-link library (DLL) is a shared library in the Microsoft Windows or OS/2 operating system.

In computer programming, the term hooking covers a range of techniques used to alter or augment the behaviour of an operating system, of applications, or of other software components by intercepting function calls or messages or events passed between software components. Code that handles such intercepted function calls, events or messages is called a hook.

In computing, a dynamic linker is the part of an operating system that loads and links the shared libraries needed by an executable when it is executed, by copying the content of libraries from persistent storage to RAM, filling jump tables and relocating pointers. The specific operating system and executable format determine how the dynamic linker functions and how it is implemented.

ntoskrnl.exe, also known as the kernel image, contains the kernel and executive layers of the Microsoft Windows NT kernel, and is responsible for hardware abstraction, process handling, and memory management. In addition to the kernel and executive layers, it contains the cache manager, security reference monitor, memory manager, scheduler (Dispatcher), and blue screen of death.

Platform Invocation Services, commonly referred to as P/Invoke, is a feature of Common Language Infrastructure implementations, like Microsoft's Common Language Runtime, that enables managed code to call native code.

The booting process of Microsoft Windows varies between different releases.

Dynamic loading is a mechanism by which a computer program can, at run time, load a library into memory, retrieve the addresses of functions and variables contained in the library, execute those functions or access those variables, and unload the library from memory. It is one of the 3 mechanisms by which a computer program can use some other software; the other two are static linking and dynamic linking. Unlike static linking and dynamic linking, dynamic loading allows a computer program to start up in the absence of these libraries, to discover available libraries, and to potentially gain additional functionality.

Component Object Model (COM) is a binary-interface standard for software components introduced by Microsoft in 1993. It is used to enable inter-process communication (IPC) object creation in a large range of programming languages. COM is the basis for several other Microsoft technologies and frameworks, including OLE, OLE Automation, Browser Helper Object, ActiveX, COM+, DCOM, the Windows shell, DirectX, UMDF and Windows Runtime.

In computing on Microsoft platforms, WoW64 is a subsystem of the Windows operating system capable of running 32-bit applications on 64-bit Windows. It is included in all 64-bit versions of Windows, except in Windows Server Server Core where it is an optional component, and Windows Nano Server where it is not included. WoW64 aims to take care of many of the differences between 32-bit Windows and 64-bit Windows, particularly involving structural changes to Windows itself.

<span class="mw-page-title-main">Architecture of Windows 9x</span>

The Windows 9x series of operating systems refers to the monolithic kernel which powers these operating systems. The basic code is similar in function to MS-DOS. As a 16-/32-bit hybrid, it requires support from MS-DOS to operate.

<span class="mw-page-title-main">Longene</span> Linux distribution

Longene is a Linux-based operating system kernel intended to be binary compatible with application software and device drivers made for Microsoft Windows and Linux. As of 1.0-rc2, it consists of a Linux kernel module implementing aspects of the Windows kernel and a modified Wine distribution designed to take advantage of the more native interface. Longene is written in the C programming language and is free and open source software. It is licensed under the terms of the GNU General Public License version 2 (GPLv2).

References

  1. 1 2 James Shewmaker (2006). "Analyzing DLL Injection" (PDF). GSM Presentation. Bluenotch. Archived from the original (PDF) on December 3, 2008. Retrieved August 31, 2008.
  2. 1 2 Iczelion (August 2002). "Tutorial 24: Windows Hooks". Iczelion's Win32 Assembly Homepage. Archived from the original on August 1, 2008. Retrieved August 31, 2008.
  3. Rocky Pulley (May 19, 2005). "Extending Task Manager with DLL Injection". CodeProject. Archived from the original on February 6, 2009. Retrieved September 1, 2008.
  4. 1 2 Nasser R. Rowhani (October 23, 2003). "DLL Injection and function interception tutorial". CodeProject. Archived from the original on April 15, 2018. Retrieved August 31, 2008.
  5. 1 2 3 Ivo Ivanov (December 2, 2002). "API hooking revealed". CodeProject. Retrieved August 31, 2008.
  6. 1 2 3 4 Robert Kuster (August 20, 2003). "Three Ways to Inject Your Code into Another Process". CodeProject. Retrieved August 31, 2008.
  7. "Working with the AppInit_DLLs registry value". Microsoft Help and Support. Microsoft. November 21, 2006. Retrieved August 31, 2008.
  8. Raymond Chen (December 13, 2007). "AppInit_DLLs should be renamed Deadlock_Or_Crash_Randomly_DLLs". The Old New Thing. Microsoft. Retrieved August 31, 2008.
  9. "dllmain.c". ReactOS. ReactOS Foundation. July 8, 2008. Retrieved August 31, 2008.[ permanent dead link ]
  10. AppInit_DLLs in Windows 7 and Windows Server 2008 R2
  11. "AppInit DLLs and Secure Boot". MSDN. Retrieved March 29, 2016.
  12. "'AtomBombing' Microsoft Windows Via Code Injection". Dark Reading. Retrieved April 20, 2017.
  13. 1 2 3 4 Trent Waddington. "InjectDLL". Archived from the original on December 30, 2019. Retrieved August 31, 2008.
  14. "Dll Injection". DreamInCode.net. MediaGroup1. May 4, 2006. Archived from the original on September 2, 2008. Retrieved August 31, 2008.
  15. Greg Jenkins (November 2007). "DLL Injection Framework". Ring3 Circus. WordPress. Archived from the original on June 28, 2020. Retrieved August 31, 2008.
  16. Drew Benton (August 17, 2007). "A More Complete DLL Injection Solution Using CreateRemoteThread". CodeProject. Retrieved September 1, 2008.
  17. "CreateProcess". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  18. "PROCESS_INFORMATION". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  19. "GetWindowThreadProcessId Function". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  20. "EnumProcesses". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  21. "GetModuleBaseName". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  22. "VirtualAllocEx". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  23. "WriteProcessMemory". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  24. "Outpost Bypassing Self-Protection via Advanced DLL injection with handle stealing Vulnerability". Matousec. December 1, 2006. Archived from the original on February 6, 2009. Retrieved August 31, 2008.
  25. "CreateRemoteThread". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  26. "LoadLibrary". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  27. 1 2 "DllMain". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  28. "SetWindowsHookEx Function". Platform SDK for Windows XP SP2. Microsoft. Retrieved August 31, 2008.
  29. "AppInit_DLLs Registry Value and Windows 95". Microsoft Help and Support. Microsoft. March 1, 2005. Retrieved August 31, 2008.
  30. "Dll Injection using SetWindowsHookEx() Method". Game Reversal. April 3, 2008. Retrieved September 1, 2008.
  31. "SetThreadContext DLL Injection". January 16, 2007. Archived from the original on August 23, 2011. Retrieved September 1, 2008.
  32. Ben Botto (September 6, 2008). "DLL Injector". Archived from the original on February 7, 2009. Retrieved September 1, 2008.
  33. "Insecure Library Loading Could Allow Remote Code Execution". Microsoft. June 10, 2011. Retrieved April 20, 2016.
  34. "Secure loading of libraries to prevent DLL preloading attacks". Microsoft. June 10, 2011. Retrieved August 8, 2012.
  35. "Microsoft Security Advisory: Insecure library loading could allow remote code execution". Microsoft. June 10, 2011. Retrieved April 20, 2016.
  36. Nicolas Falliere (September 26, 2010). "Stuxnet Infection of Step 7 Projects". Symantec.
  37. Linus Torvalds; David Engel; Eric Youngdale; Peter MacDonald; Hongjiu Lu; Lars Wirzenius; Mitch D'Souza (March 14, 1998). "ld.so/ld-linux.so – dynamic linker/loader". UNIX man pages. Archived from the original on February 6, 2009. Retrieved August 31, 2008.
  38. "Code Gen Options". Using the GNU Compiler Collection (GCC). Free Software Foundation. Retrieved August 31, 2008. -fpic Generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine. sqq.
  39. "Link Options". Using the GNU Compiler Collection (GCC). Free Software Foundation. Retrieved August 31, 2008. -shared Produce a shared object which can then be linked with other objects to form an executable. sqq.
  40. "The LD_PRELOAD trick". Peter Goldsborough. Retrieved May 17, 2017.
  41. Gregory Shpitalnik (February 12, 2009). "Code Injection into Running Linux Application". Code Project. Retrieved November 18, 2010.