├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── jni ├── Android.mk ├── Application.mk ├── injector │ ├── Android.mk │ ├── main.cpp │ └── traced.hpp └── libhook │ ├── Android.mk │ ├── hook.cpp │ ├── hook.h │ ├── hooks │ ├── io.cpp │ └── io.h │ ├── linker.h │ ├── main.cpp │ ├── report.cpp │ └── report.h ├── pyadb ├── __init__.py └── adb.py ├── test.py └── trace_pid.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.pyc 4 | injector/injector 5 | libs 6 | obj 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2015, Simone Margaritelli 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | * Neither the name of ARM Inject nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | @ndk-build -B 3 | 4 | clean: 5 | @rm -rf obj libs 6 | 7 | test: all 8 | python test.py 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ARM Inject 2 | === 3 | 4 | An application to dynamically inject a shared object into a running process on 5 | ARM architectures and hook API calls. 6 | 7 | Read more on: 8 | 9 | - [Dynamically inject a shared library into a running process on Android/ARM](http://www.evilsocket.net/2015/05/01/dynamically-inject-a-shared-library-into-a-running-process-on-androidarm/). 10 | - [Android Native API Hooking with Library Injection and ELF Introspection](http://www.evilsocket.net/2015/05/04/android-native-api-hooking-with-library-injecto/) 11 | 12 | ## How to Test 13 | 14 | In order to test this, you'll need the Android NDK installed and a device connected to your USB port, 15 | then simply run: 16 | 17 | make test 18 | 19 | This will launch a new Chrome browser instance and inject libhook into it. Once injected 20 | the library will hook the **open** function and print every call to it to the logcat. 21 | 22 | @ Pushing files to /data/local/tmp ... 23 | @ Starting com.android.chrome/com.google.android.apps.chrome.Main ... 24 | @ Injection into PID 18233 starting ... 25 | 26 | I/LIBHOOK (18233): LIBRARY LOADED FROM PID 18233. 27 | I/LIBHOOK (18233): Found 104 loaded modules. 28 | I/LIBHOOK (18233): Installing 12 hooks. 29 | I/LIBHOOK (18233): [0xA0861000] Hooking /data/app/com.android.chrome-2/lib/arm/libchrome.so ... 30 | I/LIBHOOK (18233): [0xA0A68000] Hooking /data/app/com.android.chrome-2/lib/arm/libchrome.so ... 31 | I/LIBHOOK (18233): [0xAB8A9000] Hooking /system/vendor/lib/egl/libGLESv2_adreno.so ... 32 | I/LIBHOOK (18233): [0xAB9EC000] Hooking /system/vendor/lib/egl/libGLESv1_CM_adreno.so ... 33 | I/LIBHOOK (18233): [0xABA20000] Hooking /system/vendor/lib/libgsl.so ... 34 | I/LIBHOOK (18233): open - 0xb6f31951 -> 0xa446577c 35 | I/LIBHOOK (18233): write - 0xb6f55ec8 -> 0xa4464d5c 36 | I/LIBHOOK (18233): read - 0xb6f56964 -> 0xa4464c70 37 | I/LIBHOOK (18233): close - 0xb6f552e8 -> 0xa4464e54 38 | I/LIBHOOK (18233): connect - 0xb6f30365 -> 0xa44657fc 39 | I/LIBHOOK (18233): sendto - 0xb6f562a0 -> 0xa4465020 40 | I/LIBHOOK (18233): recvfrom - 0xb6f5679c -> 0xa4465318 41 | I/LIBHOOK (18233): shutdown - 0xb6f566ac -> 0xa4465518 42 | I/LIBHOOK (18233): send - 0xb6f33851 -> 0xa4464f28 43 | I/LIBHOOK (18233): recvmsg - 0xb6f560c0 -> 0xa446542c 44 | I/LIBHOOK (18233): sendmsg - 0xb6f55de0 -> 0xa4465134 45 | ... 46 | ... 47 | I/LIBHOOK (18233): [18233] open('/dev/ashmem', 2) -> 18 48 | I/LIBHOOK (18233): [18233] close( '/dev/ashmem' ) -> 0 49 | I/LIBHOOK (18233): [18233] open('/dev/ashmem', 2) -> 18 50 | I/LIBHOOK (18233): [18233] close( '/dev/ashmem' ) -> 0 51 | I/LIBHOOK (18233): [18233] open('/data/data/com.android.chrome/shared_prefs/com.google.android.apps.chrome.omaha.xml', 0) -> 18 52 | I/LIBHOOK (18233): [18233] open('/dev/ashmem', 2) -> 19 53 | I/LIBHOOK (18233): [18233] close( '/dev/ashmem' ) -> 0 54 | I/LIBHOOK (18233): [18233] open('/dev/ashmem', 2) -> 19 55 | I/LIBHOOK (18233): [18233] close( '/dev/ashmem' ) -> 0 56 | I/LIBHOOK (18233): [18233] read( '/data/data/com.android.chrome/shared_prefs/com.google.android.apps.chrome.omaha.xml', 0xb007c00c, 16384 ) -> 655 57 | I/LIBHOOK (18233): [18233] close( '/data/data/com.android.chrome/shared_prefs/com.google.android.apps.chrome.omaha.xml' ) -> 0 58 | I/LIBHOOK (18233): [18233] write( 'pipe:[4020814]', W, 1, 2147483647 ) -> 1 59 | I/LIBHOOK (18233): [18233] write( '(14)', 18306, 5, -1601827487 ) -> 5 60 | I/LIBHOOK (18233): [18233] open('/dev/ashmem', 2) -> 22 61 | I/LIBHOOK (18233): [18233] close( '/dev/ashmem' ) -> 0 62 | I/LIBHOOK (18233): [18233] open('/dev/ashmem', 2) -> 22 63 | I/LIBHOOK (18233): [18233] close( '/dev/ashmem' ) -> 0 64 | I/LIBHOOK (18233): [18233] close( '(22)' ) -> 0 65 | I/LIBHOOK (18233): [18233] read( '(18)', 0xa0860b6c, 16 ) -> 1 66 | I/LIBHOOK (18233): [18233] close( '(24)' ) -> 0 67 | I/LIBHOOK (18233): [18233] close( '(22)' ) -> 0 68 | I/LIBHOOK (18233): [18233] open('/dev/ashmem', 2) -> 22 69 | I/LIBHOOK (18233): [18233] recvfrom( 'socket:[4043146]', nysv, 2400, 64, 0x0, 0 ) -> 24 70 | I/LIBHOOK (18233): [18233] recvfrom( 'socket:[4043146]', nysv, 2400, 64, 0x0, 0 ) -> -1 71 | I/LIBHOOK (18233): [18233] read( '(18)', 0xa0860b6c, 16 ) -> 1 72 | I/LIBHOOK (18233): [18233] write( 'pipe:[4020814]', W, 1, 2147483647 ) -> 1 73 | I/LIBHOOK (18233): [18233] recvfrom( 'socket:[4043184]', , 2264, 64, 0x0, 0 ) -> -1 74 | I/LIBHOOK (18233): [18233] write( 'pipe:[4043980]', W, 1, -1 ) -> 1 75 | ... 76 | ... 77 | @ CTRL+C detected, killing process ... 78 | 79 | ## Note 80 | 81 | Most of the ELF manipulation code inside the file hook.cpp of libhook was taken from the **Andrey Petrov**'s 82 | blog post "[Android hacking: hooking system functions used by Dalvik](http://shadowwhowalks.blogspot.it/2013/01/android-hacking-hooking-system.html 83 | )" and fixed by me ( the original source code didn't work due to page align, memory protection, etc ). 84 | 85 | ## License 86 | 87 | Released under the BSD license. 88 | Copyright © 2015, Simone Margaritelli 89 | All rights reserved. 90 | -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(call all-subdir-makefiles) 4 | -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-19 2 | APP_ABI := armeabi-v7a 3 | APP_STL := stlport_static 4 | APP_PIE := true 5 | 6 | APP_CXXFLAGS := -Wall -Werror -fpermissive -fpic 7 | -------------------------------------------------------------------------------- /jni/injector/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := injector 6 | LOCAL_SRC_FILES := main.cpp 7 | 8 | include $(BUILD_EXECUTABLE) 9 | -------------------------------------------------------------------------------- /jni/injector/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Simone Margaritelli 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of ARM Inject nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #include "traced.hpp" 30 | #include 31 | 32 | int usage( char *argvz ){ 33 | printf( "Usage: %s \n", argvz ); 34 | return 1; 35 | } 36 | 37 | int main( int argc, char **argv ) 38 | { 39 | if( argc < 3 ){ 40 | return usage(argv[0]); 41 | } 42 | else if( geteuid() != 0 ){ 43 | fprintf( stderr, "This script must be executed as root.\n" ); 44 | return 1; 45 | } 46 | 47 | pid_t pid = atoi(argv[1]); 48 | std::string library = argv[2]; 49 | 50 | if( pid == 0 ){ 51 | fprintf( stderr, "Invaid PID %s\n", argv[1] ); 52 | return 1; 53 | } 54 | 55 | Traced proc(pid); 56 | 57 | printf( "@ Injecting library %s into process %d.\n\n", library.c_str(), pid ); 58 | 59 | printf( "@ Calling dlopen in target process ...\n" ); 60 | 61 | unsigned long dlret = proc.dlopen( library.c_str() ); 62 | 63 | printf( "@ dlopen returned 0x%lX\n", dlret ); 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /jni/injector/traced.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Simone Margaritelli 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of ARM Inject nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef TRACED_H__ 30 | #define TRACED_H__ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #define CPSR_T_MASK ( 1u << 5 ) 46 | 47 | class Traced 48 | { 49 | private: 50 | 51 | pid_t _pid; 52 | 53 | void *_dlopen; 54 | void *_dlsym; 55 | void *_dlerror; 56 | void *_calloc; 57 | void *_free; 58 | 59 | // ptrace wrapper with some error checking. 60 | long trace( int request, void *addr = 0, size_t data = 0 ) { 61 | long ret = ptrace( request, _pid, (caddr_t)addr, (void *)data ); 62 | if( ret == -1 && (errno == EBUSY || errno == EFAULT || errno == ESRCH) ){ 63 | perror("ptrace"); 64 | return -1; 65 | } 66 | return ret; 67 | } 68 | 69 | public: 70 | 71 | /* 72 | * This method will open /proc//maps and search for the specified 73 | * library base address. 74 | */ 75 | uintptr_t findLibrary( const char *library, pid_t pid = -1 ) { 76 | char filename[0xFF] = {0}, 77 | buffer[1024] = {0}; 78 | FILE *fp = NULL; 79 | uintptr_t address = 0; 80 | 81 | sprintf( filename, "/proc/%d/maps", pid == -1 ? _pid : pid ); 82 | 83 | fp = fopen( filename, "rt" ); 84 | if( fp == NULL ){ 85 | perror("fopen"); 86 | goto done; 87 | } 88 | 89 | while( fgets( buffer, sizeof(buffer), fp ) ) { 90 | if( strstr( buffer, library ) ){ 91 | address = (uintptr_t)strtoul( buffer, NULL, 16 ); 92 | goto done; 93 | } 94 | } 95 | 96 | done: 97 | 98 | if(fp){ 99 | fclose(fp); 100 | } 101 | 102 | return address; 103 | } 104 | 105 | /* 106 | * Compute the delta of the local and the remote modules and apply it to 107 | * the local address of the symbol ... BOOM, remote symbol address! 108 | */ 109 | void *findFunction( const char* library, void* local_addr ){ 110 | uintptr_t local_handle, remote_handle; 111 | 112 | local_handle = findLibrary( library, getpid() ); 113 | remote_handle = findLibrary( library ); 114 | 115 | return (void *)( (uintptr_t)local_addr + (uintptr_t)remote_handle - (uintptr_t)local_handle ); 116 | } 117 | 118 | /* 119 | * Read 'blen' bytes from the remote process at 'addr' address. 120 | */ 121 | bool read( size_t addr, unsigned char *buf, size_t blen ){ 122 | size_t i = 0; 123 | long ret = 0; 124 | 125 | for( i = 0; i < blen; i += sizeof(size_t) ){ 126 | ret = trace( PTRACE_PEEKTEXT, (void *)(addr + i) ); 127 | if( ret == -1 ) { 128 | return false; 129 | } 130 | 131 | memcpy( &buf[i], &ret, sizeof(ret) ); 132 | } 133 | 134 | return true; 135 | } 136 | 137 | /* 138 | * Write 'blen' bytes to the remote process at 'addr' address. 139 | */ 140 | bool write( size_t addr, unsigned char *buf, size_t blen){ 141 | size_t i = 0; 142 | long ret; 143 | 144 | // make sure the buffer is word aligned 145 | char *ptr = (char *)calloc(blen + blen % sizeof(size_t), 1); 146 | memcpy(ptr, buf, blen); 147 | 148 | for( i = 0; i < blen; i += sizeof(size_t) ){ 149 | ret = trace( PTRACE_POKETEXT, (void *)(addr + i), *(size_t *)&ptr[i] ); 150 | if( ret == -1 ) { 151 | ::free(ptr); 152 | return false; 153 | } 154 | } 155 | 156 | ::free(ptr); 157 | 158 | return true; 159 | } 160 | 161 | /* 162 | * Remotely call the remote function given its address, the number of 163 | * arguments and the arguments themselves. 164 | */ 165 | unsigned long call( void *function, int nargs, ... ) { 166 | int i = 0; 167 | struct pt_regs regs = {{0}}, rbackup = {{0}}; 168 | 169 | // get registers and backup them 170 | trace( PTRACE_GETREGS, 0, (size_t)®s ); 171 | memcpy( &rbackup, ®s, sizeof(struct pt_regs) ); 172 | 173 | va_list vl; 174 | va_start(vl,nargs); 175 | 176 | for( i = 0; i < nargs; ++i ){ 177 | unsigned long arg = va_arg( vl, long ); 178 | 179 | // fill R0-R3 with the first 4 arguments 180 | if( i < 4 ){ 181 | regs.uregs[i] = arg; 182 | } 183 | // push remaining params onto stack 184 | else { 185 | regs.ARM_sp -= sizeof(long) ; 186 | write( (size_t)regs.ARM_sp, (uint8_t *)&arg, sizeof(long) ); 187 | } 188 | } 189 | 190 | va_end(vl); 191 | 192 | regs.ARM_lr = 0; 193 | regs.ARM_pc = (long int)function; 194 | // setup the current processor status register 195 | if ( regs.ARM_pc & 1 ){ 196 | /* thumb */ 197 | regs.ARM_pc &= (~1u); 198 | regs.ARM_cpsr |= CPSR_T_MASK; 199 | } 200 | else{ 201 | /* arm */ 202 | regs.ARM_cpsr &= ~CPSR_T_MASK; 203 | } 204 | 205 | // do the call 206 | trace( PTRACE_SETREGS, 0, (size_t)®s ); 207 | trace( PTRACE_CONT ); 208 | waitpid( _pid, NULL, WUNTRACED ); 209 | 210 | // get registers again, R0 holds the return value 211 | trace( PTRACE_GETREGS, 0, (size_t)®s ); 212 | 213 | // restore original registers state 214 | trace( PTRACE_SETREGS, 0, (size_t)&rbackup ); 215 | 216 | return regs.ARM_r0; 217 | } 218 | 219 | // Copy a given string into the remote process memory. 220 | unsigned long copyString( const char *s ) { 221 | unsigned long mem = call( _calloc, 2, strlen(s) + 1, 1 ); 222 | 223 | write( mem, (unsigned char *)s, strlen(s) + 1 ); 224 | 225 | return mem; 226 | } 227 | 228 | // Remotely force the target process to dlopen a library. 229 | unsigned long dlopen( const char *libname ) { 230 | unsigned long pmem = copyString(libname); 231 | unsigned long plib = call( _dlopen, 2, pmem, 0 ); 232 | 233 | free(pmem); 234 | 235 | return plib; 236 | } 237 | 238 | // Remotely call dlsym on the target process. 239 | unsigned long dlsym( unsigned long dl, const char *symname ) { 240 | unsigned long pmem = copyString(symname); 241 | unsigned long psym = call( _dlsym, 2, dl, pmem ); 242 | 243 | free(pmem); 244 | 245 | return psym; 246 | } 247 | 248 | // Free remotely allocated memory. 249 | void free( unsigned long p ) { 250 | call( _free, 1, p ); 251 | } 252 | 253 | Traced( pid_t pid ) : _pid(pid) { 254 | if( trace( PTRACE_ATTACH ) != -1 ){ 255 | int status; 256 | waitpid( _pid, &status, 0 ); 257 | 258 | /* 259 | * First thing first, we need to search these functions into the target 260 | * process address space. 261 | */ 262 | _dlopen = findFunction( "/system/bin/linker", (void *)::dlopen ); 263 | _dlsym = findFunction( "/system/bin/linker", (void *)::dlsym ); 264 | _dlerror = findFunction( "/system/bin/linker", (void *)::dlerror ); 265 | _calloc = findFunction( "/system/lib/libc.so", (void *)::calloc ); 266 | _free = findFunction( "/system/lib/libc.so", (void *)::free ); 267 | 268 | if( !_calloc ){ 269 | fprintf( stderr, "Could not find calloc symbol.\n" ); 270 | } 271 | else if( !_free ){ 272 | fprintf( stderr, "Could not find dlopen symbol.\n" ); 273 | } 274 | else if( !_dlopen ){ 275 | fprintf( stderr, "Could not find dlopen symbol.\n" ); 276 | } 277 | else if( !_dlsym ){ 278 | fprintf( stderr, "Could not find dlsym symbol.\n" ); 279 | } 280 | else if( !_dlerror ){ 281 | fprintf( stderr, "Could not find dlerror symbol.\n" ); 282 | } 283 | } 284 | else { 285 | fprintf( stderr, "Failed to attach to process %d.", _pid ); 286 | } 287 | } 288 | 289 | virtual ~Traced() { 290 | trace( PTRACE_DETACH ); 291 | } 292 | }; 293 | 294 | #endif 295 | -------------------------------------------------------------------------------- /jni/libhook/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := libhook 6 | LOCAL_SRC_FILES := main.cpp hook.cpp report.cpp hooks/io.cpp 7 | LOCAL_LDLIBS := -llog 8 | 9 | include $(BUILD_SHARED_LIBRARY) 10 | -------------------------------------------------------------------------------- /jni/libhook/hook.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Simone Margaritelli 3 | * All rights reserved. 4 | * 5 | * Most of the ELF manipulation code was taken from the Andrey Petrov's 6 | * blog post "Android hacking: hooking system functions used by Dalvik" 7 | * http://shadowwhowalks.blogspot.it/2013/01/android-hacking-hooking-system.html 8 | * and fixed by me. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions are met: 12 | * 13 | * * Redistributions of source code must retain the above copyright notice, 14 | * this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * * Neither the name of ARM Inject nor the names of its contributors may be used 19 | * to endorse or promote products derived from this software without 20 | * specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | #include "hook.h" 35 | #include 36 | 37 | 38 | static unsigned elfhash(const char *_name) { 39 | const unsigned char *name = (const unsigned char *) _name; 40 | unsigned h = 0, g; 41 | while(*name) { 42 | h = (h << 4) + *name++; 43 | g = h & 0xf0000000; 44 | h ^= g; 45 | h ^= g >> 24; 46 | } 47 | return h; 48 | } 49 | 50 | static Elf32_Sym *soinfo_elf_lookup(struct soinfo *si, unsigned hash, const char *name) { 51 | Elf32_Sym *symtab = si->symtab; 52 | const char *strtab = si->strtab; 53 | unsigned n; 54 | 55 | for( n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n] ) { 56 | Elf32_Sym *s = symtab + n; 57 | if( strcmp(strtab + s->st_name, name) == 0 ) { 58 | return s; 59 | } 60 | } 61 | 62 | return NULL; 63 | } 64 | 65 | static uint32_t gnuhash(const char *_name) { 66 | uint32_t h = 5381; 67 | const uint8_t* name = reinterpret_cast(_name); 68 | while (*name != 0) { 69 | h += (h << 5) + *name++; // h*33 + c = h + h * 32 + c = h + h << 5 + c 70 | } 71 | return h; 72 | } 73 | 74 | static Elf32_Sym *soinfo_gnu_lookup(struct soinfo *si, uint32_t hash, const char *name) 75 | { 76 | uint32_t h2 = hash >> si->gnu_shift2_; 77 | 78 | uint32_t bloom_mask_bits = sizeof(uintptr_t) * 8; 79 | uint32_t word_num = (hash / bloom_mask_bits) & si->gnu_maskwords_; 80 | uintptr_t bloom_word = si->gnu_bloom_filter_[word_num]; 81 | 82 | if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) { 83 | return NULL; 84 | } 85 | 86 | uint32_t n = si->gnu_bucket_[hash % si->gnu_nbucket_]; 87 | if (n == 0) { 88 | return NULL; 89 | } 90 | 91 | do { 92 | Elf32_Sym* s = si->symtab + n; 93 | 94 | if (((si->gnu_chain_[n] ^ hash) >> 1) == 0 && 95 | strcmp(si->strtab + s->st_name, name) == 0) { 96 | return s; 97 | } 98 | } while ((si->gnu_chain_[n++] & 1) == 0); 99 | 100 | return NULL; 101 | } 102 | 103 | ld_modules_t libhook_get_modules() { 104 | ld_modules_t modules; 105 | char buffer[1024] = {0}; 106 | uintptr_t address; 107 | std::string name; 108 | 109 | FILE *fp = fopen( "/proc/self/maps", "rt" ); 110 | if( fp == NULL ){ 111 | perror("fopen"); 112 | goto done; 113 | } 114 | 115 | while( fgets( buffer, sizeof(buffer), fp ) ) { 116 | if( strstr( buffer, "r-xp" ) ){ 117 | address = (uintptr_t)strtoul( buffer, NULL, 16 ); 118 | name = strrchr( buffer, ' ' ) + 1; 119 | name.resize( name.size() - 1 ); 120 | 121 | modules.push_back( ld_module_t( address, name ) ); 122 | } 123 | } 124 | 125 | done: 126 | 127 | if(fp){ 128 | fclose(fp); 129 | } 130 | 131 | return modules; 132 | } 133 | 134 | unsigned libhook_patch_address( unsigned addr, unsigned newval ) { 135 | unsigned original = -1; 136 | size_t pagesize = sysconf(_SC_PAGESIZE); 137 | const void *aligned_pointer = (const void*)(addr & ~(pagesize - 1)); 138 | 139 | mprotect(aligned_pointer, pagesize, PROT_WRITE | PROT_READ); 140 | 141 | original = *(unsigned *)addr; 142 | *((unsigned*)addr) = newval; 143 | 144 | mprotect(aligned_pointer, pagesize, PROT_READ); 145 | 146 | return original; 147 | } 148 | 149 | unsigned libhook_addhook( const char *soname, const char *symbol, unsigned newval ) { 150 | struct soinfo *si = NULL; 151 | Elf32_Rel *rel = NULL; 152 | Elf32_Sym *s = NULL; 153 | unsigned int sym_offset = 0; 154 | size_t i; 155 | 156 | // since we know the module is already loaded and mostly 157 | // we DO NOT want its constructors to be called again, 158 | // ise RTLD_NOLOAD to just get its soinfo address. 159 | si = (struct soinfo *)dlopen( soname, 4 /* RTLD_NOLOAD */ ); 160 | if( !si ){ 161 | HOOKLOG( "dlopen error: %s.", dlerror() ); 162 | return 0; 163 | } 164 | 165 | if ((si->flags & FLAG_GNU_HASH) != 0) 166 | { 167 | s = soinfo_gnu_lookup(si, gnuhash(symbol), symbol); 168 | } 169 | else 170 | { 171 | s = soinfo_elf_lookup(si, elfhash(symbol), symbol); 172 | } 173 | 174 | if(!s && 175 | // GNU hash table doesn't contain relocation symbols. 176 | // We still need to search the .rel.plt section for the symbol 177 | (si->flags & FLAG_GNU_HASH) == 0) 178 | { 179 | return 0; 180 | } 181 | 182 | sym_offset = s - si->symtab; 183 | 184 | // loop reloc table to find the symbol by index 185 | for( i = 0, rel = si->plt_rel; i < si->plt_rel_count; ++i, ++rel ) { 186 | unsigned type = ELF32_R_TYPE(rel->r_info); 187 | unsigned sym = ELF32_R_SYM(rel->r_info); 188 | unsigned reloc = (unsigned)(rel->r_offset + si->load_bias); 189 | 190 | if( sym_offset == sym || 191 | strcmp(si->strtab + ((Elf32_Sym*)(si->symtab + sym))->st_name, symbol) == 0) { 192 | switch(type) { 193 | case R_ARM_JUMP_SLOT: 194 | 195 | return libhook_patch_address( reloc, newval ); 196 | 197 | default: 198 | 199 | HOOKLOG( "Expected R_ARM_JUMP_SLOT, found 0x%X", type ); 200 | } 201 | } 202 | } 203 | 204 | unsigned original = 0; 205 | 206 | // loop dyn reloc table 207 | for( i = 0, rel = si->rel; i < si->rel_count; ++i, ++rel ) { 208 | unsigned type = ELF32_R_TYPE(rel->r_info); 209 | unsigned sym = ELF32_R_SYM(rel->r_info); 210 | unsigned reloc = (unsigned)(rel->r_offset + si->load_bias); 211 | 212 | if( sym_offset == sym || 213 | strcmp(si->strtab + ((Elf32_Sym*)(si->symtab + sym))->st_name, symbol) == 0) { 214 | switch(type) { 215 | case R_ARM_ABS32: 216 | case R_ARM_GLOB_DAT: 217 | 218 | original = libhook_patch_address( reloc, newval ); 219 | 220 | default: 221 | 222 | HOOKLOG( "Expected R_ARM_ABS32 or R_ARM_GLOB_DAT, found 0x%X", type ); 223 | } 224 | } 225 | } 226 | 227 | if( original == 0 ){ 228 | HOOKLOG( "Unable to find symbol in the reloc tables ( plt_rel_count=%u - rel_count=%u ).", si->plt_rel_count, si->rel_count ); 229 | } 230 | 231 | return original; 232 | } 233 | -------------------------------------------------------------------------------- /jni/libhook/hook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Simone Margaritelli 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of ARM Inject nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef HOOK_H 30 | #define HOOK_H 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "linker.h" 40 | 41 | #define HOOKLOG(F,...) \ 42 | __android_log_print( ANDROID_LOG_INFO, "LIBHOOK", F, __VA_ARGS__ ) 43 | 44 | #define ORIGINAL( TYPENAME, ... ) \ 45 | ((TYPENAME ## _t)find_original( #TYPENAME ))( __VA_ARGS__ ) 46 | 47 | #define DEFINEHOOK( RET_TYPE, NAME, ARGS ) \ 48 | typedef RET_TYPE (* NAME ## _t)ARGS; \ 49 | RET_TYPE hook_ ## NAME ARGS 50 | 51 | #define ADDHOOK( NAME ) \ 52 | { #NAME, 0, (uintptr_t)&hook_ ## NAME } 53 | 54 | typedef struct ld_module 55 | { 56 | uintptr_t address; 57 | std::string name; 58 | 59 | ld_module( uintptr_t a, const std::string& n ) : address(a), name(n) { 60 | 61 | } 62 | } 63 | ld_module_t; 64 | 65 | typedef std::vector ld_modules_t; 66 | 67 | ld_modules_t libhook_get_modules(); 68 | unsigned libhook_addhook( const char *soname, const char *symbol, unsigned newval ); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /jni/libhook/hooks/io.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Simone Margaritelli 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of ARM Inject nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #include "hook.h" 30 | #include "io.h" 31 | #include "report.h" 32 | #include 33 | #include 34 | #include 35 | 36 | typedef std::map< int, std::string > fds_map_t; 37 | 38 | static pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER; 39 | static fds_map_t __descriptors; 40 | 41 | #define LOCK() pthread_mutex_lock(&__lock) 42 | #define UNLOCK() pthread_mutex_unlock(&__lock) 43 | 44 | extern uintptr_t find_original( const char *name ); 45 | 46 | void io_add_descriptor( int fd, const char *name ) { 47 | LOCK(); 48 | 49 | __descriptors[fd] = name; 50 | 51 | UNLOCK(); 52 | } 53 | 54 | void io_del_descriptor( int fd ) { 55 | LOCK(); 56 | 57 | fds_map_t::iterator i = __descriptors.find(fd); 58 | if( i != __descriptors.end() ){ 59 | __descriptors.erase(i); 60 | } 61 | 62 | UNLOCK(); 63 | } 64 | 65 | std::string io_resolve_descriptor( int fd ) { 66 | std::string name; 67 | 68 | LOCK(); 69 | 70 | fds_map_t::iterator i = __descriptors.find(fd); 71 | if( i == __descriptors.end() ){ 72 | // attempt to read descriptor from /proc/self/fd 73 | char descpath[0xFF] = {0}, 74 | descbuff[0xFF] = {0}; 75 | 76 | sprintf( descpath, "/proc/self/fd/%d", fd ); 77 | if( readlink( descpath, descbuff, 0xFF ) != -1 ){ 78 | name = descbuff; 79 | } 80 | else { 81 | std::ostringstream s; 82 | s << "(" << fd << ")"; 83 | name = s.str(); 84 | } 85 | } 86 | else { 87 | name = i->second; 88 | } 89 | 90 | UNLOCK(); 91 | 92 | return name; 93 | } 94 | 95 | DEFINEHOOK( int, open, (const char *pathname, int flags) ) { 96 | int fd = ORIGINAL( open, pathname, flags ); 97 | 98 | if( fd != -1 ){ 99 | io_add_descriptor( fd, pathname ); 100 | } 101 | 102 | report_add( "open", "si.i", 103 | "pathname", pathname, 104 | "flags", flags, 105 | fd ); 106 | 107 | return fd; 108 | } 109 | 110 | DEFINEHOOK( ssize_t, read, (int fd, void *buf, size_t count) ) { 111 | ssize_t r = ORIGINAL( read, fd, buf, count ); 112 | 113 | report_add( "read", "spu.i", 114 | "fd", io_resolve_descriptor(fd).c_str(), 115 | "buf", buf, 116 | "count", count, 117 | r ); 118 | 119 | return r; 120 | } 121 | 122 | DEFINEHOOK( ssize_t, write, (int fd, const void *buf, size_t len, int flags) ) { 123 | ssize_t wrote = ORIGINAL( write, fd, buf, len, flags ); 124 | 125 | report_add( "write", "spui.i", 126 | "fd", io_resolve_descriptor(fd).c_str(), 127 | "buf", buf, 128 | "len", len, 129 | "flags", flags, 130 | wrote ); 131 | 132 | return wrote; 133 | } 134 | 135 | DEFINEHOOK( int, close, (int fd) ) { 136 | int c = ORIGINAL( close, fd ); 137 | 138 | report_add( "close", "s.i", 139 | "fd", io_resolve_descriptor(fd).c_str(), 140 | c ); 141 | 142 | io_del_descriptor( fd ); 143 | 144 | return c; 145 | } 146 | 147 | DEFINEHOOK( int, connect, (int sockfd, const struct sockaddr *addr, socklen_t addrlen) ) { 148 | int ret = ORIGINAL( connect, sockfd, addr, addrlen ); 149 | 150 | struct sockaddr_in *addr_in = (struct sockaddr_in *)addr; 151 | std::ostringstream s; 152 | 153 | if( addr_in->sin_family == 1 ){ 154 | struct sockaddr_un *sun = (struct sockaddr_un *)addr; 155 | 156 | s << "unix://" << sun->sun_path; 157 | } 158 | else { 159 | s << "ip://" << inet_ntoa(addr_in->sin_addr); 160 | } 161 | 162 | if( ret == 0 ){ 163 | io_add_descriptor( sockfd, s.str().c_str() ); 164 | } 165 | 166 | report_add( "connect", "spd.i", 167 | "sockfd", io_resolve_descriptor(sockfd).c_str(), 168 | "addr", addr, 169 | "addrlen", addrlen, 170 | ret ); 171 | 172 | return ret; 173 | } 174 | 175 | DEFINEHOOK( ssize_t, send, (int sockfd, const void *buf, size_t len, int flags) ) { 176 | ssize_t sent = ORIGINAL( send, sockfd, buf, len, flags ); 177 | 178 | report_add( "send", "spui.i", 179 | "sockfd", io_resolve_descriptor(sockfd).c_str(), 180 | "buf", buf, 181 | "len", len, 182 | "flags", flags, 183 | sent ); 184 | 185 | return sent; 186 | } 187 | 188 | DEFINEHOOK( ssize_t, sendto, (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) ) { 189 | ssize_t sent = ORIGINAL( sendto, sockfd, buf, len, flags, dest_addr, addrlen ); 190 | 191 | report_add( "sendto", "spuibu.i", 192 | "sockfd", io_resolve_descriptor(sockfd).c_str(), 193 | "buf", buf, 194 | "len", len, 195 | "flags", flags, 196 | "dest_addr", dest_addr, 197 | "addrlen", addrlen, 198 | sent ); 199 | 200 | return sent; 201 | } 202 | 203 | DEFINEHOOK( ssize_t, sendmsg, (int sockfd, const struct msghdr *msg, int flags) ) { 204 | ssize_t sent = ORIGINAL( sendmsg, sockfd, msg, flags ); 205 | 206 | report_add( "sendmsg", "spi.i", 207 | "sockfd", io_resolve_descriptor(sockfd).c_str(), 208 | "msg", msg, 209 | "flags", flags, 210 | sent ); 211 | 212 | return sent; 213 | } 214 | 215 | DEFINEHOOK( ssize_t, recv, (int sockfd, const void *buf, size_t len, int flags) ) { 216 | ssize_t recvd = ORIGINAL( recv, sockfd, buf, len, flags ); 217 | 218 | report_add( "recv", "spui.i", 219 | "sockfd", io_resolve_descriptor(sockfd).c_str(), 220 | "buf", buf, 221 | "len", len, 222 | "flags", flags, 223 | recvd ); 224 | 225 | return recvd; 226 | } 227 | 228 | DEFINEHOOK( ssize_t, recvfrom, (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) ) { 229 | ssize_t recvd = ORIGINAL( recvfrom, sockfd, buf, len, flags, dest_addr, addrlen ); 230 | 231 | report_add( "recvfrom", "spuipu.i", 232 | "sockfd", io_resolve_descriptor(sockfd).c_str(), 233 | "buf", buf, 234 | "len", len, 235 | "flags", flags, 236 | "dest_addr", dest_addr, 237 | "addrlen", addrlen, 238 | recvd ); 239 | 240 | return recvd; 241 | } 242 | 243 | DEFINEHOOK( ssize_t, recvmsg, (int sockfd, const struct msghdr *msg, int flags) ) { 244 | ssize_t recvd = ORIGINAL( recvmsg, sockfd, msg, flags ); 245 | 246 | report_add( "recvmsg", "spi.i", 247 | "sockfd", io_resolve_descriptor(sockfd).c_str(), 248 | "msg", msg, 249 | "flags", flags, 250 | recvd ); 251 | 252 | return recvd; 253 | } 254 | 255 | DEFINEHOOK( int, shutdown, (int sockfd, int how) ) { 256 | int ret = ORIGINAL( shutdown, sockfd, how ); 257 | 258 | report_add( "shutdown", "si.i", 259 | "sockfd", io_resolve_descriptor(sockfd).c_str(), 260 | "how", how, 261 | ret ); 262 | 263 | return ret; 264 | } 265 | -------------------------------------------------------------------------------- /jni/libhook/hooks/io.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Simone Margaritelli 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of ARM Inject nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef IO_H 30 | #define IO_H 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | int hook_open(const char *pathname, int flags); 38 | ssize_t hook_write(int fd, const void *buf, size_t len, int flags); 39 | ssize_t hook_read(int fd, void *buf, size_t count); 40 | int hook_close(int fd); 41 | 42 | int hook_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 43 | ssize_t hook_send(int sockfd, const void *buf, size_t len, int flags); 44 | ssize_t hook_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); 45 | ssize_t hook_sendmsg(int sockfd, const struct msghdr *msg, int flags); 46 | ssize_t hook_recv(int sockfd, const void *buf, size_t len, int flags); 47 | ssize_t hook_recvfrom(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); 48 | ssize_t hook_recvmsg(int sockfd, const struct msghdr *msg, int flags); 49 | int hook_shutdown(int sockfd, int how); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /jni/libhook/linker.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Simone Margaritelli 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of ARM Inject nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef LINKER_H_ 30 | #define LINKER_H_ 31 | 32 | #include 33 | 34 | #define ANDROID_ARM_LINKER 1 35 | 36 | #define SOINFO_NAME_LEN 128 37 | #define FLAG_GNU_HASH 0x00000040 38 | 39 | typedef Elf32_Half Elf32_Versym; 40 | 41 | struct link_map 42 | { 43 | uintptr_t l_addr; 44 | char * l_name; 45 | uintptr_t l_ld; 46 | struct link_map * l_next; 47 | struct link_map * l_prev; 48 | }; 49 | 50 | struct soinfo_list_t 51 | { 52 | void * head; 53 | void * tail; 54 | }; 55 | 56 | struct soinfo 57 | { 58 | const char name[SOINFO_NAME_LEN]; 59 | Elf32_Phdr *phdr; 60 | int phnum; 61 | unsigned entry; 62 | unsigned base; 63 | unsigned size; 64 | int unused; // DO NOT USE, maintained for compatibility. 65 | unsigned *dynamic; 66 | unsigned wrprotect_start; 67 | unsigned wrprotect_end; 68 | struct soinfo *next; 69 | unsigned flags; 70 | const char *strtab; 71 | Elf32_Sym *symtab; 72 | unsigned nbucket; 73 | unsigned nchain; 74 | unsigned *bucket; 75 | unsigned *chain; 76 | unsigned *plt_got; 77 | Elf32_Rel *plt_rel; 78 | unsigned plt_rel_count; 79 | Elf32_Rel *rel; 80 | unsigned rel_count; 81 | unsigned *preinit_array; 82 | unsigned preinit_array_count; 83 | unsigned *init_array; 84 | unsigned init_array_count; 85 | unsigned *fini_array; 86 | unsigned fini_array_count; 87 | void (*init_func)(void); 88 | void (*fini_func)(void); 89 | #ifdef ANDROID_ARM_LINKER 90 | /* ARM EABI section used for stack unwinding. */ 91 | unsigned *ARM_exidx; 92 | unsigned ARM_exidx_count; 93 | #endif 94 | unsigned refcount; 95 | struct link_map linkmap; 96 | int constructors_called; 97 | 98 | unsigned *load_bias; 99 | 100 | #if !defined(__LP64__) 101 | bool has_text_relocations; 102 | #endif 103 | bool has_DT_SYMBOLIC; 104 | 105 | // version >= 0 106 | dev_t st_dev_; 107 | ino_t st_ino_; 108 | 109 | soinfo_list_t children_; 110 | soinfo_list_t parents_; 111 | 112 | // version >= 1 113 | off64_t file_offset_; 114 | uint32_t rtld_flags_; 115 | uint32_t dt_flags_1_; 116 | size_t strtab_size_; 117 | 118 | // version >= 2 119 | size_t gnu_nbucket_; 120 | uint32_t *gnu_bucket_; 121 | uint32_t *gnu_chain_; 122 | uint32_t gnu_maskwords_; 123 | uint32_t gnu_shift2_; 124 | unsigned *gnu_bloom_filter_; 125 | 126 | soinfo* local_group_root_; 127 | 128 | uint8_t* android_relocs_; 129 | size_t android_relocs_size_; 130 | 131 | const char* soname_; 132 | std::string realpath_; 133 | 134 | const Elf32_Versym* versym_; 135 | 136 | unsigned *verdef_ptr_; 137 | size_t verdef_cnt_; 138 | 139 | unsigned *verneed_ptr_; 140 | size_t verneed_cnt_; 141 | 142 | uint32_t target_sdk_version_; 143 | 144 | std::vector dt_runpath_; 145 | }; 146 | 147 | #define R_ARM_ABS32 2 148 | #define R_ARM_COPY 20 149 | #define R_ARM_GLOB_DAT 21 150 | #define R_ARM_JUMP_SLOT 22 151 | #define R_ARM_RELATIVE 23 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /jni/libhook/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Simone Margaritelli 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of ARM Inject nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #include "hook.h" 30 | #include "hooks/io.h" 31 | 32 | typedef struct 33 | { 34 | const char *name; 35 | uintptr_t original; 36 | uintptr_t hook; 37 | } 38 | hook_t; 39 | 40 | static hook_t __hooks[] = { 41 | 42 | ADDHOOK( open ), 43 | ADDHOOK( write ), 44 | ADDHOOK( read ), 45 | ADDHOOK( close ), 46 | ADDHOOK( connect ), 47 | ADDHOOK( send ), 48 | ADDHOOK( sendto ), 49 | ADDHOOK( sendmsg ), 50 | ADDHOOK( recv ), 51 | ADDHOOK( recvfrom ), 52 | ADDHOOK( recvmsg ), 53 | ADDHOOK( shutdown ) 54 | }; 55 | 56 | #define NHOOKS ( sizeof(__hooks) / sizeof(__hooks[0] ) ) 57 | 58 | uintptr_t find_original( const char *name ) { 59 | for( size_t i = 0; i < NHOOKS; ++i ) { 60 | if( strcmp( __hooks[i].name, name ) == 0 ){ 61 | return __hooks[i].original; 62 | } 63 | } 64 | 65 | HOOKLOG( "[%d] !!! COULD NOT FIND ORIGINAL POINTER OF FUNCTION '%s' !!!", getpid(), name ); 66 | 67 | return 0; 68 | } 69 | 70 | void __attribute__ ((constructor)) libhook_main() 71 | { 72 | HOOKLOG( "LIBRARY LOADED FROM PID %d.", getpid() ); 73 | 74 | // get a list of all loaded modules inside this process. 75 | ld_modules_t modules = libhook_get_modules(); 76 | 77 | HOOKLOG( "Found %u loaded modules.", modules.size() ); 78 | HOOKLOG( "Installing %u hooks.", NHOOKS ); 79 | 80 | for( ld_modules_t::const_iterator i = modules.begin(), e = modules.end(); i != e; ++i ){ 81 | // don't hook ourself :P 82 | if( i->name.find( "libhook.so" ) == std::string::npos ) { 83 | HOOKLOG( "[0x%X] Hooking %s ...", i->address, i->name.c_str() ); 84 | 85 | for( size_t j = 0; j < NHOOKS; ++j ) { 86 | unsigned tmp = libhook_addhook( i->name.c_str(), __hooks[j].name, __hooks[j].hook ); 87 | 88 | // update the original pointer only if the reference we found is valid 89 | // and the pointer itself doesn't have a value yet. 90 | if( __hooks[j].original == 0 && tmp != 0 ){ 91 | __hooks[j].original = (uintptr_t)tmp; 92 | 93 | HOOKLOG( " %s - 0x%x -> 0x%x", __hooks[j].name, __hooks[j].original, __hooks[j].hook ); 94 | } 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /jni/libhook/report.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Simone Margaritelli 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of ARM Inject nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #include "report.h" 30 | #include "hook.h" 31 | #include 32 | #include 33 | #include 34 | 35 | #define LOCK() pthread_mutex_lock(&__lock) 36 | #define UNLOCK() pthread_mutex_unlock(&__lock) 37 | 38 | static report_options_t __opts = { LOGCAT, "", 0 }; 39 | static pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER; 40 | 41 | long int timestamp() { 42 | struct timeval tp = {0}; 43 | gettimeofday(&tp, NULL); 44 | 45 | return tp.tv_sec * 1000 + tp.tv_usec / 1000; 46 | } 47 | 48 | static long int __started = timestamp(); 49 | 50 | void report_set_options( report_options_t *opts ) { 51 | LOCK(); 52 | 53 | __opts.mode = opts->mode; 54 | __opts.dest = opts->dest; 55 | __opts.port = opts->port; 56 | 57 | UNLOCK(); 58 | } 59 | 60 | std::ostringstream& parse( char fmt, std::ostringstream& s, va_list& va ) { 61 | switch( fmt ) 62 | { 63 | case 'i': 64 | s << va_arg( va, int ) << " "; 65 | break; 66 | 67 | case 'u': 68 | s << va_arg( va, unsigned int ) << " "; 69 | break; 70 | 71 | case 'p': 72 | s << std::hex << std::setfill('0') << "0x" << va_arg( va, uintptr_t ) << " "; 73 | break; 74 | 75 | case 's': 76 | s << '"' << va_arg( va, const char * ) << '"' << " "; 77 | break; 78 | 79 | default: 80 | 81 | s << std::hex << std::setfill('0') << "0x" << va_arg( va, uintptr_t ) << " "; 82 | } 83 | 84 | return s; 85 | } 86 | 87 | void report_add( const char *fnname, const char *argsfmt, ... ) { 88 | va_list va; 89 | size_t i, argc = strlen(argsfmt); 90 | 91 | LOCK(); 92 | 93 | if( __opts.mode == LOGCAT ) { 94 | std::ostringstream s; 95 | 96 | s << "[ ts=" << ( timestamp() - __started ) << " pid=" << getpid() << ", tid=" << gettid() << " ] " << fnname << "( "; 97 | 98 | va_start( va, argsfmt ); 99 | 100 | for( i = 0; i < argc; ++i ) { 101 | char fmt = argsfmt[i]; 102 | 103 | // next will be the return value, break 104 | if( fmt == '.' ){ 105 | break; 106 | } 107 | 108 | s << va_arg( va, char * ) << "="; 109 | parse( fmt, s, va ); 110 | } 111 | 112 | s << ")"; 113 | 114 | // get return value 115 | if( i != argc ){ 116 | char fmt = argsfmt[i + 1]; 117 | s << " -> "; 118 | parse( fmt, s, va ); 119 | } 120 | 121 | va_end( va ); 122 | 123 | HOOKLOG( "%s", s.str().c_str() ); 124 | } 125 | 126 | UNLOCK(); 127 | } 128 | -------------------------------------------------------------------------------- /jni/libhook/report.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Simone Margaritelli 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of ARM Inject nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef REPORT_H_ 30 | #define REPORT_H_ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | typedef enum { 38 | LOGCAT = 0 39 | } 40 | report_mode_t; 41 | 42 | typedef struct { 43 | report_mode_t mode; 44 | // for future use 45 | std::string dest; 46 | unsigned short port; 47 | } 48 | report_options_t; 49 | 50 | void report_set_options( report_options_t *opts ); 51 | void report_add( const char *fnname, const char *argsfmt, ... ); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /pyadb/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evilsocket/arminject/2f1ea7256ea0a817f2ee50c4246f8c9c19272f13/pyadb/__init__.py -------------------------------------------------------------------------------- /pyadb/adb.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Simone Margaritelli 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of ARM Inject nor the names of its contributors may be used 13 | # to endorse or promote products derived from this software without 14 | # specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | # POSSIBILITY OF SUCH DAMAGE. 27 | import subprocess 28 | import time 29 | import os 30 | 31 | class ADB: 32 | def __init__(self): 33 | # make sure we have adb 34 | if self._exec( "which adb" ) == "": 35 | raise "ADB binary not found in PATH." 36 | 37 | def push( self, src, dst ): 38 | self._exec( "adb push '%s' '%s'" % ( src, dst ), True ) 39 | 40 | def sh( self, cmd ): 41 | return self._exec( "adb shell '%s'" % cmd ) 42 | 43 | def sudo( self, cmd ): 44 | return self.sh( "su -c \"%s\"" % cmd ) 45 | 46 | def pkill( self, proc ): 47 | self.sudo( "pkill -9 %s" % proc ) 48 | 49 | def clear_log( self ): 50 | self._exec( "adb logcat -c" ) 51 | 52 | def set_selinux_level( self, level ): 53 | self.sh( "su 0 setenforce %d" % level ) 54 | if level == 0: 55 | self.sh( 'su -c supolicy --live "allow s_untrusted_app shell_data_file file { execute execute_no_trans }"' ) 56 | 57 | def get_pid( self, proc ): 58 | out = self.sudo( "ps | grep '%s'" % proc ).strip().split(' ') 59 | out = [x for x in out if x] 60 | pid = int( out[1] ) 61 | return pid 62 | 63 | def start_activity( self, proc, activity ): 64 | self.pkill( proc ) 65 | time.sleep(1) 66 | self.sh( "am start %s/%s" % ( proc, activity ) ) 67 | return self.get_pid( proc ) 68 | 69 | def logcat( self, tag = None ): 70 | if tag is not None: 71 | cmd = "adb logcat -s '%s'" % tag 72 | else: 73 | cmd = "adb logcat" 74 | 75 | proc = subprocess.Popen( cmd, stdout=subprocess.PIPE, shell=True ) 76 | for line in iter( proc.stdout.readline, '' ): 77 | print line.rstrip() 78 | 79 | def _exec( self, cmdline, silent = False ): 80 | channel = open(os.devnull, 'wb') if silent is True else subprocess.PIPE 81 | p = subprocess.Popen( cmdline, stdout=channel, stderr=channel, shell=True ) 82 | out, err = p.communicate() 83 | if err: 84 | print err 85 | if p.returncode != 0: 86 | print "[STDERR] : %s" % out 87 | 88 | return out 89 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Simone Margaritelli 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of ARM Inject nor the names of its contributors may be used 13 | # to endorse or promote products derived from this software without 14 | # specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | # POSSIBILITY OF SUCH DAMAGE. 27 | from pyadb.adb import ADB 28 | 29 | try: 30 | adb = ADB() 31 | 32 | process = "com.android.chrome" 33 | activity = "com.google.android.apps.chrome.Main" 34 | 35 | print "@ Pushing files to /data/local/tmp ..." 36 | 37 | adb.sh( "rm -rf /data/local/tmp/injector /data/local/tmp/libhook.so" ) 38 | adb.push( "libs/armeabi-v7a/injector", "/data/local/tmp/injector" ) 39 | adb.push( "libs/armeabi-v7a/libhook.so", "/data/local/tmp/libhook.so" ) 40 | adb.sh( "chmod 777 /data/local/tmp/injector" ) 41 | 42 | print "@ Starting %s/%s ..." % ( process, activity ) 43 | 44 | # we need to set selinux to permissive in order to make ptrace work 45 | adb.set_selinux_level( 0 ) 46 | adb.clear_log() 47 | 48 | pid = adb.start_activity( process, activity ) 49 | 50 | print "@ Injection into PID %d starting ..." % pid 51 | 52 | adb.sudo( "/data/local/tmp/injector %d /data/local/tmp/libhook.so" % pid ) 53 | adb.logcat("LIBHOOK") 54 | 55 | except KeyboardInterrupt: 56 | print "\n\n@ CTRL+C detected, killing process ..." 57 | adb.pkill( process ) 58 | -------------------------------------------------------------------------------- /trace_pid.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015, Simone Margaritelli 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of ARM Inject nor the names of its contributors may be used 13 | # to endorse or promote products derived from this software without 14 | # specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | # POSSIBILITY OF SUCH DAMAGE. 27 | from pyadb.adb import ADB 28 | import sys 29 | 30 | if len(sys.argv) != 2: 31 | print "Usage: python %s " % sys.argv[0] 32 | quit() 33 | 34 | pid = int(sys.argv[1]) 35 | 36 | try: 37 | adb = ADB() 38 | 39 | print "@ Pushing files to /data/local/tmp ..." 40 | 41 | adb.sh( "rm -rf /data/local/tmp/injector /data/local/tmp/libhook.so" ) 42 | adb.push( "libs/armeabi-v7a/injector", "/data/local/tmp/injector" ) 43 | adb.push( "libs/armeabi-v7a/libhook.so", "/data/local/tmp/libhook.so" ) 44 | adb.sh( "chmod 777 /data/local/tmp/injector" ) 45 | 46 | # we need to set selinux to permissive in order to make ptrace work 47 | adb.set_selinux_level( 0 ) 48 | adb.clear_log() 49 | 50 | print "@ Injection into PID %d starting ..." % pid 51 | 52 | adb.sudo( "/data/local/tmp/injector %d /data/local/tmp/libhook.so" % pid ) 53 | adb.logcat("LIBHOOK") 54 | 55 | except KeyboardInterrupt: 56 | pass 57 | --------------------------------------------------------------------------------