Skip to content

Instantly share code, notes, and snippets.

@eltongo
Created December 19, 2016 01:26
Show Gist options
  • Save eltongo/48a454799c53f2f46e93baed71cc050c to your computer and use it in GitHub Desktop.
Save eltongo/48a454799c53f2f46e93baed71cc050c to your computer and use it in GitHub Desktop.
Download files via HTTP through Ian Beer's exploit
/* J. Levin has compiled a bunch of Apple opensource utilites for arm64
* You can get them from his site here: http://newosxbook.com/tools/iOSBinaries.html
*
* Follow the link to "The 64-bit tgz pack"
*
* Unpack the tarball into a directory called iosbinpack64 and drag-and-drop
* that directory into the directory with all the source files in in XCode
* so that it ends up in the .app bundle
*
* I (Elton) have added the ability to download files from your iPhone using your browser.
* Browsing to http://iPhones-IP:8081/ will display a simple form where you can enter the full
* path to the file you want to download.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <spawn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <CoreFoundation/CoreFoundation.h>
typedef struct {
char *env;
int port;
} shellThreadArgs;
char* bundle_path() {
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
int len = 4096;
char* path = malloc(len);
CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8*)path, len);
return path;
}
char* prepare_directory(char* dir_path) {
DIR *dp;
struct dirent *ep;
char* in_path = NULL;
char* bundle_root = bundle_path();
asprintf(&in_path, "%s/iosbinpack64/%s", bundle_root, dir_path);
dp = opendir(in_path);
if (dp == NULL) {
printf("unable to open payload directory: %s\n", in_path);
return NULL;
}
while ((ep = readdir(dp))) {
char* entry = ep->d_name;
char* full_entry_path = NULL;
asprintf(&full_entry_path, "%s/iosbinpack64/%s/%s", bundle_root, dir_path, entry);
printf("preparing: %s\n", full_entry_path);
// make that executable:
int chmod_err = chmod(full_entry_path, 0777);
if (chmod_err != 0){
printf("chmod failed\n");
}
free(full_entry_path);
}
closedir(dp);
free(bundle_root);
return in_path;
}
// prepare all the payload binaries under the iosbinpack64 directory
// and build up the PATH
char* prepare_payload() {
char* path = calloc(4096, 1);
strcpy(path, "PATH=");
char* dir;
dir = prepare_directory("bin");
strcat(path, dir);
strcat(path, ":");
free(dir);
dir = prepare_directory("sbin");
strcat(path, dir);
strcat(path, ":");
free(dir);
dir = prepare_directory("usr/bin");
strcat(path, dir);
strcat(path, ":");
free(dir);
dir = prepare_directory("usr/local/bin");
strcat(path, dir);
strcat(path, ":");
free(dir);
dir = prepare_directory("usr/sbin");
strcat(path, dir);
strcat(path, ":");
free(dir);
strcat(path, "/bin:/sbin:/usr/bin:/usr/sbin:/usr/libexec");
return path;
}
#define START_HTML "<html><body>"
#define END_HTML "</body></html>"
#define HTTP_404 "<h1>404 Not Found</h1>"
#define FORM_SOURCE "<script type=\"text/javascript\">" \
"function dl() {" \
"var p = document.getElementById('path').value;" \
"if (p[0] != '\') p += '\';" \
"window.location.href = document.location.origin + p;" \
"}</script>" \
"<h2>Enter full file path:</h2>" \
"<input type=\"text\" id=\"path\" placeholder=\"Enter path here\" />" \
"<input type=\"button\" onclick=\"dl()\" value=\"Download\"/>"
void send_html(int connection, int statusCode, char *source) {
char headerbuf[256] = {0};
size_t length = strlen(source);
size_t sz;
sz = snprintf(headerbuf, 256, "HTTP/1.1 %d NOTNECESSARY\r\n", statusCode);
write(connection, headerbuf, sz);
sz = snprintf(headerbuf, 256, "Content-Type: text/html\r\n");
write(connection, headerbuf, sz);
sz = snprintf(headerbuf, 256, "Content-Length: %zu\r\n\r\n", length);
write(connection, headerbuf, sz);
write(connection, source, length);
}
void send_form(int connection) {
char *source = START_HTML FORM_SOURCE END_HTML;
send_html(connection, 200, source);
}
void send_404(int connection) {
char *source = START_HTML HTTP_404 FORM_SOURCE END_HTML;
send_html(connection, 404, source);
}
void send_file(int connection, char *filePath) {
char headerbuf[256] = {0};
char fbuf[1024] = {0};
char *fileName = "default.bin";
for (char *i = filePath; *i; i++) {
if (*i == '/') {
fileName = i + 1;
}
}
int sz;
FILE *f = fopen(filePath, "rb");
struct stat f_stat;
if (!f) {
send_404(connection);
return;
}
printf("File opened. Checking file\n");
fstat((int) f, &f_stat);
if (S_ISDIR(f_stat.st_mode)) {
printf("Not a regular file\n");
send_404(connection);
fclose(f);
return;
}
size_t size;
fseek(f, 0L, SEEK_END);
size = ftell(f);
fseek(f, 0L, SEEK_SET);
printf("File size is %zu bytes.\n", size);
sz = snprintf(headerbuf, 256, "HTTP/1.1 200 OK\r\n");
write(connection, headerbuf, sz);
sz = snprintf(headerbuf, 256, "Content-Type: application/octet-stream\r\n");
write(connection, headerbuf, sz);
sz = snprintf(headerbuf, 256, "Content-Disposition:attachment;filename=%s\r\n", fileName);
write(connection, headerbuf, sz);
sz = snprintf(headerbuf, 256, "Content-Length: %zu\r\n\r\n", size);
write(connection, headerbuf, sz);
printf("Starting to send file\n");
while ((size = fread(fbuf, 1, 1024, f)) > 0) {
write(connection, fbuf, size);
}
}
void* do_bind_http(void* port) {
struct sockaddr_in sa;
sa.sin_len = 0;
sa.sin_family = AF_INET;
sa.sin_port = htons((int)port);
sa.sin_addr.s_addr = INADDR_ANY;
int sock = socket(PF_INET, SOCK_STREAM, 0);
bind(sock, (struct sockaddr*)&sa, sizeof(sa));
listen(sock, 1);
printf("listening http on %d\n", (int)port);
for (;;) {
int conn = accept(sock, 0, 0);
char inbuf[1024] = {0};
char filebuf[256] = {0};
printf("Got connection\n");
size_t bytesRead = read(conn, inbuf, 1023);
printf("Read %zu\n", bytesRead);
for (int i = 4; i < 256 && !isspace(inbuf[i]); ++i) {
filebuf[i - 4] = inbuf[i];
}
printf("Accessing %s\n", filebuf);
if (strlen(filebuf) < 2) {
printf("Sending form\n");
send_form(conn);
} else {
printf("Trying to send file\n");
send_file(conn, filebuf);
}
close(conn);
}
return NULL;
}
void* do_bind_shell(void* args) {
shellThreadArgs *shellArgs = (shellThreadArgs *) args;
char *env = shellArgs->env;
int port = shellArgs->port;
char* bundle_root = bundle_path();
char* shell_path = NULL;
asprintf(&shell_path, "%s/iosbinpack64/bin/bash", bundle_root);
char* argv[] = {shell_path, NULL};
char* envp[] = {env, NULL};
struct sockaddr_in sa;
sa.sin_len = 0;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = INADDR_ANY;
int sock = socket(PF_INET, SOCK_STREAM, 0);
bind(sock, (struct sockaddr*)&sa, sizeof(sa));
listen(sock, 1);
printf("shell listening on port %d\n", port);
for(;;) {
int conn = accept(sock, 0, 0);
posix_spawn_file_actions_t actions;
posix_spawn_file_actions_init(&actions);
posix_spawn_file_actions_adddup2(&actions, conn, 0);
posix_spawn_file_actions_adddup2(&actions, conn, 1);
posix_spawn_file_actions_adddup2(&actions, conn, 2);
pid_t spawned_pid = 0;
int spawn_err = posix_spawn(&spawned_pid, shell_path, &actions, NULL, argv, envp);
if (spawn_err != 0){
perror("shell spawn error");
} else {
printf("shell posix_spawn success!\n");
}
posix_spawn_file_actions_destroy(&actions);
printf("our pid: %d\n", getpid());
printf("spawned_pid: %d\n", spawned_pid);
int wl = 0;
while (waitpid(spawned_pid, &wl, 0) == -1 && errno == EINTR);
}
free(shell_path);
return NULL;
}
void drop_payload() {
char* env_path = prepare_payload();
printf("will launch a shell with this environment: %s\n", env_path);
pthread_t shellThread;
pthread_t httpThread;
shellThreadArgs shellArgs = {env_path, 4141};
pthread_create(&shellThread, NULL, &do_bind_shell, &shellArgs);
pthread_create(&httpThread, NULL, &do_bind_http, (void *)8081);
pthread_join(shellThread, NULL);
pthread_join(httpThread, NULL);
free(env_path);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment