2

This should be a very simple,very quick qustion. These are the first 3 lines of a program in C I wrote:

Dump of assembler code for function main:
   0x0804844d <+0>: push   ebp
   0x0804844e <+1>: mov    ebp,esp
   0x08048450 <+3>: and    esp,0xfffffff0
   ... ... ... ... ... ... ...

What is 0x0804844d and 0x0804844e and 0x08048450? It is not affected by ASLR. Is it still a memory address, or a relative point to the file?

Goodies
  • 4,439
  • 3
  • 31
  • 57
  • 2
    Well, those **are** addresses. –  Jan 15 '14 at 09:25
  • But they are not affected by ASLR? FOr example, a command: `0x0804846d <+32>: eb 15 jmp 0x8048484
    ` the address is obviously not hard coded into the OPCODE.
    – Goodies Jan 15 '14 at 09:26
  • What do you expect ASLR to do with this frame setup code? – dbrank0 Jan 15 '14 at 09:31
  • Randomize the memory addresses data locations. – Goodies Jan 15 '14 at 09:37
  • Even if addresses for main are randomized (see different implementations), *some* addresses still need to be chosen once program is loaded. – dbrank0 Jan 15 '14 at 09:42
  • I'm specifically looking at ret2reg buffer overflow. It creates a much more reliable exploit even with ASLR and will allow you to restart the application (and computer) and will still spawn a shell afterwards. – Goodies Jan 15 '14 at 09:51
  • Usually the text section is not ASLR'd, unless you have a PIE executable. And yes, GDB shows absolute addresses. – ninjalj Jan 15 '14 at 12:36
  • 2
    Also, gdb will disable ASLR by default. `set disable-randomization on|off` to toggle. – Mark Plotnick Jan 15 '14 at 16:43

2 Answers2

5

If you look at the Intel Developer Manual instruction-set reference you can see that 0x0804846d <+32>: eb 15 jmp 0x8048484 encodes a relative address. i.e. it's the jmp rel8 short encoding. This works even in position-independent code, i.e. code which can run when mapped / loaded at any address.

ASLR means that the address of the stack (and optionally code+data) in the executable can change every time you load the file into memory. Obviously, once the program is loaded, the addresses won't change anymore, until it is loaded again. So if you know the address at runtime, you can target it, but you can't write an exploit assuming a fixed address.

GDB is showing you addresses of code in the virtual-memory space of your process, after any ASLR. (BTW, GDB disables ASLR by default: set disable-randomization on|off to toggle.)


For executables, it's common that only the stack pointer is ASLRed, while the code is position-dependent and loaded at a fixed address, so code and static data addresses are link-time constants, so code like push OFFSET .LC0 / call puts can work, hard-coding the address of the string constant into a push imm32.

Libraries usually need to be position-independent anyway, so ASLR can load them at a randomized address.

But ASLR for executables is possible and becoming more common, either by making position-independent executables (Linux), or by having the OS fix-up every hard-coded address when it loads the executable at a different address than it was compiled for (Windows).

Addresses only have a 1:1 relation to the position within the file only in a relative sense within the same segment. i.e. the next byte of code is the next byte of the file. The headers of the executable describe which regions of the file are what (and where they should be mapped by the OS's program loader).

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Devolus
  • 21,661
  • 13
  • 66
  • 113
  • @OrenIshShalom: your edit introduced some errors: ASLR of the stack doesn't affect jump addresses; only ASLR of the text segment would do that. e.g. "it will remain the same even if the stack is loaded to another memory address." is nonsense: the jump target isn't a stack address, it's a code address. (Linux does stack ASLR even for non-relocatable (position-dependent) executables. But Linux *does* support position-independent executables and map them at a randomized virtual address; many distros enable PIE by default in their gcc package.) – Peter Cordes Dec 08 '17 at 08:56
3

The meaning of the addresses shown differs in three cases:

  • For executable files
  • For DLLs (Windows) or shared objects (.so, Linux and Un*x-like)
  • For object files

For executables:

Executable files typically cannot be loaded to any address in memory. In Windows there is the possibility to add a "relocation table" to an executable file (required for very old Windows versions); if this is not present (typically the case when using GCC) then it is not possible to load the file to another memory location. In Linux it is never possible to load the executable to another location.

You may try something like this:

static int a;
printf("%X\n", &a);

When you execute the program 100 times you see that the address of a is always the same so no ASLR is done for the executable file itself.

The addresses dumped by objdump are absolute addresses.

For DLLs / .so files:

The addresses are relative to the base address of the DLL (under Linux) or they are absolute addresses (under Windows) that will change when the DLL is loaded into another memory area.

For object files:

When dumping an object file the addresses are relative to the currently displayed section. If there are multiple ".text" sections in a file the addresses will start at 0 for each section.

Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
  • Re: _In Linux it is never possible to load the executable to another location._ PIE executables can be relocated. – ninjalj Jan 16 '14 at 09:53
  • [PIE is a thing](https://stackoverflow.com/questions/43367427/32-bit-absolute-addresses-no-longer-allowed-in-x86-64-linux), but you could say the statement is sort of technically correct. PIEs are "ELF shared objects" (i.e. a library with an entry-point), *not* "ELF executables" according to `file a.out`. – Peter Cordes Dec 08 '17 at 09:26