When you start a program on your Windows XP computer, a process is created and several DLLs (Dynamic Link Libraries) are loaded into the process.
Some DLLs are “system” DLLs, such as Kernel32.dll, GDI32.dll, User32.dll.
These DLLs are loaded early in the process start time, because they provide basic operating system functionality, such as input/output, graphics, memory functions.
Each process has a 4 Gigabyte (2 ^ 32) address space, and DLLs are loaded into this address space starting at a particular base address, with a range extending to the size required for that DLL.
If the same DLL is loaded into multiple processes, and it has the same base address, then the entire DLL loaded range is the same for each of these processes and so each process can share the same physical mapping (see Global Descriptor Table)
However, if the DLL is loaded at different base addresses in some processes than others, then the DLL code needs to be modified (rebased) before it is used by the process. This means the same physical memory can not be used, and thus more physical memory (or paged memory) needs to be used.
These DLL code modifications consist of fixups for jumps within the code. For example, there might be a jump instruction embedded in the DLL code. If it’s a relative jump (i.e. jump 10 bytes back), then it doesn’t have to be patched. If it’s an absolute jump (jump to 0x12345678) then it needs to be patched. See also http://en.wikipedia.org/wiki/Import_Address_Table
When you create a DLL, there is a default base address that is in the DLL header. You can examine this default base address for any DLL:
On WinXP SP2, Start->Visual Studio 2005->Visual Studio Tools->Visual Studio command prompt
D:\>link /dump /headers c:\windows\system32\kernel32.dll | more
Dump of file c:\windows\system32\kernel32.dll
PE signature found
File Type: DLL
FILE HEADER VALUES
14C machine (x86)
4 number of sections
46239BD5 time date stamp Mon Apr 16 08:52:53 2007
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
Line numbers stripped
32 bit word machine
OPTIONAL HEADER VALUES
10B magic # (PE32)
7.10 linker version
82200 size of code
70000 size of initialized data
0 size of uninitialized data
B5AE entry point (7C80B5AE)
1000 base of code
7F000 base of data
7C800000 image base (7C800000 to 7C8F4FFF)
1000 section alignment
200 file alignment
5.01 operating system version
5.01 image version
4.00 subsystem version
0 Win32 version
F5000 size of image
400 size of headers
3 subsystem (Windows CUI)
0 DLL characteristics
40000 size of stack reserve
1000 size of stack commit
100000 size of heap reserve
1000 size of heap commit
0 loader flags
D:\>link /dump /exports c:\windows\system32\kernel32.dll | find /i "createfile"
80 4F 00001A24 CreateFileA
81 50 0000945C CreateFileMappingA
82 51 0000938E CreateFileMappingW
83 52 00010760 CreateFileW
569 238 00064F4D LZCreateFileW
The image base for Kernel32.dll is 0x7c800000
The address of CreateFileW is the sum of the image base (0x7c800000) and the relative address 10760 : 0x7c810760. As you can see from the CreateFile documentation, this API is used to create or open a file. (It also shows that this API is implemented in kernel32.dll.)
A virus writer can depend on this address (0x7c810760) being the same for every Windows XP SP2 machine. Thus a virus can just call code at that address to create or open a file on your machine.
Vista varies the starting address of the system DLLs so that CreateFile will be mapped to a different image base address each time the machine is rebooted, causing virus writers grief.
We’ll talk about how to find the number of modules that are rebased on your system next time.
Find all statically linked libraries required before your process can start
How to log application API calls using import module addresses
What external code does your EXE depend on?