1 /* Cycript - Optimizing JavaScript Compiler/Runtime 
   2  * Copyright (C) 2009-2013  Jay Freeman (saurik) 
   5 /* GNU General Public License, Version 3 {{{ */ 
   7  * Cycript is free software: you can redistribute it and/or modify 
   8  * it under the terms of the GNU General Public License as published 
   9  * by the Free Software Foundation, either version 3 of the License, 
  10  * or (at your option) any later version. 
  12  * Cycript is distributed in the hope that it will be useful, but 
  13  * WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  * GNU General Public License for more details. 
  17  * You should have received a copy of the GNU General Public License 
  18  * along with Cycript.  If not, see <http://www.gnu.org/licenses/>. 
  23 #include <mach/mach.h> 
  25 #include <mach/machine/thread_status.h> 
  32 #include "Exception.hpp" 
  33 #include "Pooling.hpp" 
  34 #include "Trampoline.t.hpp" 
  36 extern "C" void __pthread_set_self(pthread_t
); 
  38 void InjectLibrary(pid_t pid
) { 
  39     const char *library(CY_LIBRARY
); 
  41     static const size_t Stack_(8 * 1024); 
  42     size_t length(strlen(library
) + 1), depth(sizeof(Baton
) + length
); 
  43     depth 
= (depth 
+ sizeof(uintptr_t) + 1) / sizeof(uintptr_t) * sizeof(uintptr_t); 
  46     uint8_t *local(pool
.malloc
<uint8_t>(depth
)); 
  47     Baton 
*baton(reinterpret_cast<Baton 
*>(local
)); 
  49     baton
->__pthread_set_self 
= &__pthread_set_self
; 
  50     baton
->pthread_create 
= &pthread_create
; 
  52     baton
->mach_thread_self 
= &mach_thread_self
; 
  53     baton
->thread_terminate 
= &thread_terminate
; 
  55     baton
->dlerror 
= &dlerror
; 
  56     baton
->dlsym 
= &dlsym
; 
  58     baton
->pid 
= getpid(); 
  59     memcpy(baton
->library
, library
, length
); 
  61     vm_size_t 
size(depth 
+ Stack_
); 
  63     mach_port_t 
self(mach_task_self()), task
; 
  64     _krncall(task_for_pid(self
, pid
, &task
)); 
  67     _krncall(vm_allocate(task
, &stack
, size
, true)); 
  68     vm_address_t 
data(stack 
+ Stack_
); 
  70     vm_write(task
, data
, reinterpret_cast<vm_address_t
>(baton
), depth
); 
  73     _krncall(thread_create(task
, &thread
)); 
  75     thread_state_flavor_t flavor
; 
  76     mach_msg_type_number_t count
; 
  79     Trampoline 
*trampoline
; 
  82     trampoline 
= &Trampoline_armv6_
; 
  83     arm_thread_state_t state
; 
  84     flavor 
= ARM_THREAD_STATE
; 
  85     count 
= ARM_THREAD_STATE_COUNT
; 
  87 #elif defined(__i386__) 
  88     trampoline 
= &Trampoline_i386_
; 
  89     i386_thread_state_t state
; 
  90     flavor 
= i386_THREAD_STATE
; 
  91     count 
= i386_THREAD_STATE_COUNT
; 
  93 #elif defined(__x86_64__) 
  94     trampoline 
= &Trampoline_x86_64_
; 
  95     x86_thread_state64_t state
; 
  96     flavor 
= x86_THREAD_STATE64
; 
  97     count 
= x86_THREAD_STATE64_COUNT
; 
 100     #error XXX: implement 
 104     _krncall(vm_allocate(task
, &code
, trampoline
->size_
, true)); 
 105     vm_write(task
, code
, reinterpret_cast<vm_address_t
>(trampoline
->data_
), trampoline
->size_
); 
 106     _krncall(vm_protect(task
, code
, trampoline
->size_
, false, VM_PROT_READ 
| VM_PROT_EXECUTE
)); 
 109     printf("_ptss:%p\n", baton->__pthread_set_self); 
 110     printf("dlsym:%p\n", baton->dlsym); 
 111     printf("code:%zx\n", (size_t) code); 
 114     uint32_t frame
[push
]; 
 115     if (sizeof(frame
) != 0) 
 116         memset(frame
, 0, sizeof(frame
)); 
 117     memset(&state
, 0, sizeof(state
)); 
 119     mach_msg_type_number_t 
read(count
); 
 120     _krncall(thread_get_state(thread
, flavor
, reinterpret_cast<thread_state_t
>(&state
), &read
)); 
 121     _assert(read 
== count
); 
 125     state
.__sp 
= stack 
+ Stack_
; 
 126     state
.__pc 
= code 
+ trampoline
->entry_
; 
 128     if ((state
.__pc 
& 0x1) != 0) { 
 130         state
.__cpsr 
|= 0x20; 
 132 #elif defined(__i386__) 
 135     state
.__eip 
= code 
+ trampoline
->entry_
; 
 136     state
.__esp 
= stack 
+ Stack_ 
- sizeof(frame
); 
 137 #elif defined(__x86_64__) 
 138     frame
[0] = 0xdeadbeef; 
 140     state
.__rip 
= code 
+ trampoline
->entry_
; 
 141     state
.__rsp 
= stack 
+ Stack_ 
- sizeof(frame
); 
 143     #error XXX: implement 
 146     if (sizeof(frame
) != 0) 
 147         vm_write(task
, stack 
+ Stack_ 
- sizeof(frame
), reinterpret_cast<vm_address_t
>(frame
), sizeof(frame
)); 
 149     _krncall(thread_set_state(thread
, flavor
, reinterpret_cast<thread_state_t
>(&state
), count
)); 
 150     _krncall(thread_resume(thread
)); 
 152     _krncall(mach_port_deallocate(self
, task
));