Introduction

Both .exe and .dll files use the Portable Executable format, but they are used differently by Windows. An .exe file is normally created to start a process, whereas a .dll file is created to be loaded into an existing process.

For example, double-clicking notepad.exe starts a new process. Double-clicking kernel32.dll does not start a normal program because DLLs are not designed to be launched directly in the same way as EXE files. Instead, a DLL is loaded by another executable image, after which the process can call the functions exported by that DLL.

This module introduces dynamic-link libraries, exported functions, DLL entry points, run-time dynamic linking, and the WinAPIs commonly used to load DLLs and resolve exported functions.

What is a DLL?

A Dynamic-Link Library, or DLL, is a shared library that can contain executable code, data, and resources. Multiple applications can use the same DLL instead of each application carrying its own copy of the same functionality.

For example, a program that calls CreateFileW does not need to implement file creation itself. It calls the WinAPI, and Windows resolves the call through the DLLs that expose or implement that functionality. In many Win32 applications, common DLLs such as ntdll.dll, kernel32.dll, KernelBase.dll, user32.dll, advapi32.dll, and others are mapped into the process address space.

Unlike an EXE file, a DLL does not usually create a new process on its own. A DLL must first be loaded into a process, and then its exported functions can be called by code running inside that process.

The image below of Process Explorer, shows several DLLs loaded by the explorer.exe process.

Explorer-DLLs

When a process loads a DLL, Windows maps that DLL into the virtual address space of the process. The DLL's code can then run in the context of the process that loaded it. Therefore, if a DLL allocates memory, opens handles, creates threads, or accesses process memory, it is doing so from within the context of the hosting process.

Why Use DLLs?

There are several reasons why DLLs are very often used in Windows:

  1. Code Reuse - A DLL can expose functionality that multiple programs can use. This avoids duplicating the same code in many different executables.
  2. Modularization - Applications can be split into separate components. For example, one DLL may handle networking, another may handle the user interface, and another may handle file parsing.
  3. Efficient Memory Usage - When multiple processes load the same DLL, Windows can share read-only image pages between them instead of keeping completely separate physical copies.
  4. Easier Updates - Updating a DLL can update functionality used by multiple applications, assuming the exported interface remains compatible.
  5. Plugin-Like Designs - Some applications load DLLs at runtime to add optional functionality, extensions, or third-party modules.

DLL Base Addresses

On Windows, the same system DLL may appear at the same virtual address across multiple processes. The image below shows kernel32.dll mapped at the same address (0x7fff9fad0000) in several running processes.