Skip to content

Instantly share code, notes, and snippets.

@safiire

safiire/fork_aslr.c

Last active Aug 25, 2017
Embed
What would you like to do?
How many bits are random on Linux ASLR?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
/*
* A fork() doesn't (and shouldn't) re-randomize the address space
* but that happens properly after the exec()
*/
// Return the stack pointer
int64_t return_rsp(void){
__asm__("movq %rsp, %rax");
}
// Print out the stack pointer
int main(int argc, char **argv){
printf("[+] My pid is %d\n", getpid());
printf("[+] My rsp = 0x%016lx\n", return_rsp());
if(argc < 2){
printf("[+] Forking a child process...\n");
pid_t pid = fork();
if(pid == 0){
printf("[+] Forked process rsp = 0x%016lx\n", return_rsp());
printf("[+] Re-executing myself...\n");
const char *child_argv[] = {"no", "fork", '\0'};
execv(argv[0], child_argv);
perror("Wat?");
exit(1);
}else{
waitpid(pid, 0, 0);
}
}
return 0;
}
#!/usr/bin/env ruby
## Hold our bit counts
counts = 64.times.map do
[]
end
## Sample some stack addresses
sample_addresses = 10_000.times do
md = `./print_rsp`.match(/0x([0-9a-f]+)/)
value = md[1].to_i(16)
bit_vector = sprintf("%064b", value).split(//)
bit_vector.each_with_index do |bit, index|
counts[index] << bit
end
end
## Which bits stay the same?
result = counts.map do |bits|
bits.uniq.size == 1 ? 0 : 1
end
final_mask = result.join.to_i(2)
printf("Mask of bits which change are: %016x\n", final_mask)
## Any favouritism for bits?
probability = counts.map do |bits|
probability = bits.map(&:to_i).inject(0){|a,b| a + b} / bits.size.to_f
sprintf("%d%%", (probability * 100).round)
end
puts "Probability of 1 is:"
p probability
#include <stdio.h>
#include <stdint.h>
/*
* Answers the question: how random is the stack after ASLR?
*
* Linux 4.10.0-19-generic #21-Ubuntu x86_64
*
* The result of running this many times shows that only these
* bits ever change on the stack with ASLR
* 0000000000000000000000000000001111111111111111111111111111110000
* Mask = 0x00000003fffffff0
*
* That is 2^30 or 1,073,741,824 possibilities
*
* Probability of a 1 is always *very* close to 50/50 for those that change
* 0%, 0%, 0%, 0%, 0%, 0%, 0%, 0%,
* 0%, 0%, 0%, 0%, 0%, 0%, 0%, 0%,
* 0%, 100%, 100%, 100%, 100%, 100%, 100%, 100%,
* 100%, 100%, 100%, 100%, 100%, 100%, 50%, 50%,
* 49%, 50%, 50%, 51%, 50%, 51%, 49%, 50%,
* 50%, 50%, 51%, 50%, 50%, 49%, 50%, 50%,
* 50%, 49%, 50%, 50%, 50%, 50%, 50%, 49%,
* 50%, 50%, 50%, 50%, 0%, 0%, 0%, 0%
*
* Examples:
* 0x00000003fffffff0
* ------------------
* 0x00007ffe9feabf90
* 0x00007ffe77320c60
* 0x00007ffdc7cbb260
* 0x00007ffdab117000
* 0x00007fff649c64c0
* 0x00007ffffc8eea60
* 0x00007ffec9afb2c0
* 0x00007fff6aa198a0
* 0x00007ffec28af610
* 0x00007ffc694e86a0
* 0x00007ffcf15f80b0
* ------------------
* 0x00007ff[cdef]???????0
*/
// Return the stack pointer
int64_t return_rsp(void){
__asm__("movq %rsp, %rax");
}
// Print out the stack pointer
int main(int argc, char **argv){
uint64_t address = return_rsp();
printf("rsp = 0x%016lx\n", address);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.