PIE affected by ASLR
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
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
7Main's address: MA
Base address: BA
Main's Offset: MO
MA = BA + MO
= 0x555555554000 + 0x1149
= 0x555555555149After 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
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:
Due to ASLR, base address may change everytime I execute.
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
andp *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 useinfo 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
7Main's address: MA
Base address: BA
Main's Offset: MO
MA = BA + MO
= 0x555555554000 + 0x1149
= 0x555555555149Set 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.