Skip to content

Code Libraries

A code library is a collection of pre-written code that software developers can use. There's a couple of different types but usually "libraries" refer to static or dynamic libraries.

Types

  • Standard Libraries: Built into a language (e.g., stdlib.h in C).
  • Third-party Libraries: Created by the community or companies (e.g., Boost in C++, NumPy in Python).
  • Static vs. Dynamic:
    • Static libraries are linked at compile time.
    • Dynamic/shared libraries are linked at runtime (e.g., .dll on Windows, .so on Linux).

Static vs. Dynamic

Feature Static Library Dynamic Link Library
Windows File Extension .lib .dll
Linking Time Compile/Link time Run time (Load time or dynamically)
Loaded Into Binary Yes (copied into .exe) No (separate file, loaded at runtime)
Portability Self-contained Needs the .dll at runtime
Memory Sharing Each app gets its own copy Can be shared across processes
Size of Final Binary Larger Smaller
Update behavior Requires recompiling the app Can update DLL without recompiling

Static Libraries

Static libraries are archives of compiled object files (.obj) that are linked directly into the executable at compile/link time. Once linked, the executable contains all the necessary code and does not need the .lib file at runtime.

Advantages:

  • Self-contained: All code is in one binary.
  • No runtime dependencies: No external .dll to worry about.
  • Better performance: Slightly faster startup (no runtime linking).

Disadvantages:

  • Larger executables: Because all library code is copied into each binary.
  • Harder to update: Updating the library requires recompiling all apps using it.
  • Redundant memory usage: Each app using the library gets its own copy in memory.

The Microsoft docs describe a DLL as "a library that contains code and data that can be used by more than one program at the same time."

Reading up on COM objects might clear up things if you're wondering about the history behind DLL's and how they came to be what they are today.

DLLs are used as one of the core functionalities behind application execution in Windows. From the Windows documentation, "The use of DLLs helps promote modularization of code, code reuse, efficient memory usage, and reduced disk space. So, the operating system and the programs load faster, run faster, and take less disk space on the computer."

When a DLL is loaded as a function in a program, the DLL is assigned as a dependency. Since a program is dependent on a DLL, attackers can target the DLLs rather than the applications to control some aspect of execution or functionality.

DLLs are created no different than any other project/application; they only require slight syntax modification to work. Below is an example of a DLL from the Visual C++ Win32 Dynamic-Link Library project:

#include "stdafx.h"
#define EXPORTING_DLL
#include "sampleDLL.h"
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved
)
{
    return TRUE;
}
void HelloWorld()
{
    MessageBox( NULL, TEXT("Hello World"), TEXT("In a DLL"), MB_OK);
}

Below is the header file for the DLL; it will define what functions are imported and exported:

1
2
3
4
5
6
7
8
#ifndef INDLL_H
    #define INDLL_H
    #ifdef EXPORTING_DLL
        extern __declspec(dllexport) void HelloWorld();
    #else
        extern __declspec(dllimport) void HelloWorld();
    #endif
#endif

How are they used by an application?

load-time dynamic linking:

When loaded using load-time dynamic linking, explicit calls to the DLL functions are made from the application. You can only achieve this type of linking by providing a header (.h) and import library (.lib) file. Below is an example of calling an exported DLL function from an application.

1
2
3
4
5
6
7
#include "stdafx.h"
#include "sampleDLL.h"
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HelloWorld();
    return 0;
}

run-time dynamic linking:

When loaded using run-time dynamic linking, a separate function (LoadLibrary or LoadLibraryEx) is used to load the DLL at run time. Once loaded, you need to use GetProcAddress to identify the exported DLL function to call. Below is an example of loading and importing a DLL function in an application.

...
typedef VOID (*DLLPROC) (LPTSTR);
...
HINSTANCE hinstDLL;
DLLPROC HelloWorld;
BOOL fFreeDLL;
hinstDLL = LoadLibrary("sampleDLL.dll");
if (hinstDLL != NULL)
{
    HelloWorld = (DLLPROC) GetProcAddress(hinstDLL, "HelloWorld");
    if (HelloWorld != NULL)
        (HelloWorld);
    fFreeDLL = FreeLibrary(hinstDLL);
}
...