A DLL is an executable file that does not run alone. It exports functions that are used by other applications.
Run a DLL
To run a DLL, use rundll32.exe as follows:
Usage: rundll32 some.dll,export
Base address and rebasing
Each application has its own physical address space (i.e. when two processes will refer to 0x401064, they will point to different memory locations as they are in different physical address spaces).
In a process, the application (*.exe) will share the same address space as its components (e.g. DLL). In this case, if a the executable and one of its DLL refer to 0x401AFF, it will point to the same location.
The base address is the preferred address for an PE or a DLL. The most common base address are as follows:
|Type||Common preferred base address|
|Applications (.exe files)||0x00400000|
|Microsoft Visual C/C++||0x10000000|
|Microsoft Visual Basic||0x11000000.|
|Borland C++, Watcom C/C++, LCC-Win32||0x00400000|
The base address can be identified with PEView or CFF Explorer (Optional Header > ImageBase). In the below example, the base address for the DLL is 0x10000000.
Rebasing is what happens when a module is not loaded at its preferred base addess. The section that specifies the relocation information is .RELOC.
During runtime, a DLL can be loaded at a different address than its preferred address. To see at which address a DLL is loaded, you can use the OllyDbg#Memory_map in OllyDbg.
In the below example, the malware we're analyzing loads 3 DLLs that all have the same base address (0x10000000). As shown on the below screenshot, only DLL1.dll has been loaded at its preferred address (DLL2.dll and DLL3.dll have been rebased).
Analysis in IDA Pro
In IDA Pro, you will need to manually load the DLL and specify a new Image base address. Read more here.
Debug a DLL in OllyDbg
Refer to this section.
DllMain entry point
An optional entry point into a dynamic-link library (DLL). When the system starts or terminates a process or thread, it calls the entry-point function for each loaded DLL using the first thread of the process. The system also calls the entry-point function for a DLL when it is loaded or unloaded using the LoadLibrary and FreeLibrary functions.
BOOL WINAPI DllMain( _In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved );
- hinstDLL [in]
- A handle to the DLL module. The value is the base address of the DLL. The HINSTANCE of a DLL is the same as the HMODULE of the DLL, so hinstDLL can be used in calls to functions that require a module handle.
- fdwReason [in]
- The reason code that indicates why the DLL entry-point function is being called. This parameter can be one of the following values.
Value Meaning DLL_PROCESS_ATTACH
The DLL is being loaded into the virtual address space of the current process as a result of the process starting up or as a result of a call to LoadLibrary. DLLs can use this opportunity to initialize any instance data or to use the TlsAlloc function to allocate a thread local storage (TLS) index.
The lpReserved parameter indicates whether the DLL is being loaded statically or dynamically.
The DLL is being unloaded from the virtual address space of the calling process because it was loaded unsuccessfully or the reference count has reached zero (the processes has either terminated or called FreeLibrary one time for each time it called LoadLibrary).
The lpReserved parameter indicates whether the DLL is being unloaded as a result of a FreeLibrary call, a failure to load, or process termination.
The DLL can use this opportunity to call the TlsFree function to free any TLS indices allocated by using TlsAlloc and to free any thread local data.
Note that the thread that receives the DLL_PROCESS_DETACH notification is not necessarily the same thread that received the DLL_PROCESS_ATTACH notification.
The current process is creating a new thread. When this occurs, the system calls the entry-point function of all DLLs currently attached to the process. The call is made in the context of the new thread. DLLs can use this opportunity to initialize a TLS slot for the thread. A thread calling the DLL entry-point function with DLL_PROCESS_ATTACH does not call the DLL entry-point function with DLL_THREAD_ATTACH.
Note that a DLL's entry-point function is called with this value only by threads created after the DLL is loaded by the process. When a DLL is loaded using LoadLibrary, existing threads do not call the entry-point function of the newly loaded DLL.
A thread is exiting cleanly. If the DLL has stored a pointer to allocated memory in a TLS slot, it should use this opportunity to free the memory. The system calls the entry-point function of all currently loaded DLLs with this value. The call is made in the context of the exiting thread.
- lpvReserved [in]
- If fdwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-NULL for static loads.
- If fdwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if FreeLibrary has been called or the DLL load failed and non-NULL if the process is terminating.
When the system calls the DllMain function with the DLL_PROCESS_ATTACH value, the function returns TRUE if it succeeds or FALSE if initialization fails. If the return value is FALSE when DllMain is called because the process uses the LoadLibrary function, LoadLibrary returns NULL. (The system immediately calls your entry-point function with DLL_PROCESS_DETACH and unloads the DLL.) If the return value is FALSE when DllMain is called during process initialization, the process terminates with an error. To get extended error information, call GetLastError.
When the system calls the DllMain function with any value other than DLL_PROCESS_ATTACH, the return value is ignored.