]> git.saurik.com Git - cycript.git/blame - Inject.cpp
Repair build when JavaScriptCore is not available.
[cycript.git] / Inject.cpp
CommitLineData
7341eedb
JF
1/* Cycript - The Truly Universal Scripting Language
2 * Copyright (C) 2009-2016 Jay Freeman (saurik)
e91fbe93
JF
3*/
4
f95d2598 5/* GNU Affero General Public License, Version 3 {{{ */
e91fbe93 6/*
f95d2598
JF
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
c15969fd 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f95d2598
JF
15 * GNU Affero General Public License for more details.
16
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
b3378a02 19**/
e91fbe93
JF
20/* }}} */
21
f8d45a20 22#include <sstream>
7cfc264c 23#include <string>
56fc2692 24
3615a2f7 25#include <dlfcn.h>
b6961e53 26
b6961e53
JF
27#include "Exception.hpp"
28#include "Pooling.hpp"
b6961e53 29
7cfc264c 30#if defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
c3700dee
JF
31#include <unistd.h>
32
7cfc264c
JF
33#include <sys/fcntl.h>
34#include <sys/mman.h>
6342b70c 35
7cfc264c 36#include <mach-o/loader.h>
3615a2f7 37
7cfc264c 38#define CS_OPS_PIDOFFSET 6
3370d0c0 39
7cfc264c
JF
40extern "C" int csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize);
41extern "C" int proc_pidpath(int pid, void *buffer, uint32_t buffersize);
3615a2f7 42#endif
b6961e53 43
7cfc264c
JF
44int main(int argc, char * const argv[], char const * const envp[]);
45extern "C" char *MSmain0(int argc, char *argv[]);
b6961e53 46
7cfc264c
JF
47static std::string LibraryFor(void *address) {
48 Dl_info info;
49 _assert(dladdr(address, &info) != 0);
50 return info.dli_fname;
51}
3615a2f7 52
7cfc264c
JF
53template <typename Type_>
54Type_ *shift(Type_ *data, size_t size) {
55 return reinterpret_cast<Type_ *>(reinterpret_cast<uint8_t *>(data) + size);
56}
3615a2f7 57
0abb2a2f 58void InjectLibrary(int pid, std::ostream &stream, int argc, const char *const argv[]) {
7cfc264c
JF
59 auto cynject(LibraryFor(reinterpret_cast<void *>(&main)));
60 auto slash(cynject.rfind('/'));
61 _assert(slash != std::string::npos);
62 cynject = cynject.substr(0, slash) + "/cynject";
3615a2f7 63
7cfc264c 64 auto library(LibraryFor(reinterpret_cast<void *>(&MSmain0)));
3615a2f7 65
7cfc264c
JF
66#if defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
67 off_t offset;
68 _assert(csops(pid, CS_OPS_PIDOFFSET, &offset, sizeof(offset)) != -1);
3615a2f7 69
c3700dee
JF
70 // XXX: implement a safe version of this
71 char path[4096];
e4b4d8c7 72 int writ(proc_pidpath(pid, path, sizeof(path)));
7cfc264c 73 _assert(writ != 0);
b6961e53 74
7cfc264c 75 auto fd(_syscall(open(path, O_RDONLY)));
b6961e53 76
7cfc264c
JF
77 auto page(getpagesize());
78 auto size(page * 4);
79 auto map(_syscall(mmap(NULL, size, PROT_READ, MAP_SHARED, fd, offset)));
3615a2f7 80
7cfc264c 81 _syscall(close(fd)); // XXX: _scope
3615a2f7 82
7cfc264c
JF
83 auto header(reinterpret_cast<mach_header *>(map));
84 auto command(reinterpret_cast<load_command *>(header + 1));
3615a2f7 85
7cfc264c
JF
86 switch (header->magic) {
87 case MH_MAGIC_64:
88 command = shift(command, sizeof(uint32_t));
89 case MH_MAGIC:
3615a2f7
JF
90 break;
91 default:
92 _assert(false);
93 }
3db8ce8e 94
7cfc264c
JF
95 bool ios(false);
96 for (decltype(header->ncmds) i(0); i != header->ncmds; ++i) {
97 if (command->cmd == LC_VERSION_MIN_IPHONEOS)
98 ios = true;
99 command = shift(command, command->cmdsize);
3615a2f7 100 }
9d79cefc 101
7cfc264c 102 _syscall(munmap(map, size)); // XXX: _scope
9d79cefc 103
7cfc264c
JF
104 auto length(library.size());
105 _assert(length >= 6);
106 length -= 6;
9d79cefc 107
7cfc264c
JF
108 _assert(library.substr(length) == ".dylib");
109 library = library.substr(0, length);
110 library += ios ? "-sim" : "-sys";
111 library += ".dylib";
b6961e53
JF
112#endif
113
f8d45a20
JF
114 std::ostringstream inject;
115 inject << cynject << " " << std::dec << pid << " " << library;
0abb2a2f
JF
116 for (decltype(argc) i(0); i != argc; ++i) {
117 inject << " '";
118 for (const char *arg(argv[i]); *arg != '\0'; ++arg)
119 if (*arg != '\'')
120 inject.put(*arg);
121 else
122 inject << "'\\''";
123 inject << "'";
124 }
125
126 FILE *process(popen(inject.str().c_str(), "r"));
127 _assert(process != NULL);
128
129 for (;;) {
130 char data[1024];
131 auto writ(fread(data, 1, sizeof(data), process));
132 stream.write(data, writ);
133
134 if (writ == sizeof(data))
135 continue;
136 _assert(!ferror(process));
137 if (feof(process))
138 break;
139 }
f8d45a20 140
0abb2a2f
JF
141 auto status(pclose(process)); // XXX: _scope (sort of?)
142 _assert(status != -1);
143 _assert(status == 0);
b6961e53 144}