PIE affected by ASLR

PIE (Position Independent Executable)

  • The instructions will be represented in relative address instead of absolute address.

ASLR (Address Space Layout Randomization)

  • Use random base address when the program is loaded to stack, heap, etc.

Purpose of my experiment

  • Understanding how ASLR affect the address.

Design experiment

  • Run a simple program (unstripped) and find where the "main function" in the program is. Does the address of the "main function" differs everytime I execute?

  • Check the main function's offset. Does it differs everytime I execute?

  • I also create a stripped file to observe it's main function and main function's offset.

Create test files (test, test2)

  • test.c

    1
    2
    3
    4
    5
    6
    #include <stdio.h>

    int main() {
    printf("Hello!\n");
    return 0;
    }

  • Compile to 2 binary files

    • test (PIE, not stripped)

      • Compile command

        1
        gcc test.c -o test

    • test2 (PIE, stripped)

      • Compile command

        1
        gcc test.c -s -o test2

Testing test

  • Run test with GDB and set a breakpoint at main.

  • Run it and it will stop at main. The main's address is 0x555555555149.

  • Base address.

  • Calculation of Main's address & Main's Offset & Base address.

    1
    2
    3
    4
    5
    6
    7
    Main's address: MA
    Base address: BA
    Main's Offset: MO

    MA = BA + MO
    = 0x555555554000 + 0x1149
    = 0x555555555149

  • After testing test a lot of times I found that main's address is always the same. Maybe GDB "disabled" ASLR?

  • Due to the issue above, I created test3. The purpose of this program is to wait for user input. Then we can attach the process of this program to GDB. After doing this we might see the affect of ASLR.

  • test3.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <stdio.h>

    int main() {
    printf("Enter a number:\n");
    int num;
    scanf("%d", &num);
    printf("Hello %d!\n", num);
    return 0;
    }

  • test3 (PIE, not stripped)

    • Compile command

      1
      gcc test3.c -o test3

Testing test3

  • In this test, I will first run test3 with GDB then run it independently and compare the 2 results.

  • Run test3 with GDB and set a breakpoint at main.

    • So far, I know the main's offset is 0x11a9.
  • Check the base address.

    • Base address is 0x555555554000 this time.
  • Run test3

    1
    ./test3

  • This program will wait for an user input.

  • Find the process id of the new program. ==> 110703

  • Attach the process to gdb and check the base address (0x55ee45f8f000 for this time). By checking the base address value several times, I found that the base address may be is different every time now! Which means ASLR is working now!

  • Calculate main's offset. The result shows that main's offset is 0x11a9 everytime I test.

  • By doing the small tests above, I know that:

    1. Due to ASLR, base address may change everytime I execute.

    2. The main's offset in the same program will always be the same.

Testing test2

  • Reminder: test2 is a stripped file.

  • Run test2 with GDB.

  • I can't use b *main and p *main to find main's address.

  • Enter info files to find some clues like "Entry point".

  • Print Entry point's neighboring instructions. It seems like it is calling "libc start main" at line 0x1088. And if my assumption is true, line 0x1081 might be "loading main's address" which is (0x1088 + 0xc1 = 0x1149).

    1
    Notice that the rip value is the value of next line! (because of pipeline?) So it is 0x1088 not 0x1081!

  • 0x1149 is as same as the main's offset when I run test. Now I know the main's offset. I can use info proc mappings to find base address. By knowing main's offset and base address, I can calculate main's address!

  • Calculate main's address

    1
    2
    3
    4
    5
    6
    7
    Main's address: MA
    Base address: BA
    Main's Offset: MO

    MA = BA + MO
    = 0x555555554000 + 0x1149
    = 0x555555555149

  • Set break point and run. Then, main in test2 appears.

What I Observed And Learned?

  • Due to ASLR, base address may change everytime I execute.

  • The main's offset in the same program will always be the same.

  • I learned a way of finding the main's address when the program is stripped.