]>
git.saurik.com Git - cycript.git/blob - Mach/Inject.cpp
ace75cd032b3b9d9083b130ed149878992863e88
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/>.
27 #include "Exception.hpp"
28 #include "Pooling.hpp"
30 #if defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
31 #include <sys/fcntl.h>
34 #include <mach-o/loader.h>
36 #define CS_OPS_PIDOFFSET 6
38 extern "C" int csops(pid_t pid
, unsigned int ops
, void *useraddr
, size_t usersize
);
39 extern "C" int proc_pidpath(int pid
, void *buffer
, uint32_t buffersize
);
42 int main(int argc
, char * const argv
[], char const * const envp
[]);
43 extern "C" char *MSmain0(int argc
, char *argv
[]);
45 static std::string
LibraryFor(void *address
) {
47 _assert(dladdr(address
, &info
) != 0);
48 return info
.dli_fname
;
51 template <typename Type_
>
52 Type_
*shift(Type_
*data
, size_t size
) {
53 return reinterpret_cast<Type_
*>(reinterpret_cast<uint8_t *>(data
) + size
);
56 void InjectLibrary(int pid
, int argc
, const char *argv
[]) {
57 auto cynject(LibraryFor(reinterpret_cast<void *>(&main
)));
58 auto slash(cynject
.rfind('/'));
59 _assert(slash
!= std::string::npos
);
60 cynject
= cynject
.substr(0, slash
) + "/cynject";
62 auto library(LibraryFor(reinterpret_cast<void *>(&MSmain0
)));
64 #if defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
66 _assert(csops(pid
, CS_OPS_PIDOFFSET
, &offset
, sizeof(offset
)) != -1);
69 int writ(proc_pidpath(pid
, path
, sizeof(path
)) != 0);
72 auto fd(_syscall(open(path
, O_RDONLY
)));
74 auto page(getpagesize());
76 auto map(_syscall(mmap(NULL
, size
, PROT_READ
, MAP_SHARED
, fd
, offset
)));
78 _syscall(close(fd
)); // XXX: _scope
80 auto header(reinterpret_cast<mach_header
*>(map
));
81 auto command(reinterpret_cast<load_command
*>(header
+ 1));
83 switch (header
->magic
) {
85 command
= shift(command
, sizeof(uint32_t));
93 for (decltype(header
->ncmds
) i(0); i
!= header
->ncmds
; ++i
) {
94 if (command
->cmd
== LC_VERSION_MIN_IPHONEOS
)
96 command
= shift(command
, command
->cmdsize
);
99 _syscall(munmap(map
, size
)); // XXX: _scope
101 auto length(library
.size());
102 _assert(length
>= 6);
105 _assert(library
.substr(length
) == ".dylib");
106 library
= library
.substr(0, length
);
107 library
+= ios
? "-sim" : "-sys";
111 std::ostringstream inject
;
112 inject
<< cynject
<< " " << std::dec
<< pid
<< " " << library
;
113 for (decltype(argc
) i(0); i
!= argc
; ++i
)
114 inject
<< " " << argv
[i
];
116 _assert(system(inject
.str().c_str()) == 0);