Bob5421
Bob5421

Reputation: 9163

Difference between ASLR and PIE

I'm not sure whether I understand the difference between ASLR and PIE.

According to me, ASLR is an OS option, whereas PIE is a compilation option.

Do PIE and ASLR work on the same things (functions addresses, libraries)?

Upvotes: 15

Views: 8493

Answers (2)

qz-
qz-

Reputation: 1051

ASLR and PIE (or PIC) are two sides of the same coin: PIE is a requirement for ASLR.

PIE allows code to be placed anywhere in memory, ASLR is the act of actually positioning it randomly.

If a program is compiled without PIE its text and data sections cannot be relocated in memory, however, ASLR can be applied to the stack, heap, and dynamic libraries that it uses, such as libc.

One important caveat to this simple explanation is that Windows can apply ASLR to non-PIE executables by embedding relocation information into the executable, and these relocations are resolved by the linker on the fly when the code is loaded into memory.

Upvotes: 3

Obsidian
Obsidian

Reputation: 3897

ASLR is actually a strategy adopted by purpose by the OS mainly to circumvent certain attacks such buffer overflows, and sometimes to make a better global use of the whole memory. The main goal is to make unpredictable the locations of different resources.

PIE or PIC, however, is rather tied to the CPU instruction set, and this issue is especially significant when you're writing assembly code. In short, all the CPU is basically doing is reading data at some addresses, making simple arithmetic and logic operations, writing data at some other addresses and making jumps in the code.

It's way easier to write fixed-position code than independent ones for many reasons but it also depends a lot on the CPU you're compiling for, especially with micro-controlers.

For example, if you need to read a long data range from memory, you'll load a base register that points the beginning of this range, then indexing it. But the address of this range will be determined at compilation time, hence be fixed. In the following example, the value "1005" will be loaded into EAX

                                        USE32
                                        ORG     1000h   

 00001000 B8 05 10 00 00                MOV     EAX,data
 00001005 48 65 6C 6C 6F        data:   DB      "Hello"

This works perfectly well, but prevents to move the code at another position than the one it has been compiled for. If you need to do so, you'll have to write instead some code that first loads the current value of EIP into EAX, then adds the difference between current position and targeted data.

It slightly complicates the development process when you do it by hand, but it also adds a significant amount of overhead, making the program larger and slower, which can rapidly become a problem on small microprocessors.

On x86 architectures and other modern computers, however, it's not really visible because the instruction set is already optimized to be as position-independant as possible and because we have the benefit of MMUs, which enables the computer to run every process at the same virtual address.

And even before that, even in real mode, we had segment registers. This enabled programmers to move thing basically everywhere they wanted with a 16-bytes granularity.

However, it becomes critical when compiling shared libraries because all of them should be visible in the same process addressing space (and should actually be PART of the program).

So, - what happens if i run a no-PIE program on an OS with ASLR enabled ?

Actually, it shouldn't be a problem because it's a matter of randomly laying out ressources allocated by the OS itself. So either you already get a pointer from it and nothing changes from your point of view, either it's already up to the system to correctly set up the right registers, for example when setting up the stack before running your process.

Upvotes: 7

Related Questions