]>
git.saurik.com Git - cycript.git/blob - Mach/Inject.cpp
1 /* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2014 Jay Freeman (saurik)
5 /* GNU Affero General Public License, Version 3 {{{ */
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.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
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/>.
26 #include "Exception.hpp"
27 #include "Pooling.hpp"
29 #if defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
30 #include <sys/fcntl.h>
33 #include <mach-o/loader.h>
35 #define CS_OPS_PIDOFFSET 6
37 extern "C" int csops(pid_t pid
, unsigned int ops
, void *useraddr
, size_t usersize
);
38 extern "C" int proc_pidpath(int pid
, void *buffer
, uint32_t buffersize
);
41 int main(int argc
, char * const argv
[], char const * const envp
[]);
42 extern "C" char *MSmain0(int argc
, char *argv
[]);
44 static std::string
LibraryFor(void *address
) {
46 _assert(dladdr(address
, &info
) != 0);
47 return info
.dli_fname
;
50 template <typename Type_
>
51 Type_
*shift(Type_
*data
, size_t size
) {
52 return reinterpret_cast<Type_
*>(reinterpret_cast<uint8_t *>(data
) + size
);
55 void InjectLibrary(pid_t pid
) {
56 auto cynject(LibraryFor(reinterpret_cast<void *>(&main
)));
57 auto slash(cynject
.rfind('/'));
58 _assert(slash
!= std::string::npos
);
59 cynject
= cynject
.substr(0, slash
) + "/cynject";
61 auto library(LibraryFor(reinterpret_cast<void *>(&MSmain0
)));
63 #if defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
65 _assert(csops(pid
, CS_OPS_PIDOFFSET
, &offset
, sizeof(offset
)) != -1);
68 int writ(proc_pidpath(pid
, path
, sizeof(path
)) != 0);
71 auto fd(_syscall(open(path
, O_RDONLY
)));
73 auto page(getpagesize());
75 auto map(_syscall(mmap(NULL
, size
, PROT_READ
, MAP_SHARED
, fd
, offset
)));
77 _syscall(close(fd
)); // XXX: _scope
79 auto header(reinterpret_cast<mach_header
*>(map
));
80 auto command(reinterpret_cast<load_command
*>(header
+ 1));
82 switch (header
->magic
) {
84 command
= shift(command
, sizeof(uint32_t));
92 for (decltype(header
->ncmds
) i(0); i
!= header
->ncmds
; ++i
) {
93 if (command
->cmd
== LC_VERSION_MIN_IPHONEOS
)
95 command
= shift(command
, command
->cmdsize
);
98 _syscall(munmap(map
, size
)); // XXX: _scope
100 auto length(library
.size());
101 _assert(length
>= 6);
104 _assert(library
.substr(length
) == ".dylib");
105 library
= library
.substr(0, length
);
106 library
+= ios
? "-sim" : "-sys";
111 int status(system(pool
.sprintf(1024, "%s %u %s %u", cynject
.c_str(), pid
, library
.c_str(), getpid())));
112 _assert(status
== 0);