TL;DR version: /* really? can other people confirm this behavior pls? * * if the guess is off for you, by how many, and can you please * indicate what compiler version and flags you used? * * ive tried with gcc 4.9.2 and 4.8.3 only on kernel 4.0.0 and glibc 2.20 * i suspect its going to be an issue with the loader and kernel and sys_mmap. * * gcc -m64 -s -fpic -pie -o mmap mmap.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> signed int main(void) { char* ptr = malloc(256*1024); /* ptr - 16 = mapping base (sizeof(struct malloc_chunk)) 64-bit * - 0x564000 = ld-2.20.so base - mapping base + ld-2.20.so.base - libc-2.20 base */ printf("libc: %p\n", (ptr-16-0x564000)); return EXIT_SUCCESS; } Full-text version: While looking at things entirely unrelated, I happened to notice a few things about Linux ASLR. The first is that modules are loaded in the same order each time and appears to be english alphabetical; they second was that the first mmap's seem to always occupy a sequential order in the address space, depending largely on the size of the mapping. Rather large ones seem to bias towards the beginning of the address space immediately preceeding the first loaded module, and smaller mappings bias towards the end of the address space after the first mapped section of ld. Then I started looking a little more and I noticed that the spacing between modules seems constant, for instance, 1000 runs of vsftpd yielded 1000 different addresses for the loaded modules, however the spacing between them all was always constant. Libattr is first, followed by libc, and the loader is always last but before the vdso/etc and the executable (if PIE) and the stack/etc. So noting this, I was able to malloc() a large enough section of memory to hit the mmap threshhold, but small enough to get it loaded immediately under the loader. Then with knowledge of that pointer, I can subtract the size of the heap metadata back to the base of the mapping, then from that subtract a constant value to the loader, and from that subtract a constant value to the first loaded library. I noted that this constant value seems dependent on the executable itself, sometimes when I added/removed portions of the program and recompiled, my calculations from ld to libc (in my instance) was off, but the calculations from the mapping to ld were always correct. Then while trying to discern that behavior, it disappeared on me and the guess was always correct again. So, if this is actual behavior and its not just that the NSA has breached my virtual machine and is screwing with me (joke), then: 0. With knowledge of the target binary, such as from an RPM and; 1. With the ability to obtain an allocation large enough to trigger mmap behavior and; 2. With knowledge of the order of the mapping your allocation (waves hands around) 3. With a leak of a pointer inside of the mapped area that you can calculate back to the base 4. You can calculate the base address of any library that is loaded, providing there isnt a bunch of dlopen/dlclose type calls Given that a key aspect of process isolation in the unix world revolves around fork(), it seems likely that an intruder would generally be able to calculate what number sequentially and what size mappings came before them, so its a little less hand wavey than it seems. Really? This can't be right... Attachment manifest: - parse-libs.sh - file.pl Poor richards 30 second scripts to parse the output of /proc/pid/maps for the 1000 runs of vsftpd and output a file containing the module to module differences - Makefile - mmap.c - mapgo.sh Poor richards 30 seconds scripts and C file to try to guess the address of libc based on knowledge of the address of a mmap whose order is know -- So we have no queen, the food is strange and it's not dark at all. I say we try to escape for a bit, stick some gel to the side of the tank and then die in weird places.
Attachment:
aslr.tar.xz
Description: Binary data
_______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: http://seclists.org/fulldisclosure/