]>
git.saurik.com Git - cycript.git/blob - Inject.cpp
1 /* Cycript - The Truly Universal Scripting Language
2 * Copyright (C) 2009-2016 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__))
33 #include <sys/fcntl.h>
36 #include <mach-o/loader.h>
38 #define CS_OPS_PIDOFFSET 6
40 extern "C" int csops(pid_t pid
, unsigned int ops
, void *useraddr
, size_t usersize
);
41 extern "C" int proc_pidpath(int pid
, void *buffer
, uint32_t buffersize
);
44 int main(int argc
, char * const argv
[], char const * const envp
[]);
45 extern "C" char *MSmain0(int argc
, char *argv
[]);
47 static std::string
LibraryFor(void *address
) {
49 _assert(dladdr(address
, &info
) != 0);
50 return info
.dli_fname
;
53 template <typename Type_
>
54 Type_
*shift(Type_
*data
, size_t size
) {
55 return reinterpret_cast<Type_
*>(reinterpret_cast<uint8_t *>(data
) + size
);
58 void InjectLibrary(int pid
, int argc
, const char *const argv
[]) {
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";
64 auto library(LibraryFor(reinterpret_cast<void *>(&MSmain0
)));
66 #if defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
68 _assert(csops(pid
, CS_OPS_PIDOFFSET
, &offset
, sizeof(offset
)) != -1);
70 // XXX: implement a safe version of this
72 int writ(proc_pidpath(pid
, path
, sizeof(path
)));
75 auto fd(_syscall(open(path
, O_RDONLY
)));
77 auto page(getpagesize());
79 auto map(_syscall(mmap(NULL
, size
, PROT_READ
, MAP_SHARED
, fd
, offset
)));
81 _syscall(close(fd
)); // XXX: _scope
83 auto header(reinterpret_cast<mach_header
*>(map
));
84 auto command(reinterpret_cast<load_command
*>(header
+ 1));
86 switch (header
->magic
) {
88 command
= shift(command
, sizeof(uint32_t));
96 for (decltype(header
->ncmds
) i(0); i
!= header
->ncmds
; ++i
) {
97 if (command
->cmd
== LC_VERSION_MIN_IPHONEOS
)
99 command
= shift(command
, command
->cmdsize
);
102 _syscall(munmap(map
, size
)); // XXX: _scope
104 auto length(library
.size());
105 _assert(length
>= 6);
108 _assert(library
.substr(length
) == ".dylib");
109 library
= library
.substr(0, length
);
110 library
+= ios
? "-sim" : "-sys";
114 std::ostringstream inject
;
115 inject
<< cynject
<< " " << std::dec
<< pid
<< " " << library
;
116 for (decltype(argc
) i(0); i
!= argc
; ++i
)
117 inject
<< " " << argv
[i
];
119 _assert(system(inject
.str().c_str()) == 0);