1 /* Cycript - Inlining/Optimizing JavaScript Compiler 
   2  * Copyright (C) 2009  Jay Freeman (saurik) 
   5 /* Modified BSD License {{{ */ 
   7  *        Redistribution and use in source and binary 
   8  * forms, with or without modification, are permitted 
   9  * provided that the following conditions are met: 
  11  * 1. Redistributions of source code must retain the 
  12  *    above copyright notice, this list of conditions 
  13  *    and the following disclaimer. 
  14  * 2. Redistributions in binary form must reproduce the 
  15  *    above copyright notice, this list of conditions 
  16  *    and the following disclaimer in the documentation 
  17  *    and/or other materials provided with the 
  19  * 3. The name of the author may not be used to endorse 
  20  *    or promote products derived from this software 
  21  *    without specific prior written permission. 
  23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' 
  24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
  25  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  27  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 
  28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  31  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
  34  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  36  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  41 #include <mach/mach.h> 
  43 #include <mach/i386/thread_status.h> 
  50 #include "Exception.hpp" 
  51 #include "Pooling.hpp" 
  52 #include "Trampoline.t.hpp" 
  54 extern "C" void __pthread_set_self(pthread_t
); 
  56 void InjectLibrary(pid_t pid
) { 
  57     // DOUG: turn this into some kind of -D passed from configure 
  58     const char *library("/usr/lib/libcycript.dylib"); 
  60     static const size_t Stack_(8 * 1024); 
  61     size_t length(strlen(library
) + 1), depth(sizeof(Baton
) + length
); 
  62     depth 
= (depth 
+ sizeof(uintptr_t) + 1) / sizeof(uintptr_t) * sizeof(uintptr_t); 
  65     uint8_t *local(reinterpret_cast<uint8_t *>(apr_palloc(pool
, depth
))); 
  66     Baton 
*baton(reinterpret_cast<Baton 
*>(local
)); 
  68     baton
->__pthread_set_self 
= &__pthread_set_self
; 
  70     baton
->pthread_create 
= &pthread_create
; 
  71     baton
->pthread_join 
= &pthread_join
; 
  73     baton
->dlopen 
= &dlopen
; 
  74     baton
->dlsym 
= &dlsym
; 
  76     baton
->mach_thread_self 
= &mach_thread_self
; 
  77     baton
->thread_terminate 
= &thread_terminate
; 
  79     baton
->pid 
= getpid(); 
  80     memcpy(baton
->library
, library
, length
); 
  82     vm_size_t 
size(depth 
+ Stack_
); 
  84     mach_port_t 
self(mach_task_self()), task
; 
  85     _krncall(task_for_pid(self
, pid
, &task
)); 
  88     _krncall(vm_allocate(task
, &stack
, size
, true)); 
  89     vm_address_t 
data(stack 
+ Stack_
); 
  91     vm_write(task
, data
, reinterpret_cast<vm_address_t
>(baton
), depth
); 
  94     _krncall(thread_create(task
, &thread
)); 
  96     thread_state_flavor_t flavor
; 
  97     mach_msg_type_number_t count
; 
 100     Trampoline 
*trampoline
; 
 103     trampoline 
= &Trampoline_arm_
; 
 104     arm_thread_state_t state
; 
 105     flavor 
= ARM_THREAD_STATE
; 
 106     count 
= ARM_THREAD_STATE_COUNT
; 
 108 #elif defined(__i386__) 
 109     trampoline 
= &Trampoline_i386_
; 
 110     i386_thread_state_t state
; 
 111     flavor 
= i386_THREAD_STATE
; 
 112     count 
= i386_THREAD_STATE_COUNT
; 
 114 #elif defined(__x86_64__) 
 115     trampoline 
= &Trampoline_x86_64_
; 
 116     x86_thread_state64_t state
; 
 117     flavor 
= x86_THREAD_STATE64
; 
 118     count 
= x86_THREAD_STATE64_COUNT
; 
 121     #error XXX: implement 
 125     _krncall(vm_allocate(task
, &code
, trampoline
->size_
, true)); 
 126     vm_write(task
, code
, reinterpret_cast<vm_address_t
>(trampoline
->data_
), trampoline
->size_
); 
 127     _krncall(vm_protect(task
, code
, trampoline
->size_
, false, VM_PROT_READ 
| VM_PROT_EXECUTE
)); 
 130     printf("_ptss:%p\n", baton->__pthread_set_self); 
 131     printf("dlsym:%p\n", baton->dlsym); 
 132     printf("code:%zx\n", (size_t) code); 
 135     uint32_t frame
[push
]; 
 136     if (sizeof(frame
) != 0) 
 137         memset(frame
, 0, sizeof(frame
)); 
 138     memset(&state
, 0, sizeof(state
)); 
 140     mach_msg_type_number_t 
read(count
); 
 141     _krncall(thread_get_state(thread
, flavor
, reinterpret_cast<thread_state_t
>(&state
), &read
)); 
 142     _assert(count 
== count
); 
 146     state
.sp 
= stack 
+ Stack_
; 
 147     state
.pc 
= code 
+ trampoline
->entry_
; 
 149     if ((state
.pc 
& 0x1) != 0) { 
 153 #elif defined(__i386__) 
 156     state
.__eip 
= code 
+ trampoline
->entry_
; 
 157     state
.__esp 
= stack 
+ Stack_ 
- sizeof(frame
); 
 158 #elif defined(__x86_64__) 
 159     frame
[0] = 0xdeadbeef; 
 161     state
.__rip 
= code 
+ trampoline
->entry_
; 
 162     state
.__rsp 
= stack 
+ Stack_ 
- sizeof(frame
); 
 164     #error XXX: implement 
 167     if (sizeof(frame
) != 0) 
 168         vm_write(task
, stack 
+ Stack_ 
- sizeof(frame
), reinterpret_cast<vm_address_t
>(frame
), sizeof(frame
)); 
 170     _krncall(thread_set_state(thread
, flavor
, reinterpret_cast<thread_state_t
>(&state
), count
)); 
 171     _krncall(thread_resume(thread
)); 
 173     _krncall(mach_port_deallocate(self
, task
));