What are possible reasons for not mapping Win32 Portable Executable images at offset 0? - winapi

I've been looking into Window's PE format lately and I have noticed that in most examples,
people tend to set the ImageBase offset value in the optional header to something unreasonably high like 0x400000.
What could make it unfavorable not to map an image at offset 0x0?

First off, that's not a default of Windows or the PE file format, it is the default for the linker's /BASE option when you use it to link an EXE. The default for a DLL is 0x10000000.
Selecting /BASE:0 would be bad choice, no program can ever run at that base address. The first 64 KB of the address space is reserved and can never be mapped. Primarily to catch null pointer dereference bugs. And expanded to 64KB to catch pointer bugs in programs that started life in 16-bits and got recompiled to 32-bits.
Why 0x40000 and not 0x10000 is the default is a historical accident as well and goes back to at least Windows 95. Which reserved the first 4 megabytes of the address space for the "16-bit/MS-DOS Compatibility Arena". I don't remember much about it, Windows 9x had a very different 16-bit VM implementation from NT. You can read some more about it in this ancient KB article. It certainly isn't relevant anymore these days, a 64-bit OS will readily allocate heap memory in the space between 0x010000 and 0x400000.
There isn't any point in changing the /BASE option for an EXE. However, there's lots of point changing it for a DLL. They are much more effective if they don't overlap and thus don't have to be relocated, they won't take any space in the paging file and can be shared between processes. There's even an SDK tool for it so you can change it after building, rebase.exe

Practically, the impact of setting /BASE to 0 depends on the Address Space Layout Randomization (ASLR) setting of your image (which is also put by the Linker - /DYNAMICBASE:NO).
Should your image have /BASE:0 and ASLR is on (/DYNAMICBASE:YES), then your image will start and run because the loader will automatically load it at a "valid" address.
Should your image have /BASE:0 and ASLR is off (/DYNAMICBASE:NO), then your image will NOT start because the loader will NOT load it at the desired based address (which is, as explained above, unvalid/reserved).

If you map it to address 0 then that means the code expects to be running starting at address zero.
For the OS, address zero is NULL, which is an invalid address.
(Not "fundamentally", but for modern-day OSes, it is.)
Also, in general you don't want anything in the lower 16 MiB of memory (even virtual), for numerous reasons.
But what's the alternative? It has to be mapped somewhere, so they chose 0x400000... no particular reason for that particular address, probably. It was probably just handy.

Microsoft chose that address as the default starting address specified by the linker at which the PE file will be memory mapped. The linker assumes this address and and can optimize the executable with that assumption. When the file is memory mapped at that address the code can be run without needing to modify any internal offsets.
If for some reason the file cannot be loaded to that location (another exe/dll already loaded there) relocations will need to occur before the executable can run which will increase load times.
Lower memory addresses are usually assumed to contain low level system routines and are generally left alone. The only real requirement for the ImageBase address is that it is a multiple of 0x10000.
Recommended reading:
http://msdn.microsoft.com/en-us/library/ms809762.aspx

Related

What is there before ImageBase address in Virtual Address?

I know from the Microsoft documentation that the image base is set to 0x140000000 for 64-bit images and it is the base address where the executable file is first loaded into the memory.
So my questions are as follows
What comes before 0x140000000 address and starting of virtual address first page (0x0000000)
What does it mean by executable first loaded? Is it the entry point of the program (which is of course not the main function) or something else
What comes before 0x140000000 address and starting of virtual address first page (0x0000000)
Whatever happens to allocate there, like DLLs, file mappings, heap memory, or this memory can be free. The first page is always inaccessible.
What does it mean by executable first loaded? Is it the entry point of the program (which is of course not the main function) or something else
Loaded means mapped into memory. After it is mapped into memory, its imports are resolved, statically linked DLLs are mapped into memory, their entry points are executed, and only then it comes to the executable entry point. Executable entry point is not really the first function to execute from the executable if it has TLS callbacks.
I don't know the technical reason why the 64-bit default is so high, perhaps just to make sure your app does not have 32-bit pointer truncation bugs with data/code in the module? And it is important to note that this default comes from the Microsoft compiler, Windows itself will accept a lower value. The default for 32-bit applications is 0x00400000 and there are actual hardware and technical reasons for that.
The first page starting at 0 is off limits in most operating systems to prevent issues with de-referencing a NULL pointer. The first couple of megabytes might have BIOS/firmware or other legacy things mapped there.
By first loaded, it means the loader will map the file into memory starting at that address. First the MZ part (DOS header and stub code) and the PE header. After this comes the various sections listed in the PE header.
Most applications are using ASLR these days so the base address will be random and not the preferred address listed in the PE. ntdll and kernel32 are mapped before the exe so if you choose their base address you will also be relocated.

Low-level details on linking and loading of (PE) programs in Windows

Low-level details on linking and loading of (PE) programs in Windows.
I'm looking for an answer or tutorial that clarifies how a Windows program are linked and loaded into memory after it has been assembled.
Especially, I'm uncertain about the following points:
After the program is assembled, some instructions may reference memory within the .DATA section. How are these references translated, when the program is loaded into memory starting at some arbitrary address? Does RVA's and relative memory references take care of these issues (BaseOfCode and BaseOfData RVA-fields of the PE-header)?
Is the program always loaded at the address specified in ImageBase header field? What if a loaded (DLL) module specifies the same base?
First I'm going to answer your second question:
No, a module (being an exe or dll) is not allways loaded at the base address. This can happen for two reasons, either there is some other module already loaded and there is no space for loading it at the base address contained in the headers, or because of ASLR (Address Space Layout Randomization) which mean modules are loaded at random slots for exploit mitigation purposes.
To address the first question (it is related to the second one):
The way a memory location is refered to can be relative or absolute. Usually jumps and function calls are relative (though they can be absolute), which say: "go this many bytes from the current instruction pointer". Regardless of where the module is loaded, relative jumps and calls will work.
When it comes to addressing data, they are usually absolute references, that is, "access these 4-byte datum at this address". And a full virtual address is specified, not an RVA but a VA.
If a module is not loaded at its base address, absolute references will all be broken, they are no longer pointing to the correct place the linker assumed they should point to. Let's say the ImageBase is 0x04000000 and you have a variable at RVA 0x000000F4, the VA will be 0x040000F4. Now imagine the module is loaded not at its BaseAddress, but at 0x05000000, everything is moved 0x1000 bytes forward, so the VA of your variable is actually 0x050000F4, but the machine code that accessess the data still has the old address hardcoded, so the program is corrupted. In order to fix this, linkers store in the executable where these absolute references are, so they can be fixed by adding to them how much the executable has been displaced: the delta offset, the difference between where the image is loaded and the image base contained in the headers of the executable file. In this case it's 0x1000. This process is called Base Relocation and is performed at load time by the operating system: before the code starts executing.
Sometimes a module has no relocations, so it can't be loaded anywhere else but at its base address. See How do I determine if an EXE (or DLL) participate in ASLR, i.e. is relocatable?
For more information on ASLR: https://insights.sei.cmu.edu/cert/2014/02/differences-between-aslr-on-windows-and-linux.html
There is another way to move the executable in memory and still have it run correctly. There exists something called Position Independent Code. Code crafted in such a way that it will run anywhere in memory without the need for the loader to perform base relocations.
This is very common in Linux shared libraries and it is done addressing data relatively (access this data item at this distance from the instruction pointer).
To do this, in the x64 architecture there is RIP-relative addressing, in x86 a trick is used to emulate it: get the content of the instruction pointer and then calculate the VA of a variable by adding to it a constant offset.
This is very well explained here:
https://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html
I don't think PIC code is common in Windows, more often than not, Windows modules contain base relocations to fix absolute addresses when it is loaded somewhere else than its prefered base address, although I'm not exactly sure of this last paragraph so take it with a grain of salt.
More info:
http://opensecuritytraining.info/LifeOfBinaries.html
How are windows DLL actually shared? (a bit confusing because I didn't explain myself well when asking the question).
https://www.iecc.com/linker/
I hope I've helped :)

How to get relocated base address in PE Files?

I'm trying to make Simple PE Packer. My PE Viewer show me base address 0x40000000, but OllyDbg show me 0x01900400 or other address.
I guess that it is address relocation.
how to get relocated address ?
what do make packer simple sequence ?
A PE file has a preferred base address. If you're writing a PE Viewer, then it sounds like it will analyze the PE file only. This is a static analysis, so you'll only get the preferred base address, which is 0x40000000.
OllyDbg is a debugger, which is a totally different thing than a PE Viewer. A debugger performs a dynamic analysis at runtime. At runtime, the PE file might have been loaded to a different address, since the preferred address was already used.
So, in my opinion, your PE Viewer program does what it should do - except if you wanted to write a debugger.
Thomas has already explained that base address is just a preferred address, it does not guarantee you that file will load on that address only.
Still, in most of the cases, it should be 400000. If you are using Windows XP, this condition is satisfied most of the times. But from Windows Vista and Windows 7, a new concept known as ASLR was introduced.
When you see some other address while the file is loaded in debugger, it is because of ASLR(Address Space Randomization).
What is ASLR?
Address Space Layout Randomization calculates the address of PE files in memory based on the processor's timestamp counter.
Formula = ([SHR4(Timestamp Counter) mod 254] + 1)*64KB
**need confirmation for formula
Why ASLR?
The main motto behind ASL was to stop malware authors from using various flaws of memory structures like buffer overflow, etc. The randomly arranged memory structures and modules made the guessing of memory addresses(where they wished to put malicious code) difficult for them.
Now, coming back to your question: How to get relocated address:
If you can find the CPU timestamp, which I doubt is possible, you can calculate the base location of executable.How to bypass ASLR
Otherwise, you cannot retrieve this address(for Windows Vista and above) after ASLR from a PE file structure.
Also, you can refer to this:
https://security.stackexchange.com/questions/18556/how-do-aslr-and-dep-work

The ImageBase's Address of Excutable file

Why does the ImageBase is difference between CFF and OllyDbg?
CFF is showing you static analysis, meaning it's just reading the file from disk not debugging it at runtime, showing you the "Preferred ImageBase" from the PE header, this is where the binary wants to be loaded at runtime.
When you do dynamic analysis such as with ollydbg it's showing you the values in the PE header at runtime, ImageBase will hold the current ImageBase, not the preferred one from disk. But when you read DllCharacteristics from the optional PE header you will see it is set to 0x8140.
The 0x0040 = IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE meaning Address Space Layout Randomisation is enabled, causing the Windows loader to load modules into random addresses in effort to make exploits more difficult because hard coded jmps and addresses will not be accurate.
The exploit developers now need to calculate everything at runtime, well unless you use Windows 8 or 10 because a bug has been causing ASLR to not work correctly...

How can I determine if Windows applies ASLR without rebooting?

As far as I understand, ASLR Address Space Layout Randomization will only do random relocation per system start (per reboot).
Address Space Layout Randomization (ASLR)
ASLR moves executable images into random locations when a system
boots, making it harder for exploit
code to operate predictably. (...)
If this is the case, how can I then "test" or, rather, check that ASLR is happening for my C++ module or for a system module (say, kernel32.dll) without repeatedly restarting Windows and hoping the randomness kicks in?
This is what I would try:
Remember that a module's HMODULE handle is actually the base address of the module's image. You can use GetModuleHandle to obtain this value. If you compare that to the base address in the image's optional header values, we would expect those two values to be different when ASLR is turned on.
Keep in mind that this would only be a clear indicator of ASLR when GetModuleHandle is used on certain system DLLs; it would work for kernel32 because it is not a typical candidate for image relocation:
Microsoft system DLLs are all given unique recommended base addresses; and
It is one of the first DLLs mapped into the process address space.
Since kernel32 wouldn't typically be relocated, if ASLR was turned off it would be reasonable to expect it to be loaded at its recommended base address.
How do you obtain the recommended base address from the image headers? The easiest way is to use the DUMPBIN utility included with Visual C++. If you'd rather do it programatically, you will need to do some spelunking through the executable image's headers until you locate the IMAGE_OPTIONAL_HEADER structure's ImageBase field. For more information about PE headers, I'd recommend "An In-Depth Look into the Win32 Portable Executable File Format" by Matt Pietrek.

Resources