├── .gitignore ├── Makefile ├── Makevars.global ├── refs ├── inject.c ├── inject.h └── shellcode.s ├── src ├── .gdbinit ├── Makefile ├── Makefile.bk ├── Makevars.local ├── autodbg.gdb ├── build.sh ├── crc.cpp ├── crc.h ├── debugger.cpp.bk ├── dk-client.sh ├── dk-server.sh ├── dlfcn.cpp ├── gdb_udog.sh ├── libPingan.so.dump ├── libiSecurityPAB.so.dump ├── linker.cpp ├── linker.h ├── linker_debug.h ├── linker_environ.cpp ├── linker_environ.h ├── linker_format.cpp ├── linker_format.h ├── linker_phdr.cpp ├── linker_phdr.h ├── options.cpp ├── options.h ├── rt.cpp ├── tool ├── xdlfcn.h ├── xor.cpp └── xor.h └── test ├── Makefile ├── hello1.c ├── hello2.c └── hello3.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.obj 8 | *.o 9 | *.so 10 | *.a 11 | 12 | # Temp source # 13 | ################### 14 | *.*~ 15 | 16 | # Packages # 17 | ############ 18 | # it's better to unpack these files and commit the raw source 19 | # git has its own built in compression methods 20 | *.7z 21 | *.dmg 22 | *.gz 23 | *.iso 24 | *.jar 25 | *.rar 26 | *.tar 27 | *.zip 28 | 29 | # Logs and databases # 30 | ###################### 31 | *.log 32 | *.sql 33 | *.sqlite 34 | 35 | # OS generated files # 36 | ###################### 37 | .DS_Store 38 | .DS_Store? 39 | ._* 40 | .Spotlight-V100 41 | .Trashes 42 | ehthumbs.db 43 | Thumbs.db 44 | 45 | # Customs files # 46 | ###################### 47 | bk*/ 48 | xlinker 49 | *.out 50 | .depend 51 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile - needs GNU make 3.81 or better 3 | # 4 | # Copyright (C) 2013-2014 4dog.cn 5 | # 6 | 7 | MAKEFLAGS += -rR 8 | .SUFFIXES: 9 | export SHELL = /bin/sh 10 | 11 | ifneq ($(findstring $(firstword $(MAKE_VERSION)),3.77 3.78 3.78.1 3.79 3.79.1 3.80),) 12 | $(error GNU make 3.81 or better is required) 13 | endif 14 | 15 | # srcdir = . 16 | # top_srcdir = . 17 | # include $(wildcard $(top_srcdir)/Makevars.global ./Makevars.local) 18 | 19 | default: 20 | @echo "[info]: please choose a target for 'make'" 21 | 22 | all mostlyclean clean distclean maintainer-clean: 23 | $(MAKE) -C src $@ 24 | 25 | # 编译文档 26 | ifneq ($(BUILD_DOC),) 27 | $(MAKE) -C doc $@ 28 | endif 29 | 30 | .PHONY: default all mostlyclean clean distclean maintainer-clean 31 | -------------------------------------------------------------------------------- /Makevars.global: -------------------------------------------------------------------------------- 1 | # 全局配置选项 2 | PLATFORM := $(shell uname | sed -e 's/_.*//') 3 | 4 | # 指定是Android平台编译 5 | ANDROID ?= 1 6 | 7 | # ARM:1,X86:2,MIPS:3 8 | CPU ?= 1 9 | 10 | # tools 11 | ifndef COPY 12 | COPY=cp 13 | endif 14 | 15 | ifndef RM 16 | RM=rm 17 | endif 18 | 19 | ifndef MAKE 20 | MAKE=make 21 | endif 22 | 23 | # 设定NDK 24 | NDK_HOME ?= ~/sdk/android-ndk-r8e 25 | # 判断编译器集合 26 | ifeq ($(ANDROID),1) 27 | ifeq ($(CPU),1) 28 | # ARM编译 29 | SYSROOT := $(NDK_HOME)/platforms/android-8/arch-arm/ 30 | ADDR2LINE := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line 31 | AR := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar 32 | AS := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-as 33 | CC := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=$(SYSROOT) 34 | CXX := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ --sysroot=$(SYSROOT) 35 | GDB := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb 36 | GDBTUI := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdbtui 37 | GPROF := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gprof 38 | LD := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld --sysroot=$(SYSROOT) 39 | NM := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-nm 40 | OBJCOPY := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-objcopy 41 | OBJDUMP := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-objdump 42 | RANLIB := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ranlib 43 | READELF := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-readelf 44 | RUN := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-run 45 | SIZE := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-size 46 | STRINGS := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strings 47 | STRIP := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip 48 | else 49 | # X86编译 50 | SYSROOT := $(NDK_HOME)/platforms/android-14/arch-x86/ 51 | ADDR2LINE := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-addr2line 52 | AR := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-ar 53 | AS := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-as 54 | CC := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-gcc --sysroot=$(SYSROOT) 55 | CXX := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-g++ --sysroot=$(SYSROOT) 56 | GDB := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-gdb 57 | GDBTUI := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-gdbtui 58 | GPROF := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-gprof 59 | LD := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-ld --sysroot=$(SYSROOT) 60 | NM := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-nm 61 | OBJCOPY := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-objcopy 62 | OBJDUMP := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-objdump 63 | RANLIB := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-ranlib 64 | READELF := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-readelf 65 | RUN := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-run 66 | SIZE := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-size 67 | STRINGS := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-strings 68 | STRIP := $(NDK_HOME)/toolchains/x86-4.4.3/prebuilt/linux-x86_64/bin/i686-linux-android-strip 69 | endif 70 | else 71 | ADDR2LINE := addr2line 72 | AR := ar 73 | AS := as 74 | CC := gcc 75 | CXX := g++ 76 | GDB := gdb 77 | GDBTUI := 78 | GPROF := gprof 79 | LD := ld 80 | NM := nm 81 | OBJCOPY := objcopy 82 | OBJDUMP := objdump 83 | RANLIB := ranlib 84 | READELF := readelf 85 | RUN := run 86 | SIZE := size 87 | STRINGS := strings 88 | STRIP := strip 89 | endif 90 | 91 | # 打包选项 92 | ARFLAGS += cr 93 | 94 | # 编译选项 95 | CXXFLAGS += -fpie 96 | 97 | # 全局OBJECTS 98 | ifeq ($(ANDROID),1) 99 | global_OBJECTS += libsupc++.a 100 | else 101 | global_OBJECTS += 102 | endif 103 | 104 | # 全局SOURCES 105 | global_SOURCES = 106 | 107 | # 使用GNUC编译器 108 | #ifneq ($(findstring $(firstword $(CXX)),g++),) 109 | USE_GNUC ?= 1 110 | #endif 111 | 112 | # 交叉工具 113 | objdump: $(OBJDUMP) 114 | $(OBJDUMP) $(CMD) 115 | 116 | objcopy: $(OBJCOPY) 117 | $(OBJCOPY) $(CMD) 118 | 119 | readelf: $(READELF) 120 | $(READELF) $(CMD) 121 | 122 | nm: $(NM) 123 | $(NM) $(CMD) 124 | 125 | -------------------------------------------------------------------------------- /refs/inject.c: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================ 3 | Name : libinject.c 4 | Author : 5 | Version : 6 | Copyright : 7 | Description : Android shared library inject helper 8 | ============================================================================ 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | 26 | #define ENABLE_DEBUG 1 27 | 28 | #define PTRACE_PEEKTEXT 1 29 | #define PTRACE_POKETEXT 4 30 | #define PTRACE_ATTACH 16 31 | #define PTRACE_CONT 7 32 | #define PTRACE_DETACH 17 33 | #define PTRACE_SYSCALL 24 34 | #define CPSR_T_MASK ( 1u << 5 ) 35 | 36 | #define MAX_PATH 0x100 37 | 38 | #define REMOTE_ADDR( addr, local_base, remote_base ) ( (uint32_t)(addr) + (uint32_t)(remote_base) - (uint32_t)(local_base) ) 39 | 40 | const char *libc_path = "/system/lib/libc.so"; 41 | const char *linker_path = "/system/bin/linker"; 42 | 43 | 44 | #if ENABLE_DEBUG 45 | #define DEBUG_PRINT(format,args...) \ 46 | LOGD(format, ##args) 47 | #else 48 | #define DEBUG_PRINT(format,args...) 49 | #endif 50 | 51 | 52 | int ptrace_readdata( pid_t pid, uint8_t *src, uint8_t *buf, size_t size ) 53 | { 54 | uint32_t i, j, remain; 55 | uint8_t *laddr; 56 | 57 | union u { 58 | long val; 59 | char chars[sizeof(long)]; 60 | } d; 61 | 62 | j = size / 4; 63 | remain = size % 4; 64 | 65 | laddr = buf; 66 | 67 | for ( i = 0; i < j; i ++ ) 68 | { 69 | d.val = ptrace( PTRACE_PEEKTEXT, pid, src, 0 ); 70 | memcpy( laddr, d.chars, 4 ); 71 | src += 4; 72 | laddr += 4; 73 | } 74 | 75 | if ( remain > 0 ) 76 | { 77 | d.val = ptrace( PTRACE_PEEKTEXT, pid, src, 0 ); 78 | memcpy( laddr, d.chars, remain ); 79 | } 80 | 81 | return 0; 82 | 83 | } 84 | 85 | int ptrace_writedata( pid_t pid, uint8_t *dest, uint8_t *data, size_t size ) 86 | { 87 | uint32_t i, j, remain; 88 | uint8_t *laddr; 89 | 90 | union u { 91 | long val; 92 | char chars[sizeof(long)]; 93 | } d; 94 | 95 | j = size / 4; 96 | remain = size % 4; 97 | 98 | laddr = data; 99 | 100 | for ( i = 0; i < j; i ++ ) 101 | { 102 | memcpy( d.chars, laddr, 4 ); 103 | ptrace( PTRACE_POKETEXT, pid, dest, d.val ); 104 | 105 | dest += 4; 106 | laddr += 4; 107 | } 108 | 109 | if ( remain > 0 ) 110 | { 111 | d.val = ptrace( PTRACE_PEEKTEXT, pid, dest, 0 ); 112 | for ( i = 0; i < remain; i ++ ) 113 | { 114 | d.chars[i] = *laddr ++; 115 | } 116 | 117 | ptrace( PTRACE_POKETEXT, pid, dest, d.val ); 118 | 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | 125 | int ptrace_writestring( pid_t pid, uint8_t *dest, char *str ) 126 | { 127 | return ptrace_writedata( pid, dest, str, strlen(str)+1 ); 128 | } 129 | 130 | int ptrace_call( pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct pt_regs* regs ) 131 | { 132 | uint32_t i; 133 | 134 | for ( i = 0; i < num_params && i < 4; i ++ ) 135 | { 136 | regs->uregs[i] = params[i]; 137 | } 138 | 139 | // 140 | // push remained params onto stack 141 | // 142 | if ( i < num_params ) 143 | { 144 | regs->ARM_sp -= (num_params - i) * sizeof(long) ; 145 | ptrace_writedata( pid, (void *)regs->ARM_sp, (uint8_t *)¶ms[i], (num_params - i) * sizeof(long) ); 146 | } 147 | 148 | regs->ARM_pc = addr; 149 | if ( regs->ARM_pc & 1 ) 150 | { 151 | /* thumb */ 152 | regs->ARM_pc &= (~1u); 153 | regs->ARM_cpsr |= CPSR_T_MASK; 154 | } 155 | else 156 | { 157 | /* arm */ 158 | regs->ARM_cpsr &= ~CPSR_T_MASK; 159 | } 160 | 161 | 162 | regs->ARM_lr = 0; 163 | 164 | if ( ptrace_setregs( pid, regs ) == -1 165 | || ptrace_continue( pid ) == -1 ) 166 | { 167 | return -1; 168 | } 169 | 170 | 171 | waitpid( pid, NULL, WUNTRACED ); 172 | 173 | return 0; 174 | } 175 | 176 | 177 | 178 | int ptrace_getregs( pid_t pid, struct pt_regs* regs ) 179 | { 180 | if ( ptrace( PTRACE_GETREGS, pid, NULL, regs ) < 0 ) 181 | { 182 | perror( "ptrace_getregs: Can not get register values" ); 183 | return -1; 184 | } 185 | 186 | return 0; 187 | } 188 | 189 | int ptrace_setregs( pid_t pid, struct pt_regs* regs ) 190 | { 191 | if ( ptrace( PTRACE_SETREGS, pid, NULL, regs ) < 0 ) 192 | { 193 | perror( "ptrace_setregs: Can not set register values" ); 194 | return -1; 195 | } 196 | 197 | return 0; 198 | } 199 | 200 | 201 | 202 | 203 | int ptrace_continue( pid_t pid ) 204 | { 205 | if ( ptrace( PTRACE_CONT, pid, NULL, 0 ) < 0 ) 206 | { 207 | perror( "ptrace_cont" ); 208 | return -1; 209 | } 210 | 211 | return 0; 212 | } 213 | 214 | int ptrace_attach( pid_t pid ) 215 | { 216 | if ( ptrace( PTRACE_ATTACH, pid, NULL, 0 ) < 0 ) 217 | { 218 | perror( "ptrace_attach" ); 219 | return -1; 220 | } 221 | 222 | waitpid( pid, NULL, WUNTRACED ); 223 | 224 | //DEBUG_PRINT("attached\n"); 225 | 226 | if ( ptrace( PTRACE_SYSCALL, pid, NULL, 0 ) < 0 ) 227 | { 228 | perror( "ptrace_syscall" ); 229 | return -1; 230 | } 231 | 232 | 233 | 234 | waitpid( pid, NULL, WUNTRACED ); 235 | 236 | return 0; 237 | } 238 | 239 | int ptrace_detach( pid_t pid ) 240 | { 241 | if ( ptrace( PTRACE_DETACH, pid, NULL, 0 ) < 0 ) 242 | { 243 | perror( "ptrace_detach" ); 244 | return -1; 245 | } 246 | 247 | return 0; 248 | } 249 | 250 | void* get_module_base( pid_t pid, const char* module_name ) 251 | { 252 | FILE *fp; 253 | long addr = 0; 254 | char *pch; 255 | char filename[32]; 256 | char line[1024]; 257 | 258 | if ( pid < 0 ) 259 | { 260 | /* self process */ 261 | snprintf( filename, sizeof(filename), "/proc/self/maps", pid ); 262 | } 263 | else 264 | { 265 | snprintf( filename, sizeof(filename), "/proc/%d/maps", pid ); 266 | } 267 | 268 | fp = fopen( filename, "r" ); 269 | 270 | if ( fp != NULL ) 271 | { 272 | while ( fgets( line, sizeof(line), fp ) ) 273 | { 274 | if ( strstr( line, module_name ) ) 275 | { 276 | pch = strtok( line, "-" ); 277 | addr = strtoul( pch, NULL, 16 ); 278 | 279 | if ( addr == 0x8000 ) 280 | addr = 0; 281 | 282 | break; 283 | } 284 | } 285 | 286 | fclose( fp ) ; 287 | } 288 | 289 | return (void *)addr; 290 | } 291 | 292 | 293 | void* get_remote_addr( pid_t target_pid, const char* module_name, void* local_addr ) 294 | { 295 | void* local_handle, *remote_handle; 296 | 297 | local_handle = get_module_base( -1, module_name ); 298 | remote_handle = get_module_base( target_pid, module_name ); 299 | 300 | DEBUG_PRINT( "[+] get_remote_addr: local[%x], remote[%x]\n", local_handle, remote_handle ); 301 | 302 | return (void *)( (uint32_t)local_addr + (uint32_t)remote_handle - (uint32_t)local_handle ); 303 | } 304 | 305 | int find_pid_of( const char *process_name ) 306 | { 307 | int id; 308 | pid_t pid = -1; 309 | DIR* dir; 310 | FILE *fp; 311 | char filename[32]; 312 | char cmdline[256]; 313 | 314 | struct dirent * entry; 315 | 316 | if ( process_name == NULL ) 317 | return -1; 318 | 319 | dir = opendir( "/proc" ); 320 | if ( dir == NULL ) 321 | return -1; 322 | 323 | while( (entry = readdir( dir )) != NULL ) 324 | { 325 | id = atoi( entry->d_name ); 326 | if ( id != 0 ) 327 | { 328 | sprintf( filename, "/proc/%d/cmdline", id ); 329 | fp = fopen( filename, "r" ); 330 | if ( fp ) 331 | { 332 | fgets( cmdline, sizeof(cmdline), fp ); 333 | fclose( fp ); 334 | 335 | if ( strcmp( process_name, cmdline ) == 0 ) 336 | { 337 | /* process found */ 338 | pid = id; 339 | break; 340 | } 341 | } 342 | } 343 | } 344 | 345 | closedir( dir ); 346 | 347 | return pid; 348 | } 349 | 350 | 351 | 352 | int inject_remote_process( pid_t target_pid, const char *library_path, const char *function_name, void *param, size_t param_size ) 353 | { 354 | int ret = -1; 355 | void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr; 356 | void *local_handle, *remote_handle, *dlhandle; 357 | uint8_t *map_base; 358 | uint8_t *dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr; 359 | 360 | struct pt_regs regs, original_regs; 361 | extern uint32_t _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, _dlsym_addr_s, \ 362 | _dlsym_param2_s, _dlclose_addr_s, _inject_start_s, _inject_end_s, _inject_function_param_s, \ 363 | _saved_cpsr_s, _saved_r0_pc_s; 364 | 365 | uint32_t code_length; 366 | 367 | 368 | long parameters[10]; 369 | 370 | 371 | 372 | DEBUG_PRINT( "[+] Injecting process: %d\n", target_pid ); 373 | 374 | if ( ptrace_attach( target_pid ) == -1 ) 375 | return EXIT_SUCCESS; 376 | 377 | 378 | if ( ptrace_getregs( target_pid, ®s ) == -1 ) 379 | goto exit; 380 | 381 | /* save original registers */ 382 | memcpy( &original_regs, ®s, sizeof(regs) ); 383 | 384 | mmap_addr = get_remote_addr( target_pid, "/system/lib/libc.so", (void *)mmap ); 385 | 386 | DEBUG_PRINT( "[+] Remote mmap address: %x\n", mmap_addr ); 387 | 388 | /* call mmap */ 389 | parameters[0] = 0; // addr 390 | parameters[1] = 0x4000; // size 391 | parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; // prot 392 | parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; // flags 393 | parameters[4] = 0; //fd 394 | parameters[5] = 0; //offset 395 | 396 | DEBUG_PRINT( "[+] Calling mmap in target process.\n" ); 397 | 398 | if ( ptrace_call( target_pid, (uint32_t)mmap_addr, parameters, 6, ®s ) == -1 ) 399 | goto exit; 400 | 401 | 402 | 403 | if ( ptrace_getregs( target_pid, ®s ) == -1 ) 404 | goto exit; 405 | 406 | 407 | DEBUG_PRINT( "[+] Target process returned from mmap, return value=%x, pc=%x \n", regs.ARM_r0, regs.ARM_pc ); 408 | 409 | map_base = (uint8_t *)regs.ARM_r0; 410 | 411 | dlopen_addr = get_remote_addr( target_pid, linker_path, (void *)dlopen ); 412 | dlsym_addr = get_remote_addr( target_pid, linker_path, (void *)dlsym ); 413 | dlclose_addr = get_remote_addr( target_pid, linker_path, (void *)dlclose ); 414 | 415 | DEBUG_PRINT( "[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x\n", dlopen_addr, dlsym_addr, dlclose_addr ); 416 | 417 | 418 | remote_code_ptr = map_base + 0x3C00; 419 | local_code_ptr = (uint8_t *)&_inject_start_s; 420 | 421 | 422 | _dlopen_addr_s = (uint32_t)dlopen_addr; 423 | _dlsym_addr_s = (uint32_t)dlsym_addr; 424 | _dlclose_addr_s = (uint32_t)dlclose_addr; 425 | 426 | DEBUG_PRINT( "[+] Inject code start: %x, end: %x\n", local_code_ptr, &_inject_end_s ); 427 | 428 | code_length = (uint32_t)&_inject_end_s - (uint32_t)&_inject_start_s; 429 | dlopen_param1_ptr = local_code_ptr + code_length + 0x20; 430 | dlsym_param2_ptr = dlopen_param1_ptr + MAX_PATH; 431 | saved_r0_pc_ptr = dlsym_param2_ptr + MAX_PATH; 432 | inject_param_ptr = saved_r0_pc_ptr + MAX_PATH; 433 | 434 | 435 | /* dlopen parameter 1: library name */ 436 | strcpy( dlopen_param1_ptr, library_path ); 437 | _dlopen_param1_s = REMOTE_ADDR( dlopen_param1_ptr, local_code_ptr, remote_code_ptr ); 438 | DEBUG_PRINT( "[+] _dlopen_param1_s: %x\n", _dlopen_param1_s ); 439 | 440 | /* dlsym parameter 2: function name */ 441 | strcpy( dlsym_param2_ptr, function_name ); 442 | _dlsym_param2_s = REMOTE_ADDR( dlsym_param2_ptr, local_code_ptr, remote_code_ptr ); 443 | DEBUG_PRINT( "[+] _dlsym_param2_s: %x\n", _dlsym_param2_s ); 444 | 445 | /* saved cpsr */ 446 | _saved_cpsr_s = original_regs.ARM_cpsr; 447 | 448 | /* saved r0-pc */ 449 | memcpy( saved_r0_pc_ptr, &(original_regs.ARM_r0), 16 * 4 ); // r0 ~ r15 450 | _saved_r0_pc_s = REMOTE_ADDR( saved_r0_pc_ptr, local_code_ptr, remote_code_ptr ); 451 | DEBUG_PRINT( "[+] _saved_r0_pc_s: %x\n", _saved_r0_pc_s ); 452 | 453 | /* Inject function parameter */ 454 | memcpy( inject_param_ptr, param, param_size ); 455 | _inject_function_param_s = REMOTE_ADDR( inject_param_ptr, local_code_ptr, remote_code_ptr ); 456 | DEBUG_PRINT( "[+] _inject_function_param_s: %x\n", _inject_function_param_s ); 457 | 458 | DEBUG_PRINT( "[+] Remote shellcode address: %x\n", remote_code_ptr ); 459 | ptrace_writedata( target_pid, remote_code_ptr, local_code_ptr, 0x400 ); 460 | 461 | memcpy( ®s, &original_regs, sizeof(regs) ); 462 | regs.ARM_sp = (long)remote_code_ptr; 463 | regs.ARM_pc = (long)remote_code_ptr; 464 | ptrace_setregs( target_pid, ®s ); 465 | ptrace_detach( target_pid ); 466 | 467 | // inject succeeded 468 | ret = 0; 469 | 470 | exit: 471 | return ret; 472 | } 473 | int main(int argc, char** argv) { 474 | pid_t target_pid; 475 | target_pid = find_pid_of("/system/bin/servicemanager"); 476 | inject_remote_process( target_pid, "/dev/yuki/payload.so", "hook_entry", "I'm parameter!", strlen("I'm parameter!") ); 477 | } -------------------------------------------------------------------------------- /refs/inject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef __cplusplus 6 | extern "C" 7 | { 8 | #endif 9 | 10 | int inject_remote_process( pid_t target_pid, const char *library_path, const char *function_name, void *param, size_t param_size ); 11 | 12 | int find_pid_of( const char *process_name ); 13 | 14 | void* get_module_base( pid_t pid, const char* module_name ); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | struct inject_param_t 22 | { 23 | pid_t from_pid; 24 | } ; 25 | -------------------------------------------------------------------------------- /refs/shellcode.s: -------------------------------------------------------------------------------- 1 | .global _dlopen_addr_s 2 | .global _dlopen_param1_s 3 | .global _dlopen_param2_s 4 | 5 | .global _dlsym_addr_s 6 | .global _dlsym_param2_s 7 | 8 | .global _dlclose_addr_s 9 | 10 | .global _inject_start_s 11 | .global _inject_end_s 12 | 13 | .global _inject_function_param_s 14 | 15 | .global _saved_cpsr_s 16 | .global _saved_r0_pc_s 17 | 18 | .data 19 | 20 | _inject_start_s: 21 | @ debug loop 22 | 3: 23 | @sub r1, r1, #0 24 | @B 3b 25 | 26 | @ dlopen 27 | ldr r1, _dlopen_param2_s 28 | ldr r0, _dlopen_param1_s 29 | ldr r3, _dlopen_addr_s 30 | blx r3 31 | subs r4, r0, #0 32 | beq 2f 33 | 34 | @dlsym 35 | ldr r1, _dlsym_param2_s 36 | ldr r3, _dlsym_addr_s 37 | blx r3 38 | subs r3, r0, #0 39 | beq 1f 40 | 41 | @call our function 42 | ldr r0, _inject_function_param_s 43 | blx r3 44 | subs r0, r0, #0 45 | beq 2f 46 | 47 | 1: 48 | @dlclose 49 | mov r0, r4 50 | ldr r3, _dlclose_addr_s 51 | blx r3 52 | 53 | 2: 54 | @restore context 55 | ldr r1, _saved_cpsr_s 56 | msr cpsr_cf, r1 57 | ldr sp, _saved_r0_pc_s 58 | ldmfd sp, {r0-pc} 59 | 60 | _dlopen_addr_s: 61 | .word 0x11111111 62 | 63 | _dlopen_param1_s: 64 | .word 0x11111111 65 | 66 | _dlopen_param2_s: 67 | .word 0x2 68 | 69 | _dlsym_addr_s: 70 | .word 0x11111111 71 | 72 | _dlsym_param2_s: 73 | .word 0x11111111 74 | 75 | _dlclose_addr_s: 76 | .word 0x11111111 77 | 78 | _inject_function_param_s: 79 | .word 0x11111111 80 | 81 | _saved_cpsr_s: 82 | .word 0x11111111 83 | 84 | _saved_r0_pc_s: 85 | .word 0x11111111 86 | 87 | _inject_end_s: 88 | 89 | .space 0x400, 0 90 | 91 | .end 92 | -------------------------------------------------------------------------------- /src/.gdbinit: -------------------------------------------------------------------------------- 1 | #filename dk-client-debug 2 | target remote:1234 3 | file "~/workspace/udog/src/udog.out" 4 | b main 5 | c 6 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile - needs GNU make 3.81 or better 3 | # 4 | # Copyright (C) 2013-2014 4dog.cn 5 | # 6 | 7 | # 确定是否是正确的Make版本 8 | ifneq ($(findstring $(firstword $(MAKE_VERSION)),3.77 3.78 3.78.1 3.79 3.79.1 3.80),) 9 | $(error GNU make 3.81 or better is required) 10 | endif 11 | 12 | # 定义源目录,取最后一个make文件的,也就是当前处理的make文件的路径作为源目录 13 | # sed的作用是如果文件名以$结尾,则去掉这个$号 14 | ifndef srcdir 15 | srcdir := $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) 16 | srcdir := $(shell echo '$(srcdir)' | sed 's,/*$$,,') 17 | endif 18 | 19 | # 设定顶级目录 20 | ifndef top_srcdir 21 | top_srcdir := $(srcdir)/.. 22 | endif 23 | 24 | # 如果源目录非当前目录则设定VPATH 25 | ifneq ($(srcdir),.) 26 | ##$(info Info: using VPATH . $(srcdir)) 27 | VPATH := . $(srcdir) 28 | endif 29 | 30 | # 包含全局配置与本地配置脚本 31 | include $(wildcard $(top_srcdir)/Makevars.global $(srcdir)/Makevars.local) 32 | 33 | # -r(--no-builtin-rules)禁止make使用任何隐含规则 34 | # -R(--no-builtin-variabes)禁止make使用任何作用于变量上的隐含规则 35 | MAKEFLAGS += -rR 36 | .SUFFIXES: 37 | export SHELL = /bin/sh 38 | # call函数的参数模板e 39 | # $($1)负责展开选项 40 | # $(EXTRA_$1)表示当前选项的扩展选项,例如:CXXFLAGS,则展开变量$(EXTRA_CXXFLAGS) 41 | # $($(project)_$1)表示针对tdog的选项,例如:CXXFLAGS,则展开变量$(tdog_CXXFLAGS) 42 | # $($(basename $(notdir $@)).$1) 表示针对某个文件的选项,例如:CXXFLAGS,$@=linker.cpp 43 | # 则展开变量$(linker.CXXFLAGS) 44 | # 针对几个层级进行编译或者链接或者其他操作的参数构造 45 | override e = $($1) $(EXTRA_$1) $($(project)_$1) $($(basename $(notdir $@)).$1) 46 | 47 | # 指定编译器 48 | # ifeq ($(CXX),) 49 | # CXX = g++ 50 | # endif 51 | 52 | # 如果USE_GNUC之前定义过,则保持之前的值,否则则默认开启 53 | # ifneq ($(findstring $(firstword $(CXX)),g++),) 54 | # USE_GNUC ?= 1 55 | # endif 56 | 57 | # 如果USE_GNUC等于1则设定相应编译选项 58 | ifeq ($(USE_GNUC),1) 59 | 60 | # 调试编译 61 | ifeq ($(DEBUG),1) 62 | CXXFLAGS += -O0 -g3 63 | else 64 | CXXFLAGS += -O3 65 | endif 66 | 67 | # 体系架构 68 | ifeq ($(ANDROID),) 69 | # 在真实的机器下采用指定体系的编译选项 70 | ifeq ($(ARCH),32) 71 | CXXFLAGS += -m32 72 | else 73 | CXXFLAGS += -m64 74 | endif 75 | endif 76 | 77 | endif 78 | 79 | # 合成编译选项 80 | CPPFLAGS += $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) # 生成依赖关系使用 81 | CXXLD ?= $(CXX) 82 | 83 | # 后缀选项 84 | exeext ?= .out 85 | libext ?= .a 86 | objext ?= .o 87 | 88 | # 文件集合 89 | local_SOURCES := $(sort $(wildcard $(srcdir)/*.cpp)) 90 | local_OBJECTS := $(notdir $(local_SOURCES:.cpp=$(objext))) 91 | 92 | # 目标 93 | all: $(project)$(exeext) | .depend 94 | .DELETE_ON_ERROR: $(project)$(exeext) $(local_OBJECTS) .depend # 发生错误时删除 95 | 96 | # 这里提供了外部控制的HOOK选项 97 | # 通过project.out变量的值.PRE_LINK_STEP来进行控制 98 | # 当链接完成后可由project.out变量.POST_LINK_STEP来进行控制 99 | $(project)$(exeext): $(local_OBJECTS) $($(project)_DEPENDENCIES) 100 | $($(notdir $@).PRE_LINK_STEP) 101 | $(strip $(CXXLD) $(call e,CPPFLAGS) $(call e,CXXFLAGS) $(call e,LDFLAGS) -o $@ $(local_OBJECTS) $(global_OBJECTS) $(call e,LDADD) $(call e,LIBS)) 102 | $($(notdir $@).POST_LINK_STEP) 103 | 104 | %.o : %.cpp | .depend 105 | $(strip $(CXX) $(call e,CPPFLAGS) $(call e,CXXFLAGS) -o $@ -c $<) 106 | 107 | # 生成依赖文件 108 | .depend: $(sort $(wildcard $(srcdir)/*.cpp $(srcdir)/*.h)) $(MAKEFILE_LIST) 109 | @rm -f $@ 110 | 111 | # 如果是GNU编译器集合 112 | # 从文件集合中取出.cpp文件依次进行编译,并将编译输出去掉首尾空格写入到.depend文件中 113 | # 如果非GNU编译器单纯的创建一个.depend的文件 114 | ifeq ($(USE_GNUC),1) 115 | @echo "Updating $@" 116 | @$(strip $(CXX) $(call e,CPPFLAGS) -MM) $(filter %.cpp,$^) > $@ 117 | else 118 | touch $@ 119 | endif 120 | 121 | # 清除 122 | mostlyclean clean distclean maintainer-clean: 123 | rm -f *.d *.map *.o *.obj *.res .depend $(project).exe $(project).out $(project).ttp $(project)$(exeext) 124 | 125 | # 伪目标 126 | .PHONY: all mostlyclean clean distclean maintainer-clean 127 | 128 | ifeq ($(MAKECMDGOALS),mostlyclean) 129 | else ifeq ($(MAKECMDGOALS),clean) 130 | else ifeq ($(MAKECMDGOALS),distclean) 131 | else ifeq ($(MAKECMDGOALS),maintainer-clean) 132 | else 133 | -include .depend 134 | endif 135 | -------------------------------------------------------------------------------- /src/Makefile.bk: -------------------------------------------------------------------------------- 1 | # MAKEFILE for linux GCC 2 | # 3 | 4 | # The version 5 | VERSION=1.0 6 | 7 | PLATFORM := $(shell uname | sed -e 's/_.*//') 8 | 9 | # tools 10 | ifndef COPY 11 | COPY=cp 12 | endif 13 | 14 | ifndef RM 15 | RM=rm 16 | endif 17 | 18 | ifndef MAKE 19 | MAKE=make 20 | endif 21 | 22 | # NDK tools 23 | SYSROOT := $(NDK_HOME)/platforms/android-8/arch-arm/ 24 | ADDR2LINE := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line 25 | AR := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar 26 | AS := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-as 27 | CC := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=$(SYSROOT) 28 | CXX := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ --sysroot=$(SYSROOT) 29 | GDB := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb 30 | GDBTUI := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdbtui 31 | GPROF := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gprof 32 | LD := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld --sysroot=$(SYSROOT) 33 | NM := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-nm 34 | OBJCOPY := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-objcopy 35 | OBJDUMP := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-objdump 36 | RANLIB := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ranlib 37 | READELF := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-readelf 38 | RUN := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-run 39 | SIZE := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-size 40 | STRINGS := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strings 41 | STRIP := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip 42 | 43 | # 打包选项 44 | ARFLAGS := cr 45 | 46 | CFLAGS += -DANDROID_ARM_LINKER 47 | 48 | # 开启调试选项 49 | ifdef DEBUG 50 | CFLAGS += -g3 -O0 51 | CFLAGS += -DLINKER_DEBUG=1 -DLOG_TO_STDOUT=1 52 | else 53 | CFLAGS += -DNODEBUG -DLINKER_DEBUG=0 54 | CFLAGS += -O3 55 | endif 56 | 57 | # UDOG标识 58 | CFLAGS += -DUDOG 59 | 60 | 61 | # 是否使用地址无关代码 62 | ifdef PIC 63 | CFLAGS += -fpic 64 | endif 65 | 66 | # 是否要编译APP 67 | ifdef APP 68 | CFLAGS += -DAPP 69 | ifdef PIC 70 | CFLAGS += -fpie 71 | endif 72 | endif 73 | 74 | CXXFLAGS = $(CFLAGS) 75 | 76 | OBJECTS=linker.o \ 77 | linker_environ.o \ 78 | linker_format.o \ 79 | linker_phdr.o \ 80 | dlfcn.o \ 81 | rt.o \ 82 | options.o 83 | 84 | # debugger.o 85 | 86 | SOURCES=linker.cpp \ 87 | linker_environ.cpp \ 88 | linker_format.cpp \ 89 | linker_phdr.cpp \ 90 | dlfcn.cpp \ 91 | rt.cpp \ 92 | options.cpp 93 | 94 | HEADERS=linker.h \ 95 | linker_debug.h \ 96 | linker_format.h \ 97 | linker_phdr.h \ 98 | linker_environ.h 99 | 100 | test_aux: test_aux.cpp 101 | $(CXX) $(CXXFLAGS) $< -o $@ 102 | 103 | # 这里有一个链接顺序的问题,必须首先链接.o文件以及.c文件x 104 | # 随后才可以 链接.a文件,否则将找不到一些符号的定义 105 | # xlinker: $(OBJECTS) $(SOURCES) $(HEADERS) 106 | # $(CXX) $(CXXFLAGS) $(OBJECTS) libsupc++.a -o $@ 107 | 108 | udog: $(OBJECTS) $(SOURCES) $(HEADERS) 109 | $(CXX) $(CXXFLAGS) $(OBJECTS) libsupc++.a -o $@ 110 | 111 | linker.o: linker.cpp 112 | $(CXX) $(CXXFLAGS) -c $< -o $@ 113 | 114 | linker_environ.o: linker_environ.cpp 115 | $(CXX) $(CXXFLAGS) -c $< -o $@ 116 | 117 | linker_format.o: linker_format.cpp 118 | $(CXX) $(CXXFLAGS) -c $< -o $@ 119 | 120 | dlfcn.o: dlfcn.cpp 121 | $(CXX) $(CXXFLAGS) -c $< -o $@ 122 | 123 | options.o: options.cpp 124 | $(CXX) $(CXXFLAGS) -c $< -o $@ 125 | 126 | # debugger.o: debugger.cpp 127 | # $(CXX) $(CXXFLAGS) -c $< -o $@ 128 | 129 | objdump: $(OBJDUMP) 130 | $(OBJDUMP) $(CMD) 131 | 132 | objcopy: $(OBJCOPY) 133 | $(OBJCOPY) $(CMD) 134 | 135 | readelf: $(READELF) 136 | $(READELF) $(CMD) 137 | 138 | nm: $(NM) 139 | $(NM) $(CMD) 140 | 141 | clean_local: 142 | -$(RM) -f *.o 143 | -$(RM) -f xlinker 144 | 145 | clean: 146 | -$(RM) -f `find . -type f | grep "[.]o" | xargs` 147 | -------------------------------------------------------------------------------- /src/Makevars.local: -------------------------------------------------------------------------------- 1 | # 局部配置选项 2 | #DEBUG ?= 1 3 | #USE_GNUC ?= 1 4 | ARCH ?= 32 5 | UDOG_VERSION ?= 1 6 | 7 | # 设置工程名称 8 | project ?= udog 9 | 10 | # 如果USE_GNUC等于1则设定相应编译选项 11 | ifeq ($(USE_GNUC),1) 12 | 13 | # 调试编译 14 | ifeq ($(DEBUG),1) 15 | DEFS += -DLINKER_DEBUG=1 -DLOG_TO_STDOUT=0 16 | else 17 | DEFS += -DNODEBUG -DLINKER_DEBUG=0 -DLINKER_DEBUG=1 18 | endif 19 | 20 | # 一些自定义的宏设定 21 | DEFS += -DUDOG_VERSION=$(UDOG_VERSION) 22 | 23 | # 启用XXX体系下的连接器 24 | ifeq ($(CPU),1) 25 | DEFS += -DANDROID_ARM_LINKER=1 26 | endif 27 | 28 | ifeq ($(CPU),2) 29 | DEFS += -DANDROID_X86_LINKER=1 30 | endif 31 | 32 | ifeq ($(CPU),3) 33 | DEFS += -DANDROID_MIPS_LINKER=1 34 | endif 35 | 36 | # 其余错误编译选项 37 | CXXFLAGS_WERROR = -Werror 38 | CXXFLAGS += -Wall -Wcast-qual -Wcast-align -Wpointer-arith -Wshadow -Wwrite-strings -W -Wno-unused-function 39 | CXXFLAGS += $(CXXFLAGS_WERROR) 40 | 41 | # ANDROID编译选项 42 | ifeq ($(ANDROID),1) 43 | DEFS += -DANDROID 44 | endif 45 | 46 | endif 47 | -------------------------------------------------------------------------------- /src/autodbg.gdb: -------------------------------------------------------------------------------- 1 | echo /****************************************/ 2 | echo / Naga Auto dbg script / 3 | echo /****************************************/ 4 | display /i $pc 5 | -------------------------------------------------------------------------------- /src/build.sh: -------------------------------------------------------------------------------- 1 | rm ./udog 2 | make udog DEBUG=1 -------------------------------------------------------------------------------- /src/crc.cpp: -------------------------------------------------------------------------------- 1 | #include "crc.h" 2 | 3 | #if !defined(CRC_NOT_TABLE) 4 | /* CRC polynomial 0x04c11db7 */ 5 | unsigned crc_32_tab[]= { 6 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 7 | 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 8 | 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 9 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 10 | 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 11 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 12 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 13 | 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 14 | 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 15 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 16 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 17 | 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 18 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 19 | 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 20 | 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 21 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 22 | 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 23 | 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 24 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 25 | 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 26 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 27 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 28 | 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 29 | 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 30 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 31 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 32 | 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 33 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 34 | 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 35 | 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 36 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 37 | 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 38 | }; 39 | 40 | unsigned crc32(unsigned char* data, unsigned length) { 41 | unsigned CRC = 0xffffffff; 42 | 43 | while (length--) 44 | CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *data++) & 0xFF ]; 45 | 46 | return CRC ^ 0xFFFFFFFF; 47 | } 48 | 49 | unsigned crc32int(unsigned *data) { 50 | unsigned *d = data; 51 | unsigned CRC = 0xFFFFFFFF; 52 | 53 | CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; 54 | CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; 55 | CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; 56 | return (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d) & 0xFF ] ^ 0xFFFFFFFF; 57 | } 58 | 59 | #define __CRC_SELFTEST__ 0x6fcf9e13 60 | //#define __CRC_SELFTEST__ 0xca87914d 61 | 62 | bool crc32_selftests() { 63 | int i; 64 | unsigned crc = 0xFFFFFFFF; 65 | bool bSuccess = false; 66 | 67 | for (i = 0; i < (int)sizeof(crc_32_tab); i++) 68 | crc = UPDC32 (((unsigned char *) crc_32_tab)[i], crc); 69 | 70 | bSuccess = __CRC_SELFTEST__ == (crc ^ 0xFFFFFFFF); 71 | 72 | bSuccess &= crc32((unsigned char*)crc_32_tab, sizeof crc_32_tab) == __CRC_SELFTEST__; 73 | 74 | return bSuccess; 75 | } 76 | 77 | #else // CRC_NOT_TABLE 78 | 79 | unsigned crc32(__memory data, unsigned length) { 80 | unsigned r = 0xFFFFFFFFUL; 81 | unsigned i, b; 82 | 83 | for (i = 0; i < length; ++i) { 84 | r ^= data[i]; 85 | for (b = 0; b < 8; ++b) { 86 | if ((__byte) r & 1) 87 | r = (r >> 1) ^ 0xEDB88320UL; 88 | else 89 | r >>= 1; 90 | } 91 | } 92 | 93 | return r ^ 0xFFFFFFFFUL; 94 | } 95 | 96 | bool crc32_selftests() { 97 | unsigned char testData[32]; 98 | unsigned char i; 99 | 100 | for (i = 0; i < sizeof (testData); ++i) 101 | testData[i] = i; 102 | 103 | return crc32(testData, sizeof (testData)) == 0x91267E8AUL; 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /src/crc.h: -------------------------------------------------------------------------------- 1 | #if !defined(__CRC_H__) 2 | #define __CRC_H__ 3 | 4 | #define UPDC32(octet, crc)\ 5 | (unsigned)((crc_32_tab[(((unsigned)(crc)) ^ ((unsigned char)(octet))) & 0xff] ^ (((unsigned)(crc)) >> 8))) 6 | 7 | unsigned crc32(unsigned char* data, unsigned length); 8 | unsigned crc32int(unsigned *data); 9 | bool crc32_selftests(); 10 | 11 | extern unsigned crc_32_tab[]; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/debugger.cpp.bk: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 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 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, 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 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | extern int tgkill(int tgid, int tid, int sig); 40 | 41 | void notify_gdb_of_libraries(); 42 | 43 | #define DEBUGGER_SOCKET_NAME "android:debuggerd" 44 | 45 | typedef enum { 46 | // dump a crash 47 | DEBUGGER_ACTION_CRASH, 48 | // dump a tombstone file 49 | DEBUGGER_ACTION_DUMP_TOMBSTONE, 50 | // dump a backtrace only back to the socket 51 | DEBUGGER_ACTION_DUMP_BACKTRACE, 52 | } debugger_action_t; 53 | 54 | /* message sent over the socket */ 55 | typedef struct { 56 | debugger_action_t action; 57 | pid_t tid; 58 | } debugger_msg_t; 59 | 60 | #define RETRY_ON_EINTR(ret,cond) \ 61 | do { \ 62 | ret = (cond); \ 63 | } while (ret < 0 && errno == EINTR) 64 | 65 | // see man(2) prctl, specifically the section about PR_GET_NAME 66 | #define MAX_TASK_NAME_LEN (16) 67 | 68 | static int socket_abstract_client(const char *name, int type) 69 | { 70 | struct sockaddr_un addr; 71 | size_t namelen; 72 | socklen_t alen; 73 | int s, err; 74 | 75 | namelen = strlen(name); 76 | 77 | // Test with length +1 for the *initial* '\0'. 78 | if ((namelen + 1) > sizeof(addr.sun_path)) { 79 | errno = EINVAL; 80 | return -1; 81 | } 82 | 83 | /* This is used for abstract socket namespace, we need 84 | * an initial '\0' at the start of the Unix socket path. 85 | * 86 | * Note: The path in this case is *not* supposed to be 87 | * '\0'-terminated. ("man 7 unix" for the gory details.) 88 | */ 89 | memset (&addr, 0, sizeof addr); 90 | addr.sun_family = AF_LOCAL; 91 | addr.sun_path[0] = 0; 92 | memcpy(addr.sun_path + 1, name, namelen); 93 | 94 | alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1; 95 | 96 | s = socket(AF_LOCAL, type, 0); 97 | if(s < 0) return -1; 98 | 99 | RETRY_ON_EINTR(err,connect(s, (struct sockaddr *) &addr, alen)); 100 | if (err < 0) { 101 | close(s); 102 | s = -1; 103 | } 104 | 105 | return s; 106 | } 107 | 108 | #include "linker_format.h" 109 | #include <../libc/private/logd.h> 110 | 111 | /* 112 | * Writes a summary of the signal to the log file. We do this so that, if 113 | * for some reason we're not able to contact debuggerd, there is still some 114 | * indication of the failure in the log. 115 | * 116 | * We could be here as a result of native heap corruption, or while a 117 | * mutex is being held, so we don't want to use any libc functions that 118 | * could allocate memory or hold a lock. 119 | * 120 | * "info" will be NULL if the siginfo_t information was not available. 121 | */ 122 | static void logSignalSummary(int signum, const siginfo_t* info) 123 | { 124 | char buffer[128]; 125 | char threadname[MAX_TASK_NAME_LEN + 1]; // one more for termination 126 | 127 | char* signame; 128 | switch (signum) { 129 | case SIGILL: signame = "SIGILL"; break; 130 | case SIGABRT: signame = "SIGABRT"; break; 131 | case SIGBUS: signame = "SIGBUS"; break; 132 | case SIGFPE: signame = "SIGFPE"; break; 133 | case SIGSEGV: signame = "SIGSEGV"; break; 134 | #if defined(SIGSTKFLT) 135 | case SIGSTKFLT: signame = "SIGSTKFLT"; break; 136 | #endif 137 | case SIGPIPE: signame = "SIGPIPE"; break; 138 | default: signame = "???"; break; 139 | } 140 | 141 | if (prctl(PR_GET_NAME, (unsigned long)threadname, 0, 0, 0) != 0) { 142 | strcpy(threadname, ""); 143 | } else { 144 | // short names are null terminated by prctl, but the manpage 145 | // implies that 16 byte names are not. 146 | threadname[MAX_TASK_NAME_LEN] = 0; 147 | } 148 | if (info != NULL) { 149 | format_buffer(buffer, sizeof(buffer), 150 | "Fatal signal %d (%s) at 0x%08x (code=%d), thread %d (%s)", 151 | signum, signame, info->si_addr, info->si_code, gettid(), threadname); 152 | } else { 153 | format_buffer(buffer, sizeof(buffer), 154 | "Fatal signal %d (%s), thread %d (%s)", 155 | signum, signame, gettid(), threadname); 156 | } 157 | 158 | __libc_android_log_write(ANDROID_LOG_FATAL, "libc", buffer); 159 | } 160 | 161 | /* 162 | * Returns true if the handler for signal "signum" has SA_SIGINFO set. 163 | */ 164 | static bool haveSiginfo(int signum) 165 | { 166 | struct sigaction oldact, newact; 167 | 168 | memset(&newact, 0, sizeof(newact)); 169 | newact.sa_handler = SIG_DFL; 170 | newact.sa_flags = SA_RESTART; 171 | sigemptyset(&newact.sa_mask); 172 | 173 | if (sigaction(signum, &newact, &oldact) < 0) { 174 | __libc_android_log_write(ANDROID_LOG_FATAL, "libc", 175 | "Failed testing for SA_SIGINFO"); 176 | return 0; 177 | } 178 | bool ret = (oldact.sa_flags & SA_SIGINFO) != 0; 179 | 180 | if (sigaction(signum, &oldact, NULL) < 0) { 181 | __libc_android_log_write(ANDROID_LOG_FATAL, "libc", 182 | "Restore failed in test for SA_SIGINFO"); 183 | } 184 | return ret; 185 | } 186 | 187 | /* 188 | * Catches fatal signals so we can ask debuggerd to ptrace us before 189 | * we crash. 190 | */ 191 | void debugger_signal_handler(int n, siginfo_t* info, void* unused __attribute__((unused))) 192 | { 193 | char msgbuf[128]; 194 | unsigned tid; 195 | int s; 196 | 197 | /* 198 | * It's possible somebody cleared the SA_SIGINFO flag, which would mean 199 | * our "info" arg holds an undefined value. 200 | */ 201 | if (!haveSiginfo(n)) { 202 | info = NULL; 203 | } 204 | 205 | logSignalSummary(n, info); 206 | 207 | tid = gettid(); 208 | s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM); 209 | 210 | if (s >= 0) { 211 | /* debugger knows our pid from the credentials on the 212 | * local socket but we need to tell it our tid. It 213 | * is paranoid and will verify that we are giving a tid 214 | * that's actually in our process 215 | */ 216 | int ret; 217 | debugger_msg_t msg; 218 | msg.action = DEBUGGER_ACTION_CRASH; 219 | msg.tid = tid; 220 | RETRY_ON_EINTR(ret, write(s, &msg, sizeof(msg))); 221 | if (ret == sizeof(msg)) { 222 | /* if the write failed, there is no point to read on 223 | * the file descriptor. */ 224 | RETRY_ON_EINTR(ret, read(s, &tid, 1)); 225 | int savedErrno = errno; 226 | notify_gdb_of_libraries(); 227 | errno = savedErrno; 228 | } 229 | 230 | if (ret < 0) { 231 | /* read or write failed -- broken connection? */ 232 | format_buffer(msgbuf, sizeof(msgbuf), 233 | "Failed while talking to debuggerd: %s", strerror(errno)); 234 | __libc_android_log_write(ANDROID_LOG_FATAL, "libc", msgbuf); 235 | } 236 | 237 | close(s); 238 | } else { 239 | /* socket failed; maybe process ran out of fds */ 240 | format_buffer(msgbuf, sizeof(msgbuf), 241 | "Unable to open connection to debuggerd: %s", strerror(errno)); 242 | __libc_android_log_write(ANDROID_LOG_FATAL, "libc", msgbuf); 243 | } 244 | 245 | /* remove our net so we fault for real when we return */ 246 | signal(n, SIG_DFL); 247 | 248 | /* 249 | * These signals are not re-thrown when we resume. This means that 250 | * crashing due to (say) SIGPIPE doesn't work the way you'd expect it 251 | * to. We work around this by throwing them manually. We don't want 252 | * to do this for *all* signals because it'll screw up the address for 253 | * faults like SIGSEGV. 254 | */ 255 | switch (n) { 256 | case SIGABRT: 257 | case SIGFPE: 258 | case SIGPIPE: 259 | #ifdef SIGSTKFLT 260 | case SIGSTKFLT: 261 | #endif 262 | (void) tgkill(getpid(), gettid(), n); 263 | break; 264 | default: // SIGILL, SIGBUS, SIGSEGV 265 | break; 266 | } 267 | } 268 | 269 | /* 调试器初始化 */ 270 | void debugger_init() 271 | { 272 | struct sigaction act; 273 | memset(&act, 0, sizeof(act)); 274 | act.sa_sigaction = debugger_signal_handler; 275 | act.sa_flags = SA_RESTART | SA_SIGINFO; 276 | sigemptyset(&act.sa_mask); 277 | 278 | sigaction(SIGILL, &act, NULL); 279 | sigaction(SIGABRT, &act, NULL); 280 | sigaction(SIGBUS, &act, NULL); 281 | sigaction(SIGFPE, &act, NULL); 282 | sigaction(SIGSEGV, &act, NULL); 283 | #if defined(SIGSTKFLT) 284 | sigaction(SIGSTKFLT, &act, NULL); 285 | #endif 286 | sigaction(SIGPIPE, &act, NULL); 287 | } 288 | -------------------------------------------------------------------------------- /src/dk-client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 安装udog到模拟器 4 | # 自动启动udog到调试器 5 | # 启动本地的调试器,并且与远程对接 6 | # 启动a-gdbtui 7 | 8 | AGdbtui="a-gdbtui" 9 | TP=1234 10 | SymbolFile="~/workspace/udog/src/udog.out" 11 | #BreakLine=3021 12 | 13 | $AGdbtui 14 | -------------------------------------------------------------------------------- /src/dk-server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 安装udog到模拟器 4 | # 自动启动udog到调试器 5 | # 启动本地的调试器,并且与远程对接 6 | 7 | # 默认的目标名称 8 | Target="./udog.out" 9 | TargetTest="./libiSecurityPAB.so" 10 | TargetParam="--dump=./libiSecurityPAB.so.dump --debug=10 ./libiSecurityPAB.so" 11 | GdbServerPort=1234 12 | Gdb="a-gdbtui" 13 | 14 | echo "[INFO]remove target" 15 | rm $Target 16 | 17 | echo "[INFO]make target" 18 | make DEBUG=1 UDOG_VERSION=1 all 19 | 20 | echo "[INFO]adb push target to /data" 21 | adb push $Target /data 22 | 23 | echo "[INFO]adb push target test file to /data" 24 | adb push $TargetTest /data 25 | 26 | # grep -Po '(?<=\[\d\]\s)\d+' 27 | # gdbserver :$GdbServerPort --attach 28 | # 匹配以[数字]任意空格 开头的字符然后在匹配后面的一个或多个数字 29 | echo "[INFO]set adb forward port" 30 | adb forward tcp:$GdbServerPort tcp:$GdbServerPort 31 | 32 | echo "[INFO]start debugging $Target" 33 | adb shell < 18 | #include 19 | #include "linker.h" 20 | #include "linker_format.h" 21 | 22 | /* This file hijacks the symbols stubbed out in libdl.so. */ 23 | 24 | #define DL_SUCCESS 0 25 | #define DL_ERR_CANNOT_LOAD_LIBRARY 1 26 | #define DL_ERR_INVALID_LIBRARY_HANDLE 2 27 | #define DL_ERR_BAD_SYMBOL_NAME 3 28 | #define DL_ERR_SYMBOL_NOT_FOUND 4 29 | #define DL_ERR_SYMBOL_NOT_GLOBAL 5 30 | 31 | static char dl_err_buf[1024]; 32 | static const char *dl_err_str; 33 | 34 | static const char *dl_errors[] = { 35 | "Success", 36 | "Cannot load library", 37 | "Invalid library handle", 38 | "Invalid symbol name", 39 | "Symbol not found", 40 | "Symbol is not global", 41 | }; 42 | 43 | #define likely(expr) __builtin_expect (expr, 1) 44 | #define unlikely(expr) __builtin_expect (expr, 0) 45 | 46 | pthread_mutex_t dl_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; 47 | 48 | static void set_dlerror(int err) 49 | { 50 | format_buffer(dl_err_buf, sizeof(dl_err_buf), "%s: %s", dl_errors[err], 51 | linker_get_error()); 52 | dl_err_str = (const char *)&dl_err_buf[0]; 53 | }; 54 | 55 | void *dlopen(const char *filename, int flag UNUSED) 56 | { 57 | soinfo *ret; 58 | 59 | pthread_mutex_lock(&dl_lock); 60 | /* 寻找库,并加载 */ 61 | ret = find_library(filename); 62 | if (unlikely(ret == NULL)) { 63 | set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY); 64 | } else { 65 | /* 调用构造函数 */ 66 | soinfo_call_constructors_from_dlopen(ret); 67 | ret->refcount++; 68 | } 69 | pthread_mutex_unlock(&dl_lock); 70 | return ret; 71 | } 72 | 73 | const char *dlerror(void) 74 | { 75 | const char *tmp = dl_err_str; 76 | dl_err_str = NULL; 77 | return (const char *)tmp; 78 | } 79 | 80 | void *dlsym(void *handle, const char *symbol) 81 | { 82 | soinfo *found; 83 | Elf32_Sym *sym; 84 | unsigned bind; 85 | 86 | pthread_mutex_lock(&dl_lock); 87 | 88 | if(unlikely(handle == 0)) { 89 | set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE); 90 | goto err; 91 | } 92 | if(unlikely(symbol == 0)) { 93 | set_dlerror(DL_ERR_BAD_SYMBOL_NAME); 94 | goto err; 95 | } 96 | 97 | if(handle == RTLD_DEFAULT) { 98 | sym = lookup(symbol, &found, NULL); 99 | } else if(handle == RTLD_NEXT) { 100 | void *ret_addr = __builtin_return_address(0); 101 | soinfo *si = find_containing_library(ret_addr); 102 | 103 | sym = NULL; 104 | if(si && si->next) { 105 | sym = lookup(symbol, &found, si->next); 106 | } 107 | } else { 108 | found = (soinfo*)handle; 109 | sym = soinfo_lookup(found, symbol); 110 | } 111 | 112 | if(likely(sym != 0)) { 113 | bind = ELF32_ST_BIND(sym->st_info); 114 | 115 | if(likely((bind == STB_GLOBAL) && (sym->st_shndx != 0))) { 116 | unsigned ret = sym->st_value + found->base; 117 | pthread_mutex_unlock(&dl_lock); 118 | return (void*)ret; 119 | } 120 | 121 | set_dlerror(DL_ERR_SYMBOL_NOT_GLOBAL); 122 | } 123 | else 124 | set_dlerror(DL_ERR_SYMBOL_NOT_FOUND); 125 | 126 | err: 127 | pthread_mutex_unlock(&dl_lock); 128 | return 0; 129 | } 130 | 131 | int dladdr(const void *addr, Dl_info* info) 132 | { 133 | int ret = 0; 134 | 135 | pthread_mutex_lock(&dl_lock); 136 | 137 | /* Determine if this address can be found in any library currently mapped */ 138 | soinfo *si = find_containing_library(addr); 139 | 140 | if(si) { 141 | memset(info, 0, sizeof(Dl_info)); 142 | 143 | info->dli_fname = si->name; 144 | info->dli_fbase = (void*)si->base; 145 | 146 | /* Determine if any symbol in the library contains the specified address */ 147 | Elf32_Sym *sym = soinfo_find_symbol(si, addr); 148 | 149 | if(sym != NULL) { 150 | info->dli_sname = si->strtab + sym->st_name; 151 | info->dli_saddr = (void*)(si->base + sym->st_value); 152 | } 153 | 154 | ret = 1; 155 | } 156 | 157 | pthread_mutex_unlock(&dl_lock); 158 | 159 | return ret; 160 | } 161 | 162 | int dlclose(void* handle) { 163 | pthread_mutex_lock(&dl_lock); 164 | int result = soinfo_unload((soinfo*)handle); 165 | pthread_mutex_unlock(&dl_lock); 166 | return result; 167 | } 168 | -------------------------------------------------------------------------------- /src/gdb_udog.sh: -------------------------------------------------------------------------------- 1 | # 安装xlinker到模拟器 2 | # 自动启动xlinker到调试器 3 | # 启动本地的调试器,并且与远程对接 4 | 5 | rm xlinker 6 | make xlinker DEBUG=1 XLINKER_VERSION=1 all 7 | adb push ./xlinker.out /data/ 8 | adb push ./libhello.so /data 9 | adb shell 10 | -------------------------------------------------------------------------------- /src/libPingan.so.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devilogic/udog/a1672a932ef089bfd0320bce53297b4ed34e7319/src/libPingan.so.dump -------------------------------------------------------------------------------- /src/libiSecurityPAB.so.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devilogic/udog/a1672a932ef089bfd0320bce53297b4ed34e7319/src/libiSecurityPAB.so.dump -------------------------------------------------------------------------------- /src/linker.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 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 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, 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 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _LINKER_H_ 30 | #define _LINKER_H_ 31 | 32 | #include 33 | #include 34 | #include 35 | #ifdef ANDROID 36 | #include 37 | #endif 38 | 39 | #ifdef __cplusplus 40 | extern "C" { 41 | #endif 42 | #include 43 | 44 | #define UNUSED __attribute__((unused)) 45 | 46 | #undef PAGE_MASK 47 | #undef PAGE_SIZE 48 | #define PAGE_SIZE 4096 49 | #define PAGE_MASK (PAGE_SIZE-1) 50 | 51 | /* Convenience macros to make page address/offset computations more explicit */ 52 | 53 | /* Returns the address of the page starting at address 'x' */ 54 | #define PAGE_START(x) ((x) & ~PAGE_MASK) 55 | 56 | /* Returns the offset of address 'x' in its memory page, i.e. this is the 57 | * same than 'x' - PAGE_START(x) */ 58 | /* 实际上这个返回了当前偏移值 - PAGE_START(x) 之间的差值 59 | */ 60 | #define PAGE_OFFSET(x) ((x) & PAGE_MASK) 61 | 62 | /* Returns the address of the next page after address 'x', unless 'x' is 63 | * itself at the start of a page. Equivalent to: 64 | * 65 | * (x == PAGE_START(x)) ? x : PAGE_START(x)+PAGE_SIZE 66 | */ 67 | #define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1)) 68 | 69 | void debugger_init(); 70 | 71 | /* magic shared structures that GDB knows about */ 72 | 73 | struct link_map 74 | { 75 | uintptr_t l_addr; /* 内存加载地址 */ 76 | char * l_name; /* 名称 */ 77 | uintptr_t l_ld; /* 动态段内存地址 */ 78 | struct link_map * l_next; 79 | struct link_map * l_prev; 80 | }; 81 | 82 | // Values for r_debug->state 83 | enum { 84 | RT_CONSISTENT, 85 | RT_ADD, 86 | RT_DELETE 87 | }; 88 | 89 | /* 对GDB调试器的接口 */ 90 | struct r_debug 91 | { 92 | int32_t r_version; 93 | struct link_map * r_map; 94 | void (*r_brk)(void); 95 | int32_t r_state; 96 | uintptr_t r_ldbase; 97 | }; 98 | 99 | typedef struct soinfo soinfo; 100 | 101 | #define FLAG_LINKED 0x00000001 /* 已经进行链接 */ 102 | #define FLAG_ERROR 0x00000002 /* 打印出错信息 */ 103 | #define FLAG_EXE 0x00000004 /* 可执行文件 */ 104 | #define FLAG_LINKER 0x00000010 /* 链接器自身 */ 105 | 106 | #define SOINFO_NAME_LEN 128 107 | 108 | /* so信息结构 */ 109 | struct soinfo 110 | { 111 | char name[SOINFO_NAME_LEN]; /* SO名称 */ 112 | const Elf32_Phdr *phdr; /* 指向程序段头表 */ 113 | int phnum; 114 | unsigned entry; 115 | unsigned base; 116 | unsigned size; /* 所有可加载段的长度 */ 117 | 118 | int unused; // DO NOT USE, maintained for compatibility. 119 | 120 | unsigned *dynamic; 121 | 122 | unsigned unused2; // DO NOT USE, maintained for compatibility 123 | unsigned unused3; // DO NOT USE, maintained for compatibility 124 | 125 | soinfo *next; 126 | unsigned flags; 127 | 128 | const char *strtab; 129 | Elf32_Sym *symtab; 130 | 131 | unsigned nbucket; 132 | unsigned nchain; 133 | unsigned *bucket; 134 | unsigned *chain; 135 | 136 | unsigned *plt_got; 137 | 138 | Elf32_Rel *plt_rel; 139 | unsigned plt_rel_count; 140 | 141 | Elf32_Rel *rel; 142 | unsigned rel_count; 143 | 144 | unsigned *preinit_array; 145 | unsigned preinit_array_count; 146 | 147 | unsigned *init_array; 148 | unsigned init_array_count; 149 | unsigned *fini_array; 150 | unsigned fini_array_count; 151 | 152 | void (*init_func)(void); 153 | void (*fini_func)(void); 154 | 155 | #if defined(ANDROID_ARM_LINKER) 156 | /* ARM EABI section used for stack unwinding. */ 157 | unsigned *ARM_exidx; 158 | unsigned ARM_exidx_count; 159 | #elif defined(ANDROID_MIPS_LINKER) 160 | #if 0 161 | /* not yet */ 162 | unsigned *mips_pltgot 163 | #endif 164 | unsigned mips_symtabno; 165 | unsigned mips_local_gotno; 166 | unsigned mips_gotsym; 167 | #endif /* ANDROID_*_LINKER */ 168 | 169 | unsigned refcount; 170 | struct link_map linkmap; 171 | 172 | int constructors_called; /* 构造函数已经被调用 */ 173 | 174 | /* When you read a virtual address from the ELF file, add this 175 | * value to get the corresponding address in the process' address space */ 176 | Elf32_Addr load_bias; 177 | int has_text_relocations; 178 | 179 | /* 表明是否是从主程序中调用 */ 180 | //int loader_is_main; 181 | }; 182 | 183 | 184 | extern soinfo libdl_info; 185 | 186 | #ifdef ANDROID 187 | #include 188 | #endif 189 | 190 | #if defined(ANDROID_ARM_LINKER) 191 | 192 | // These aren't defined in . 193 | #define R_ARM_REL32 3 194 | #define R_ARM_COPY 20 195 | #define R_ARM_GLOB_DAT 21 196 | #define R_ARM_JUMP_SLOT 22 197 | #define R_ARM_RELATIVE 23 198 | 199 | #elif defined(ANDROID_MIPS_LINKER) 200 | 201 | // These aren't defined in . 202 | #define R_MIPS_JUMP_SLOT 127 203 | 204 | #define DT_MIPS_PLTGOT 0x70000032 205 | #define DT_MIPS_RWPLT 0x70000034 206 | 207 | #elif defined(ANDROID_X86_LINKER) 208 | 209 | // x86 has everything it needs in . 210 | 211 | #endif /* ANDROID_*_LINKER */ 212 | 213 | #ifndef DT_INIT_ARRAY 214 | #define DT_INIT_ARRAY 25 215 | #endif 216 | 217 | #ifndef DT_FINI_ARRAY 218 | #define DT_FINI_ARRAY 26 219 | #endif 220 | 221 | #ifndef DT_INIT_ARRAYSZ 222 | #define DT_INIT_ARRAYSZ 27 223 | #endif 224 | 225 | #ifndef DT_FINI_ARRAYSZ 226 | #define DT_FINI_ARRAYSZ 28 227 | #endif 228 | 229 | #ifndef DT_PREINIT_ARRAY 230 | #define DT_PREINIT_ARRAY 32 231 | #endif 232 | 233 | #ifndef DT_PREINIT_ARRAYSZ 234 | #define DT_PREINIT_ARRAYSZ 33 235 | #endif 236 | 237 | soinfo *find_library(const char *name); 238 | Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start); 239 | soinfo *find_containing_library(const void *addr); 240 | const char *linker_get_error(void); 241 | 242 | int soinfo_unload(soinfo* si); 243 | Elf32_Sym *soinfo_find_symbol(soinfo* si, const void *addr); 244 | Elf32_Sym *soinfo_lookup(soinfo *si, const char *name); 245 | void soinfo_call_constructors(soinfo *si); 246 | void soinfo_call_constructors_from_dlopen(soinfo *si); 247 | 248 | #ifdef __cplusplus 249 | }; 250 | #endif 251 | 252 | #endif 253 | -------------------------------------------------------------------------------- /src/linker_debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2010 The Android Open Source Project 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 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, 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 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _LINKER_DEBUG_H_ 30 | #define _LINKER_DEBUG_H_ 31 | 32 | #include 33 | 34 | #ifndef LINKER_DEBUG 35 | #error LINKER_DEBUG should be defined to either 1 or 0 in Makefile 36 | #endif 37 | 38 | /* set LINKER_DEBUG_TO_LOG to 1 to send the logs to logcat, 39 | * or 0 to use stdout instead. 40 | */ 41 | #define LINKER_DEBUG_TO_LOG 1 42 | #define TRACE_DEBUG 1 43 | #define DO_TRACE_LOOKUP 1 44 | #define DO_TRACE_RELO 1 45 | #define TIMING 0 46 | #define STATS 0 47 | #define COUNT_PAGES 0 48 | 49 | /********************************************************************* 50 | * You shouldn't need to modify anything below unless you are adding 51 | * more debugging information. 52 | * 53 | * To enable/disable specific debug options, change the defines above 54 | *********************************************************************/ 55 | 56 | 57 | /*********************************************************************/ 58 | 59 | /* Only use printf() during debugging. We have seen occasional memory 60 | * corruption when the linker uses printf(). 61 | */ 62 | #if LINKER_DEBUG == 1 63 | #include "linker_format.h" 64 | 65 | #ifdef __cplusplus 66 | extern "C" { 67 | #endif 68 | 69 | /* 调试linker所需 */ 70 | extern int debug_verbosity; 71 | #if LINKER_DEBUG_TO_LOG == 1 72 | extern int format_log(int, const char *, const char *, ...); 73 | #define _PRINTVF(v,x...) \ 74 | do { \ 75 | if (debug_verbosity > (v)) format_log(5-(v),"linker",x); \ 76 | } while (0) 77 | #else /* !LINKER_DEBUG_TO_LOG */ 78 | extern int format_fd(int, const char *, ...); 79 | #define _PRINTVF(v,x...) \ 80 | do { \ 81 | if (debug_verbosity > (v)) format_fd(1, x); \ 82 | } while (0) 83 | #endif /* !LINKER_DEBUG_TO_LOG */ 84 | 85 | #ifdef __cplusplus 86 | }; 87 | #endif 88 | 89 | #else /* !LINKER_DEBUG */ 90 | #define _PRINTVF(v,f,x...) do {} while(0) 91 | #endif /* LINKER_DEBUG */ 92 | 93 | #define PRINT(x...) _PRINTVF(-1, x) 94 | #define INFO(x...) _PRINTVF(0, x) 95 | #define TRACE(x...) _PRINTVF(1, x) 96 | #define WARN(fmt,args...) \ 97 | _PRINTVF(-1, "%s:%d| WARNING: " fmt, __FILE__, __LINE__, ## args) 98 | #define ERROR(fmt,args...) \ 99 | _PRINTVF(-1, "%s:%d| ERROR: " fmt, __FILE__, __LINE__, ## args) 100 | 101 | 102 | #if TRACE_DEBUG == 1 103 | #define DEBUG(x...) _PRINTVF(2, "DEBUG: " x) 104 | #else /* !TRACE_DEBUG */ 105 | #define DEBUG(x...) do {} while (0) 106 | #endif /* TRACE_DEBUG */ 107 | 108 | #if LINKER_DEBUG == 1 109 | #define TRACE_TYPE(t,x...) do { if (DO_TRACE_##t) { TRACE(x); } } while (0) 110 | #else /* !LINKER_DEBUG */ 111 | #define TRACE_TYPE(t,x...) do {} while (0) 112 | #endif /* LINKER_DEBUG */ 113 | 114 | #if TIMING == 1 115 | #undef WARN 116 | #define WARN(x...) do {} while (0) 117 | #endif /* TIMING */ 118 | 119 | #define DEBUG_DUMP_PHDR(phdr, name, pid) do { \ 120 | DEBUG("%5d %s (phdr = 0x%08x)\n", (pid), (name), (unsigned)(phdr)); \ 121 | DEBUG("\t\tphdr->offset = 0x%08x\n", (unsigned)((phdr)->p_offset)); \ 122 | DEBUG("\t\tphdr->p_vaddr = 0x%08x\n", (unsigned)((phdr)->p_vaddr)); \ 123 | DEBUG("\t\tphdr->p_paddr = 0x%08x\n", (unsigned)((phdr)->p_paddr)); \ 124 | DEBUG("\t\tphdr->p_filesz = 0x%08x\n", (unsigned)((phdr)->p_filesz)); \ 125 | DEBUG("\t\tphdr->p_memsz = 0x%08x\n", (unsigned)((phdr)->p_memsz)); \ 126 | DEBUG("\t\tphdr->p_flags = 0x%08x\n", (unsigned)((phdr)->p_flags)); \ 127 | DEBUG("\t\tphdr->p_align = 0x%08x\n", (unsigned)((phdr)->p_align)); \ 128 | } while (0) 129 | 130 | #endif /* _LINKER_DEBUG_H_ */ 131 | -------------------------------------------------------------------------------- /src/linker_environ.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 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 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, 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 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #include "linker_environ.h" 29 | #include 30 | 31 | static char** _envp; 32 | 33 | /* Returns 1 if 'str' points to a valid environment variable definition. 34 | * For now, we check that: 35 | * - It is smaller than MAX_ENV_LEN (to detect non-zero terminated strings) 36 | * - It contains at least one equal sign that is not the first character 37 | * 38 | * 返回1说明 'str' 指向一个有效环境变量定义 39 | */ 40 | static int 41 | _is_valid_definition(const char* str) 42 | { 43 | int pos = 0; 44 | int first_equal_pos = -1; 45 | 46 | /* According to its sources, the kernel uses 32*PAGE_SIZE by default 47 | * as the maximum size for an env. variable definition. 48 | */ 49 | const int MAX_ENV_LEN = 32*4096; 50 | 51 | if (str == NULL) 52 | return 0; 53 | 54 | /* Parse the string, looking for the first '=' there, and its size */ 55 | do { 56 | if (str[pos] == '\0') 57 | break; 58 | if (str[pos] == '=' && first_equal_pos < 0) 59 | first_equal_pos = pos; 60 | pos++; 61 | } while (pos < MAX_ENV_LEN); 62 | 63 | if (pos >= MAX_ENV_LEN) /* Too large */ 64 | return 0; 65 | 66 | if (first_equal_pos < 1) /* No equal sign, or it is the first character */ 67 | return 0; 68 | 69 | return 1; 70 | } 71 | 72 | /* 初始化环境,确定 */ 73 | unsigned* 74 | linker_env_init(unsigned* vecs) 75 | { 76 | /* Store environment pointer - can't be NULL */ 77 | _envp = (char**) vecs; 78 | 79 | /* Skip over all definitions */ 80 | while (vecs[0] != 0) 81 | vecs++; 82 | /* The end of the environment block is marked by two NULL pointers */ 83 | vecs++; 84 | 85 | /* As a sanity check, we're going to remove all invalid variable 86 | * definitions from the environment array. 87 | */ 88 | { 89 | char** readp = _envp; 90 | char** writep = _envp; 91 | for ( ; readp[0] != NULL; readp++ ) { 92 | /* 如果不是一个有效环境定义则继续下一个 */ 93 | if (!_is_valid_definition(readp[0])) 94 | continue; 95 | /* 仅记录有效的环境块 */ 96 | writep[0] = readp[0]; 97 | writep++; 98 | } 99 | writep[0] = NULL; 100 | } 101 | 102 | /* Return the address of the aux vectors table */ 103 | return vecs; 104 | } 105 | 106 | /* Check if the environment variable definition at 'envstr' 107 | * starts with '=', and if so return the address of the 108 | * first character after the equal sign. Otherwise return NULL. 109 | * 进行变量名匹配,匹配则返回值字符串指针 110 | */ 111 | static char* 112 | env_match(char* envstr, const char* name) 113 | { 114 | size_t cnt = 0; 115 | 116 | while (envstr[cnt] == name[cnt] && name[cnt] != '\0') 117 | cnt++; 118 | 119 | if (name[cnt] == '\0' && envstr[cnt] == '=') 120 | return envstr + cnt + 1; /* 返回变量的值 */ 121 | 122 | return NULL; 123 | } 124 | 125 | #define MAX_ENV_LEN (16*4096) 126 | 127 | /* 获取变量的值 */ 128 | const char* 129 | linker_env_get(const char* name) 130 | { 131 | char** readp = _envp; 132 | 133 | if (name == NULL || name[0] == '\0') 134 | return NULL; 135 | 136 | for ( ; readp[0] != NULL; readp++ ) { 137 | char* val = env_match(readp[0], name); 138 | if (val != NULL) { 139 | /* Return NULL for empty strings, or if it is too large */ 140 | if (val[0] == '\0') 141 | val = NULL; 142 | return val; 143 | } 144 | } 145 | return NULL; 146 | } 147 | 148 | /* 移除在name中的变量 */ 149 | void 150 | linker_env_unset(const char* name) 151 | { 152 | char** readp = _envp; 153 | char** writep = readp; 154 | 155 | if (name == NULL || name[0] == '\0') 156 | return; 157 | 158 | for ( ; readp[0] != NULL; readp++ ) { 159 | /* 找到匹配的变量 */ 160 | if (env_match(readp[0], name)) 161 | continue; 162 | writep[0] = readp[0]; 163 | writep++; 164 | } 165 | /* end list with a NULL */ 166 | writep[0] = NULL; 167 | } 168 | 169 | 170 | 171 | /* Remove unsafe environment variables. This should be used when 172 | * running setuid programs. */ 173 | /* 移除不安全的环境变量,当setuid程序则移除下列变量 */ 174 | void 175 | linker_env_secure(void) 176 | { 177 | /* The same list than GLibc at this point */ 178 | static const char* const unsec_vars[] = { 179 | "GCONV_PATH", 180 | "GETCONF_DIR", 181 | "HOSTALIASES", 182 | "LD_AUDIT", 183 | "LD_DEBUG", 184 | "LD_DEBUG_OUTPUT", 185 | "LD_DYNAMIC_WEAK", 186 | "LD_LIBRARY_PATH", 187 | "LD_ORIGIN_PATH", 188 | "LD_PRELOAD", 189 | "LD_PROFILE", 190 | "LD_SHOW_AUXV", 191 | "LD_USE_LOAD_BIAS", 192 | "LOCALDOMAIN", 193 | "LOCPATH", 194 | "MALLOC_TRACE", 195 | "MALLOC_CHECK_", 196 | "NIS_PATH", 197 | "NLSPATH", 198 | "RESOLV_HOST_CONF", 199 | "RES_OPTIONS", 200 | "TMPDIR", 201 | "TZDIR", 202 | "LD_AOUT_LIBRARY_PATH", 203 | "LD_AOUT_PRELOAD", 204 | NULL 205 | }; 206 | 207 | int count; 208 | for (count = 0; unsec_vars[count] != NULL; count++) { 209 | linker_env_unset(unsec_vars[count]); 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/linker_environ.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 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 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, 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 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef LINKER_ENVIRON_H 29 | #define LINKER_ENVIRON_H 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* Call this function before anything else. 'vecs' must be the pointer 36 | * to the environment block in the ELF data block. The function returns 37 | * the start of the aux vectors after the env block. 38 | */ 39 | extern unsigned* linker_env_init(unsigned* vecs); 40 | 41 | /* Unset a given environment variable. In case the variable is defined 42 | * multiple times, unset all instances. This modifies the environment 43 | * block, so any pointer returned by linker_env_get() after this call 44 | * might become invalid */ 45 | extern void linker_env_unset(const char* name); 46 | 47 | 48 | /* Returns the value of environment variable 'name' if defined and not 49 | * empty, or NULL otherwise. Note that the returned pointer may become 50 | * invalid if linker_env_unset() or linker_env_secure() are called 51 | * after this function. */ 52 | extern const char* linker_env_get(const char* name); 53 | 54 | /* Remove insecure environment variables. This should be used when 55 | * running setuid programs. */ 56 | extern void linker_env_secure(void); 57 | 58 | #ifdef __cplusplus 59 | }; 60 | #endif 61 | 62 | #endif /* LINKER_ENVIRON_H */ 63 | -------------------------------------------------------------------------------- /src/linker_format.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 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 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, 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 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "linker_format.h" 36 | #include "linker_debug.h" 37 | 38 | /* define UNIT_TESTS to build this file as a single executable that runs 39 | * the formatter's unit tests 40 | */ 41 | #define xxUNIT_TESTS 42 | 43 | /*** Generic output sink 44 | ***/ 45 | 46 | typedef struct { 47 | void *opaque; 48 | void (*send)(void *opaque, const char *data, int len); 49 | } Out; 50 | 51 | static void 52 | out_send(Out *o, const void *data, size_t len) 53 | { 54 | o->send(o->opaque, (const char*)data, (int)len); 55 | } 56 | 57 | static void 58 | out_send_repeat(Out *o, char ch, int count) 59 | { 60 | char pad[8]; 61 | const int padSize = (int)sizeof(pad); 62 | 63 | memset(pad, ch, sizeof(pad)); 64 | while (count > 0) { 65 | int avail = count; 66 | if (avail > padSize) { 67 | avail = padSize; 68 | } 69 | o->send(o->opaque, pad, avail); 70 | count -= avail; 71 | } 72 | } 73 | 74 | /* forward declaration */ 75 | static void 76 | out_vformat(Out *o, const char *format, va_list args); 77 | 78 | /*** Bounded buffer output 79 | ***/ 80 | 81 | typedef struct { 82 | Out out[1]; 83 | char *buffer; 84 | char *pos; 85 | char *end; 86 | int total; 87 | } BufOut; 88 | 89 | static void 90 | buf_out_send(void *opaque, const char *data, int len) 91 | { 92 | BufOut *bo = (BufOut*)opaque; 93 | 94 | if (len < 0) 95 | len = strlen(data); 96 | 97 | bo->total += len; 98 | 99 | while (len > 0) { 100 | int avail = bo->end - bo->pos; 101 | if (avail == 0) 102 | break; 103 | if (avail > len) 104 | avail = len; 105 | memcpy(bo->pos, data, avail); 106 | bo->pos += avail; 107 | bo->pos[0] = '\0'; 108 | len -= avail; 109 | } 110 | } 111 | 112 | static Out* 113 | buf_out_init(BufOut *bo, char *buffer, size_t size) 114 | { 115 | if (size == 0) 116 | return NULL; 117 | 118 | bo->out->opaque = bo; 119 | bo->out->send = buf_out_send; 120 | bo->buffer = buffer; 121 | bo->end = buffer + size - 1; 122 | bo->pos = bo->buffer; 123 | bo->pos[0] = '\0'; 124 | bo->total = 0; 125 | 126 | return bo->out; 127 | } 128 | 129 | static int 130 | buf_out_length(BufOut *bo) 131 | { 132 | return bo->total; 133 | } 134 | 135 | static int 136 | vformat_buffer(char *buff, size_t buffsize, const char *format, va_list args) 137 | { 138 | BufOut bo; 139 | Out *out; 140 | 141 | out = buf_out_init(&bo, buff, buffsize); 142 | if (out == NULL) 143 | return 0; 144 | 145 | out_vformat(out, format, args); 146 | 147 | return buf_out_length(&bo); 148 | } 149 | 150 | int 151 | format_buffer(char *buff, size_t buffsize, const char *format, ...) 152 | { 153 | va_list args; 154 | int ret; 155 | 156 | va_start(args, format); 157 | ret = vformat_buffer(buff, buffsize, format, args); 158 | va_end(args); 159 | 160 | return ret; 161 | } 162 | 163 | /* The __stack_chk_fail() function calls __libc_android_log_print() 164 | * which calls vsnprintf(). 165 | * 166 | * We define our version of the function here to avoid dragging 167 | * about 25 KB of C library routines related to formatting. 168 | */ 169 | int 170 | vsnprintf(char *buff, size_t bufsize, const char *format, va_list args) 171 | { 172 | return format_buffer(buff, bufsize, format, args); 173 | } 174 | 175 | /* The pthread implementation uses snprintf(). If we define it here, we 176 | * avoid pulling the stdio vfprintf() implementation into the linker 177 | * saving about 19KB of machine code. 178 | */ 179 | int 180 | snprintf(char* buff, size_t bufsize, const char* format, ...) 181 | { 182 | va_list args; 183 | int ret; 184 | va_start(args, format); 185 | ret = vsnprintf(buff, bufsize, format, args); 186 | va_end(args); 187 | return ret; 188 | } 189 | 190 | #if LINKER_DEBUG == 1 191 | 192 | #if LINKER_DEBUG_TO_LOG == 0 193 | 194 | /*** File descriptor output 195 | ***/ 196 | 197 | typedef struct { 198 | Out out[1]; 199 | int fd; 200 | int total; 201 | } FdOut; 202 | 203 | static void 204 | fd_out_send(void *opaque, const char *data, int len) 205 | { 206 | FdOut *fdo = opaque; 207 | 208 | if (len < 0) 209 | len = strlen(data); 210 | 211 | while (len > 0) { 212 | int ret = write(fdo->fd, data, len); 213 | if (ret < 0) { 214 | if (errno == EINTR) 215 | continue; 216 | break; 217 | } 218 | data += ret; 219 | len -= ret; 220 | fdo->total += ret; 221 | } 222 | } 223 | 224 | static Out* 225 | fd_out_init(FdOut *fdo, int fd) 226 | { 227 | fdo->out->opaque = fdo; 228 | fdo->out->send = fd_out_send; 229 | fdo->fd = fd; 230 | fdo->total = 0; 231 | 232 | return fdo->out; 233 | } 234 | 235 | static int 236 | fd_out_length(FdOut *fdo) 237 | { 238 | return fdo->total; 239 | } 240 | 241 | 242 | int 243 | format_fd(int fd, const char *format, ...) 244 | { 245 | FdOut fdo; 246 | Out* out; 247 | va_list args; 248 | 249 | out = fd_out_init(&fdo, fd); 250 | if (out == NULL) 251 | return 0; 252 | 253 | va_start(args, format); 254 | out_vformat(out, format, args); 255 | va_end(args); 256 | 257 | return fd_out_length(&fdo); 258 | } 259 | 260 | #else /* LINKER_DEBUG_TO_LOG */ 261 | 262 | /*** Log output 263 | ***/ 264 | 265 | /* We need our own version of __libc_android_log_vprint, otherwise 266 | * the log output is completely broken. Probably due to the fact 267 | * that the C library is not initialized yet. 268 | * 269 | * You can test that by setting CUSTOM_LOG_VPRINT to 0 270 | * 开启CUSTOM_LOG_VPRINT宏即使用自己的日志输出 271 | */ 272 | #define CUSTOM_LOG_VPRINT 0 273 | 274 | #if CUSTOM_LOG_VPRINT == 1 275 | 276 | #include 277 | #include 278 | #include 279 | 280 | /* prio 281 | * tag 标记 282 | * fmt 格式化 283 | * args 参数 284 | */ 285 | static int log_vprint(int prio, const char *tag, const char *fmt, va_list args) 286 | { 287 | char buf[1024]; 288 | int result; 289 | static int log_fd = -1; 290 | 291 | result = vformat_buffer(buf, sizeof buf, fmt, args); 292 | 293 | if (log_fd < 0) { 294 | #ifdef LOG_TO_STDOUT 295 | log_fd = fileno(stdout); 296 | #else 297 | log_fd = open("/dev/log/main", O_WRONLY); 298 | #endif 299 | if (log_fd < 0) 300 | return result; 301 | } 302 | 303 | { 304 | ssize_t ret; 305 | struct iovec vec[3]; 306 | 307 | /* 类型 */ 308 | vec[0].iov_base = (unsigned char *) &prio; 309 | vec[0].iov_len = 1; 310 | /* 标记 */ 311 | vec[1].iov_base = (void *) tag; 312 | vec[1].iov_len = strlen(tag) + 1; 313 | /* 内容 */ 314 | vec[2].iov_base = (void *) buf; 315 | vec[2].iov_len = strlen(buf) + 1; 316 | 317 | do { 318 | ret = writev(log_fd, vec, 3); 319 | } while ((ret < 0) && (errno == EINTR)); 320 | } 321 | return result; 322 | } 323 | 324 | #define __libc_android_log_vprint log_vprint 325 | 326 | #else /* !CUSTOM_LOG_VPRINT */ 327 | 328 | //extern "C" int __libc_android_log_vprint(int prio, const char* tag, const char* format, va_list ap); 329 | #define __libc_android_log_vprint my_log_vprint 330 | 331 | int my_log_vprint(int prio, const char* tag, const char* format, va_list ap) { 332 | int ret; 333 | char string_buf[2048] = {0}; 334 | 335 | (void) &prio; 336 | 337 | vsprintf(string_buf, format, ap); 338 | sprintf(string_buf, "%s %s\n", tag, string_buf); 339 | ret = printf(string_buf); 340 | return ret; 341 | } 342 | 343 | #endif /* !CUSTOM_LOG_VPRINT */ 344 | 345 | int 346 | format_log(int prio, const char *tag, const char *format, ...) 347 | { 348 | int ret; 349 | va_list args; 350 | va_start(args, format); 351 | ret = __libc_android_log_vprint(prio, tag, format, args); 352 | va_end(args); 353 | return ret; 354 | } 355 | 356 | #endif /* LINKER_DEBUG_TO_LOG */ 357 | 358 | #endif /* LINKER_DEBUG */ 359 | 360 | /*** formatted output implementation 361 | ***/ 362 | 363 | /* Parse a decimal string from 'format + *ppos', 364 | * return the value, and writes the new position past 365 | * the decimal string in '*ppos' on exit. 366 | * 367 | * NOTE: Does *not* handle a sign prefix. 368 | */ 369 | static unsigned 370 | parse_decimal(const char *format, int *ppos) 371 | { 372 | const char* p = format + *ppos; 373 | unsigned result = 0; 374 | 375 | for (;;) { 376 | int ch = *p; 377 | unsigned d = (unsigned)(ch - '0'); 378 | 379 | if (d >= 10U) 380 | break; 381 | 382 | result = result*10 + d; 383 | p++; 384 | } 385 | *ppos = p - format; 386 | return result; 387 | } 388 | 389 | /* write an octal/decimal/number into a bounded buffer. 390 | * assumes that bufsize > 0, and 'digits' is a string of 391 | * digits of at least 'base' values. 392 | */ 393 | static void 394 | format_number(char *buffer, size_t bufsize, uint64_t value, int base, const char *digits) 395 | { 396 | char *pos = buffer; 397 | char *end = buffer + bufsize - 1; 398 | 399 | /* generate digit string in reverse order */ 400 | while (value) { 401 | unsigned d = value % base; 402 | value /= base; 403 | if (pos < end) { 404 | *pos++ = digits[d]; 405 | } 406 | } 407 | 408 | /* special case for 0 */ 409 | if (pos == buffer) { 410 | if (pos < end) { 411 | *pos++ = '0'; 412 | } 413 | } 414 | pos[0] = '\0'; 415 | 416 | /* now reverse digit string in-place */ 417 | end = pos - 1; 418 | pos = buffer; 419 | while (pos < end) { 420 | int ch = pos[0]; 421 | pos[0] = end[0]; 422 | end[0] = (char) ch; 423 | pos++; 424 | end--; 425 | } 426 | } 427 | 428 | /* Write an integer (octal or decimal) into a buffer, assumes buffsize > 2 */ 429 | static void 430 | format_integer(char *buffer, size_t buffsize, uint64_t value, int base, int isSigned) 431 | { 432 | if (isSigned && (int64_t)value < 0) { 433 | buffer[0] = '-'; 434 | buffer += 1; 435 | buffsize -= 1; 436 | value = (uint64_t)(-(int64_t)value); 437 | } 438 | 439 | format_number(buffer, buffsize, value, base, "0123456789"); 440 | } 441 | 442 | /* Write an hexadecimal into a buffer, isCap is true for capital alphas. 443 | * Assumes bufsize > 2 */ 444 | static void 445 | format_hex(char *buffer, size_t buffsize, uint64_t value, int isCap) 446 | { 447 | const char *digits = isCap ? "0123456789ABCDEF" : "0123456789abcdef"; 448 | 449 | format_number(buffer, buffsize, value, 16, digits); 450 | } 451 | 452 | 453 | /* Perform formatted output to an output target 'o' */ 454 | static void 455 | out_vformat(Out *o, const char *format, va_list args) 456 | { 457 | int nn = 0; 458 | 459 | for (;;) { 460 | int mm; 461 | int padZero = 0; 462 | int padLeft = 0; 463 | char sign = '\0'; 464 | int width = -1; 465 | int prec = -1; 466 | size_t bytelen = sizeof(int); 467 | const char* str; 468 | int slen; 469 | char buffer[32]; /* temporary buffer used to format numbers */ 470 | 471 | char c; 472 | 473 | /* first, find all characters that are not 0 or '%' */ 474 | /* then send them to the output directly */ 475 | mm = nn; 476 | do { 477 | c = format[mm]; 478 | if (c == '\0' || c == '%') 479 | break; 480 | mm++; 481 | } while (1); 482 | 483 | if (mm > nn) { 484 | out_send(o, format+nn, mm-nn); 485 | nn = mm; 486 | } 487 | 488 | /* is this it ? then exit */ 489 | if (c == '\0') 490 | break; 491 | 492 | /* nope, we are at a '%' modifier */ 493 | nn++; // skip it 494 | 495 | /* parse flags */ 496 | for (;;) { 497 | c = format[nn++]; 498 | if (c == '\0') { /* single trailing '%' ? */ 499 | c = '%'; 500 | out_send(o, &c, 1); 501 | return; 502 | } 503 | else if (c == '0') { 504 | padZero = 1; 505 | continue; 506 | } 507 | else if (c == '-') { 508 | padLeft = 1; 509 | continue; 510 | } 511 | else if (c == ' ' || c == '+') { 512 | sign = c; 513 | continue; 514 | } 515 | break; 516 | } 517 | 518 | /* parse field width */ 519 | if ((c >= '0' && c <= '9')) { 520 | nn --; 521 | width = (int)parse_decimal(format, &nn); 522 | c = format[nn++]; 523 | } 524 | 525 | /* parse precision */ 526 | if (c == '.') { 527 | prec = (int)parse_decimal(format, &nn); 528 | c = format[nn++]; 529 | } 530 | 531 | /* length modifier */ 532 | switch (c) { 533 | case 'h': 534 | bytelen = sizeof(short); 535 | if (format[nn] == 'h') { 536 | bytelen = sizeof(char); 537 | nn += 1; 538 | } 539 | c = format[nn++]; 540 | break; 541 | case 'l': 542 | bytelen = sizeof(long); 543 | if (format[nn] == 'l') { 544 | bytelen = sizeof(long long); 545 | nn += 1; 546 | } 547 | c = format[nn++]; 548 | break; 549 | case 'z': 550 | bytelen = sizeof(size_t); 551 | c = format[nn++]; 552 | break; 553 | case 't': 554 | bytelen = sizeof(ptrdiff_t); 555 | c = format[nn++]; 556 | break; 557 | default: 558 | ; 559 | } 560 | 561 | /* conversion specifier */ 562 | if (c == 's') { 563 | /* string */ 564 | str = va_arg(args, const char*); 565 | } else if (c == 'c') { 566 | /* character */ 567 | /* NOTE: char is promoted to int when passed through the stack */ 568 | buffer[0] = (char) va_arg(args, int); 569 | buffer[1] = '\0'; 570 | str = buffer; 571 | } else if (c == 'p') { 572 | uint64_t value = (uintptr_t) va_arg(args, void*); 573 | buffer[0] = '0'; 574 | buffer[1] = 'x'; 575 | format_hex(buffer + 2, sizeof buffer-2, value, 0); 576 | str = buffer; 577 | } else { 578 | /* integers - first read value from stack */ 579 | uint64_t value; 580 | int isSigned = (c == 'd' || c == 'i' || c == 'o'); 581 | 582 | /* NOTE: int8_t and int16_t are promoted to int when passed 583 | * through the stack 584 | */ 585 | switch (bytelen) { 586 | case 1: value = (uint8_t) va_arg(args, int); break; 587 | case 2: value = (uint16_t) va_arg(args, int); break; 588 | case 4: value = va_arg(args, uint32_t); break; 589 | case 8: value = va_arg(args, uint64_t); break; 590 | default: return; /* should not happen */ 591 | } 592 | 593 | /* sign extension, if needed */ 594 | if (isSigned) { 595 | int shift = 64 - 8*bytelen; 596 | value = (uint64_t)(((int64_t)(value << shift)) >> shift); 597 | } 598 | 599 | /* format the number properly into our buffer */ 600 | switch (c) { 601 | case 'i': case 'd': 602 | format_integer(buffer, sizeof buffer, value, 10, isSigned); 603 | break; 604 | case 'o': 605 | format_integer(buffer, sizeof buffer, value, 8, isSigned); 606 | break; 607 | case 'x': case 'X': 608 | format_hex(buffer, sizeof buffer, value, (c == 'X')); 609 | break; 610 | default: 611 | buffer[0] = '\0'; 612 | } 613 | /* then point to it */ 614 | str = buffer; 615 | } 616 | 617 | /* if we are here, 'str' points to the content that must be 618 | * outputted. handle padding and alignment now */ 619 | 620 | slen = strlen(str); 621 | 622 | if (slen < width && !padLeft) { 623 | char padChar = padZero ? '0' : ' '; 624 | out_send_repeat(o, padChar, width - slen); 625 | } 626 | 627 | out_send(o, str, slen); 628 | 629 | if (slen < width && padLeft) { 630 | char padChar = padZero ? '0' : ' '; 631 | out_send_repeat(o, padChar, width - slen); 632 | } 633 | } 634 | } 635 | 636 | 637 | #ifdef UNIT_TESTS 638 | 639 | #include 640 | 641 | static int gFails = 0; 642 | 643 | #define MARGIN 40 644 | 645 | #define UTEST_CHECK(condition,message) \ 646 | printf("Checking %-*s: ", MARGIN, message); fflush(stdout); \ 647 | if (!(condition)) { \ 648 | printf("KO\n"); \ 649 | gFails += 1; \ 650 | } else { \ 651 | printf("ok\n"); \ 652 | } 653 | 654 | static void 655 | utest_BufOut(void) 656 | { 657 | char buffer[16]; 658 | BufOut bo[1]; 659 | Out* out; 660 | int ret; 661 | 662 | buffer[0] = '1'; 663 | out = buf_out_init(bo, buffer, sizeof buffer); 664 | UTEST_CHECK(buffer[0] == '\0', "buf_out_init clears initial byte"); 665 | out_send(out, "abc", 3); 666 | UTEST_CHECK(!memcmp(buffer, "abc", 4), "out_send() works with BufOut"); 667 | out_send_repeat(out, 'X', 4); 668 | UTEST_CHECK(!memcmp(buffer, "abcXXXX", 8), "out_send_repeat() works with BufOut"); 669 | buffer[sizeof buffer-1] = 'x'; 670 | out_send_repeat(out, 'Y', 2*sizeof(buffer)); 671 | UTEST_CHECK(buffer[sizeof buffer-1] == '\0', "overflows always zero-terminates"); 672 | 673 | out = buf_out_init(bo, buffer, sizeof buffer); 674 | out_send_repeat(out, 'X', 2*sizeof(buffer)); 675 | ret = buf_out_length(bo); 676 | UTEST_CHECK(ret == 2*sizeof(buffer), "correct size returned on overflow"); 677 | } 678 | 679 | static void 680 | utest_expect(const char* result, const char* format, ...) 681 | { 682 | va_list args; 683 | BufOut bo[1]; 684 | char buffer[256]; 685 | Out* out = buf_out_init(bo, buffer, sizeof buffer); 686 | 687 | printf("Checking %-*s: ", MARGIN, format); fflush(stdout); 688 | va_start(args, format); 689 | out_vformat(out, format, args); 690 | va_end(args); 691 | 692 | if (strcmp(result, buffer)) { 693 | printf("KO. got '%s' expecting '%s'\n", buffer, result); 694 | gFails += 1; 695 | } else { 696 | printf("ok. got '%s'\n", result); 697 | } 698 | } 699 | 700 | int main(void) 701 | { 702 | utest_BufOut(); 703 | utest_expect("", ""); 704 | utest_expect("a", "a"); 705 | utest_expect("01234", "01234", ""); 706 | utest_expect("01234", "%s", "01234"); 707 | utest_expect("aabbcc", "aa%scc", "bb"); 708 | utest_expect("a", "%c", 'a'); 709 | utest_expect("1234", "%d", 1234); 710 | utest_expect("-8123", "%d", -8123); 711 | utest_expect("16", "%hd", 0x7fff0010); 712 | utest_expect("16", "%hhd", 0x7fffff10); 713 | utest_expect("68719476736", "%lld", 0x1000000000LL); 714 | utest_expect("70000", "%ld", 70000); 715 | utest_expect("0xb0001234", "%p", (void*)0xb0001234); 716 | utest_expect("12ab", "%x", 0x12ab); 717 | utest_expect("12AB", "%X", 0x12ab); 718 | utest_expect("00123456", "%08x", 0x123456); 719 | utest_expect("01234", "0%d", 1234); 720 | utest_expect(" 1234", "%5d", 1234); 721 | utest_expect("01234", "%05d", 1234); 722 | utest_expect(" 1234", "%8d", 1234); 723 | utest_expect("1234 ", "%-8d", 1234); 724 | utest_expect("abcdef ", "%-11s", "abcdef"); 725 | utest_expect("something:1234", "%s:%d", "something", 1234); 726 | utest_expect("005:5:05", "%03d:%d:%02d", 5, 5, 5); 727 | utest_expect("5,0x0", "%d,%p", 5, NULL); 728 | utest_expect("68719476736,6,7,8", "%lld,%d,%d,%d", 0x1000000000LL, 6, 7, 8); 729 | return gFails != 0; 730 | } 731 | 732 | #endif /* UNIT_TESTS */ 733 | -------------------------------------------------------------------------------- /src/linker_format.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 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 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, 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 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _LINKER_FORMAT_H 29 | #define _LINKER_FORMAT_H 30 | 31 | #include 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /* Formatting routines for the dynamic linker's debug traces */ 39 | /* We want to avoid dragging the whole C library fprintf() */ 40 | /* implementation into the dynamic linker since this creates */ 41 | /* issues (it uses malloc()/free()) and increases code size */ 42 | 43 | int format_buffer(char *buffer, size_t bufsize, const char *format, ...); 44 | 45 | #ifdef __cplusplus 46 | }; 47 | #endif 48 | 49 | #endif /* _LINKER_FORMAT_H */ 50 | -------------------------------------------------------------------------------- /src/linker_phdr.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Android Open Source Project 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 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, 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 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | 32 | #include "linker_phdr.h" 33 | 34 | /** 35 | TECHNICAL NOTE ON ELF LOADING. 36 | 37 | An ELF file's program header table contains one or more PT_LOAD 38 | segments, which corresponds to portions of the file that need to 39 | be mapped into the process' address space. 40 | 41 | Each loadable segment has the following important properties: 42 | 43 | p_offset -> segment file offset 44 | p_filesz -> segment file size 45 | p_memsz -> segment memory size (always >= p_filesz) 46 | p_vaddr -> segment's virtual address 47 | p_flags -> segment flags (e.g. readable, writable, executable) 48 | 49 | We will ignore the p_paddr and p_align fields of Elf32_Phdr for now. 50 | 51 | The loadable segments can be seen as a list of [p_vaddr ... p_vaddr+p_memsz) 52 | ranges of virtual addresses. A few rules apply: 53 | 54 | - the virtual address ranges should not overlap. 55 | 56 | - if a segment's p_filesz is smaller than its p_memsz, the extra bytes 57 | between them should always be initialized to 0. 58 | 59 | - ranges do not necessarily start or end at page boundaries. Two distinct 60 | segments can have their start and end on the same page. In this case, the 61 | page inherits the mapping flags of the latter segment. 62 | 63 | Finally, the real load addrs of each segment is not p_vaddr. Instead the 64 | loader decides where to load the first segment, then will load all others 65 | relative to the first one to respect the initial range layout. 66 | 67 | For example, consider the following list: 68 | 69 | [ offset:0, filesz:0x4000, memsz:0x4000, vaddr:0x30000 ], 70 | [ offset:0x4000, filesz:0x2000, memsz:0x8000, vaddr:0x40000 ], 71 | 72 | This corresponds to two segments that cover these virtual address ranges: 73 | 74 | 0x30000...0x34000 75 | 0x40000...0x48000 76 | 77 | If the loader decides to load the first segment at address 0xa0000000 78 | then the segments' load address ranges will be: 79 | 80 | 0xa0030000...0xa0034000 81 | 0xa0040000...0xa0048000 82 | 83 | In other words, all segments must be loaded at an address that has the same 84 | constant offset from their p_vaddr value. This offset is computed as the 85 | difference between the first segment's load address, and its p_vaddr value. 86 | 87 | However, in practice, segments do _not_ start at page boundaries. Since we 88 | can only memory-map at page boundaries, this means that the bias is 89 | computed as: 90 | 91 | load_bias = phdr0_load_address - PAGE_START(phdr0->p_vaddr) 92 | 93 | (NOTE: The value must be used as a 32-bit unsigned integer, to deal with 94 | possible wrap around UINT32_MAX for possible large p_vaddr values). 95 | 96 | And that the phdr0_load_address must start at a page boundary, with 97 | the segment's real content starting at: 98 | 99 | phdr0_load_address + PAGE_OFFSET(phdr0->p_vaddr) 100 | 101 | Note that ELF requires the following condition to make the mmap()-ing work: 102 | 103 | PAGE_OFFSET(phdr0->p_vaddr) == PAGE_OFFSET(phdr0->p_offset) 104 | 105 | The load_bias must be added to any p_vaddr value read from the ELF file to 106 | determine the corresponding memory address. 107 | 108 | **/ 109 | 110 | #define MAYBE_MAP_FLAG(x,from,to) (((x) & (from)) ? (to) : 0) 111 | #define PFLAGS_TO_PROT(x) (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \ 112 | MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \ 113 | MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE)) 114 | 115 | /* 读取程序段头表从一个ELF文件到有个只读的私有匿名mmap块 116 | * 117 | * Input: 118 | * fd -> file descriptor 119 | * phdr_offset -> file offset of phdr table 120 | * phdr_num -> number of entries in the table. 121 | * 122 | * Output: 123 | * phdr_mmap -> address of mmap block in memory. 124 | * phdr_memsize -> size of mmap block in memory. 125 | * phdr_table -> address of first entry in memory. 126 | * 127 | * Return: 128 | * -1 on error, or 0 on success. 129 | */ 130 | int phdr_table_load(int fd, 131 | Elf32_Addr phdr_offset, 132 | Elf32_Half phdr_num, 133 | void** phdr_mmap, 134 | Elf32_Addr* phdr_size, 135 | const Elf32_Phdr** phdr_table) 136 | { 137 | Elf32_Addr page_min, page_max, page_offset; 138 | void* mmap_result; 139 | 140 | /* Just like the kernel, we only accept program header tables that 141 | * are smaller than 64KB. */ 142 | if (phdr_num < 1 || phdr_num > 65536/sizeof(Elf32_Phdr)) { 143 | errno = EINVAL; 144 | return -1; 145 | } 146 | 147 | page_min = PAGE_START(phdr_offset); 148 | page_max = PAGE_END(phdr_offset + phdr_num*sizeof(Elf32_Phdr)); 149 | page_offset = PAGE_OFFSET(phdr_offset); 150 | 151 | mmap_result = mmap(NULL, 152 | page_max - page_min, 153 | PROT_READ, 154 | MAP_PRIVATE, 155 | fd, 156 | page_min); 157 | 158 | if (mmap_result == MAP_FAILED) { 159 | return -1; 160 | } 161 | 162 | *phdr_mmap = mmap_result; 163 | *phdr_size = page_max - page_min; 164 | *phdr_table = reinterpret_cast((unsigned)mmap_result + page_offset); 165 | 166 | return 0; 167 | } 168 | 169 | void phdr_table_unload(void* phdr_mmap, Elf32_Addr phdr_memsize) 170 | { 171 | munmap(phdr_mmap, phdr_memsize); 172 | } 173 | 174 | 175 | /* Compute the extent of all loadable segments in an ELF program header 176 | * table. This corresponds to the page-aligned size in bytes that needs to be 177 | * reserved in the process' address space 178 | * 179 | * This returns 0 if there are no loadable segments. 180 | */ 181 | /* 计算所有的可加载段的并且对齐后的内存大小 182 | * 返回0表示无可加载段 183 | * 从这里可以看出,可加载段可以不连续 184 | */ 185 | Elf32_Addr phdr_table_get_load_size(const Elf32_Phdr* phdr_table, 186 | size_t phdr_count) 187 | { 188 | Elf32_Addr min_vaddr = 0xFFFFFFFFU; 189 | Elf32_Addr max_vaddr = 0x00000000U; 190 | 191 | for (size_t i = 0; i < phdr_count; ++i) { 192 | const Elf32_Phdr* phdr = &phdr_table[i]; 193 | 194 | if (phdr->p_type != PT_LOAD) { 195 | continue; 196 | } 197 | 198 | if (phdr->p_vaddr < min_vaddr) { 199 | min_vaddr = phdr->p_vaddr; 200 | } 201 | 202 | if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) { 203 | max_vaddr = phdr->p_vaddr + phdr->p_memsz; 204 | } 205 | } 206 | 207 | if (min_vaddr > max_vaddr) { 208 | return 0; 209 | } 210 | 211 | min_vaddr = PAGE_START(min_vaddr); 212 | max_vaddr = PAGE_END(max_vaddr); 213 | 214 | return max_vaddr - min_vaddr; 215 | } 216 | 217 | /* Reserve a virtual address range big enough to hold all loadable 218 | * segments of a program header table. This is done by creating a 219 | * private anonymous mmap() with PROT_NONE. 220 | * 分配一个足够存储所有可加载段的内存空间。 221 | * 222 | * Input: 223 | * phdr_table -> program header table 224 | * phdr_count -> number of entries in the tables 225 | * Output: 226 | * load_start -> first page of reserved address space range 227 | * load_size -> size in bytes of reserved address space range 228 | * load_bias -> load bias, as described in technical note above. 229 | * 230 | * Return: 231 | * 0 on success, -1 otherwise. Error code in errno. 232 | */ 233 | int 234 | phdr_table_reserve_memory(const Elf32_Phdr* phdr_table, 235 | size_t phdr_count, 236 | void** load_start, 237 | Elf32_Addr* load_size, 238 | Elf32_Addr* load_bias) 239 | { 240 | Elf32_Addr size = phdr_table_get_load_size(phdr_table, phdr_count); 241 | if (size == 0) { 242 | errno = EINVAL; 243 | return -1; 244 | } 245 | 246 | /* 分配内存 */ 247 | int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS; 248 | void* start = mmap(NULL, size, PROT_NONE, mmap_flags, -1, 0); 249 | if (start == MAP_FAILED) { 250 | return -1; 251 | } 252 | 253 | *load_start = start; 254 | *load_size = size; 255 | *load_bias = 0; 256 | 257 | /* 遍历段表 */ 258 | for (size_t i = 0; i < phdr_count; ++i) { 259 | const Elf32_Phdr* phdr = &phdr_table[i]; 260 | if (phdr->p_type == PT_LOAD) { 261 | *load_bias = (Elf32_Addr)start - PAGE_START(phdr->p_vaddr); 262 | break; 263 | } 264 | } 265 | return 0; 266 | } 267 | 268 | /* Map all loadable segments in process' address space. 269 | * This assumes you already called phdr_table_reserve_memory to 270 | * reserve the address space range for the library. 271 | * 272 | * Input: 273 | * phdr_table -> program header table 274 | * phdr_count -> number of entries in the table 275 | * load_bias -> load offset. 276 | * fd -> input file descriptor. 277 | * 278 | * Return: 279 | * 0 on success, -1 otherwise. Error code in errno. 280 | */ 281 | int 282 | phdr_table_load_segments(const Elf32_Phdr* phdr_table, 283 | int phdr_count, 284 | Elf32_Addr load_bias, 285 | int fd) 286 | { 287 | int nn; 288 | 289 | /* 遍历程序段头 */ 290 | for (nn = 0; nn < phdr_count; nn++) { 291 | const Elf32_Phdr* phdr = &phdr_table[nn]; 292 | void* seg_addr; 293 | 294 | if (phdr->p_type != PT_LOAD) 295 | continue; 296 | 297 | /* 加载内存 */ 298 | Elf32_Addr seg_start = phdr->p_vaddr + load_bias; 299 | Elf32_Addr seg_end = seg_start + phdr->p_memsz; 300 | 301 | Elf32_Addr seg_page_start = PAGE_START(seg_start); 302 | Elf32_Addr seg_page_end = PAGE_END(seg_end); 303 | 304 | Elf32_Addr seg_file_end = seg_start + phdr->p_filesz; 305 | 306 | /* File offsets */ 307 | Elf32_Addr file_start = phdr->p_offset; 308 | Elf32_Addr file_end = file_start + phdr->p_filesz; 309 | 310 | Elf32_Addr file_page_start = PAGE_START(file_start); 311 | Elf32_Addr file_page_end UNUSED = PAGE_END(file_end); 312 | 313 | seg_addr = mmap((void*)seg_page_start, 314 | file_end - file_page_start, 315 | PFLAGS_TO_PROT(phdr->p_flags), 316 | MAP_FIXED|MAP_PRIVATE, 317 | fd, 318 | file_page_start); 319 | 320 | if (seg_addr == MAP_FAILED) { 321 | return -1; 322 | } 323 | 324 | /* if the segment is writable, and does not end on a page boundary, 325 | * zero-fill it until the page limit. */ 326 | if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) { 327 | memset((void*)seg_file_end, 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end)); 328 | } 329 | 330 | seg_file_end = PAGE_END(seg_file_end); 331 | 332 | /* seg_file_end is now the first page address after the file 333 | * content. If seg_end is larger, we need to zero anything 334 | * between them. This is done by using a private anonymous 335 | * map for all extra pages. 336 | */ 337 | if (seg_page_end > seg_file_end) { 338 | void* zeromap = mmap((void*)seg_file_end, 339 | seg_page_end - seg_file_end, 340 | PFLAGS_TO_PROT(phdr->p_flags), 341 | MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 342 | -1, 343 | 0); 344 | if (zeromap == MAP_FAILED) { 345 | return -1; 346 | } 347 | } 348 | } 349 | return 0; 350 | } 351 | 352 | /* Used internally. Used to set the protection bits of all loaded segments 353 | * with optional extra flags (i.e. really PROT_WRITE). Used by 354 | * phdr_table_protect_segments and phdr_table_unprotect_segments. 355 | * 修改所有加载段为可写 356 | */ 357 | static int 358 | _phdr_table_set_load_prot(const Elf32_Phdr* phdr_table, 359 | int phdr_count, 360 | Elf32_Addr load_bias, 361 | int extra_prot_flags) 362 | { 363 | const Elf32_Phdr* phdr = phdr_table; 364 | const Elf32_Phdr* phdr_limit = phdr + phdr_count; 365 | 366 | for (; phdr < phdr_limit; phdr++) { 367 | if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) 368 | continue; 369 | 370 | Elf32_Addr seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; 371 | Elf32_Addr seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; 372 | 373 | int ret = mprotect((void*)seg_page_start, 374 | seg_page_end - seg_page_start, 375 | PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags); 376 | if (ret < 0) { 377 | return -1; 378 | } 379 | } 380 | return 0; 381 | } 382 | 383 | /* Restore the original protection modes for all loadable segments. 384 | * You should only call this after phdr_table_unprotect_segments and 385 | * applying all relocations. 386 | * 387 | * Input: 388 | * phdr_table -> program header table 389 | * phdr_count -> number of entries in tables 390 | * load_bias -> load bias 391 | * Return: 392 | * 0 on error, -1 on failure (error code in errno). 393 | */ 394 | int 395 | phdr_table_protect_segments(const Elf32_Phdr* phdr_table, 396 | int phdr_count, 397 | Elf32_Addr load_bias) 398 | { 399 | return _phdr_table_set_load_prot(phdr_table, phdr_count, 400 | load_bias, 0); 401 | } 402 | 403 | /* Change the protection of all loaded segments in memory to writable. 404 | * This is useful before performing relocations. Once completed, you 405 | * will have to call phdr_table_protect_segments to restore the original 406 | * protection flags on all segments. 407 | * 408 | * 改变所有的在内存中的可加载段为可写.一旦完成重定位,则修改回元属性 409 | * Note that some writable segments can also have their content turned 410 | * to read-only by calling phdr_table_protect_gnu_relro. This is no 411 | * performed here. 412 | * 413 | * Input: 414 | * phdr_table -> program header table 415 | * phdr_count -> number of entries in tables 416 | * load_bias -> load bias 417 | * Return: 418 | * 0 on error, -1 on failure (error code in errno). 419 | */ 420 | int 421 | phdr_table_unprotect_segments(const Elf32_Phdr* phdr_table, 422 | int phdr_count, 423 | Elf32_Addr load_bias) 424 | { 425 | return _phdr_table_set_load_prot(phdr_table, phdr_count, 426 | load_bias, PROT_WRITE); 427 | } 428 | 429 | /* Used internally by phdr_table_protect_gnu_relro and 430 | * phdr_table_unprotect_gnu_relro. 431 | */ 432 | static int 433 | _phdr_table_set_gnu_relro_prot(const Elf32_Phdr* phdr_table, 434 | int phdr_count, 435 | Elf32_Addr load_bias, 436 | int prot_flags) 437 | { 438 | const Elf32_Phdr* phdr = phdr_table; 439 | const Elf32_Phdr* phdr_limit = phdr + phdr_count; 440 | 441 | #define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ 442 | 443 | for (phdr = phdr_table; phdr < phdr_limit; phdr++) { 444 | if (phdr->p_type != PT_GNU_RELRO) 445 | continue; 446 | 447 | /* Tricky: what happens when the relro segment does not start 448 | * or end at page boundaries?. We're going to be over-protective 449 | * here and put every page touched by the segment as read-only. 450 | * 451 | * This seems to match Ian Lance Taylor's description of the 452 | * feature at http://www.airs.com/blog/archives/189. 453 | * 454 | * Extract: 455 | * Note that the current dynamic linker code will only work 456 | * correctly if the PT_GNU_RELRO segment starts on a page 457 | * boundary. This is because the dynamic linker rounds the 458 | * p_vaddr field down to the previous page boundary. If 459 | * there is anything on the page which should not be read-only, 460 | * the program is likely to fail at runtime. So in effect the 461 | * linker must only emit a PT_GNU_RELRO segment if it ensures 462 | * that it starts on a page boundary. 463 | */ 464 | Elf32_Addr seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; 465 | Elf32_Addr seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; 466 | 467 | int ret = mprotect((void*)seg_page_start, 468 | seg_page_end - seg_page_start, 469 | prot_flags); 470 | if (ret < 0) { 471 | return -1; 472 | } 473 | } 474 | return 0; 475 | } 476 | 477 | /* Apply GNU relro protection if specified by the program header. This will 478 | * turn some of the pages of a writable PT_LOAD segment to read-only, as 479 | * specified by one or more PT_GNU_RELRO segments. This must be always 480 | * performed after relocations. 481 | * 482 | * The areas typically covered are .got and .data.rel.ro, these are 483 | * read-only from the program's POV, but contain absolute addresses 484 | * that need to be relocated before use. 485 | * 486 | * Input: 487 | * phdr_table -> program header table 488 | * phdr_count -> number of entries in tables 489 | * load_bias -> load bias 490 | * Return: 491 | * 0 on error, -1 on failure (error code in errno). 492 | */ 493 | int 494 | phdr_table_protect_gnu_relro(const Elf32_Phdr* phdr_table, 495 | int phdr_count, 496 | Elf32_Addr load_bias) 497 | { 498 | return _phdr_table_set_gnu_relro_prot(phdr_table, 499 | phdr_count, 500 | load_bias, 501 | PROT_READ); 502 | } 503 | 504 | #ifdef ANDROID_ARM_LINKER 505 | 506 | # ifndef PT_ARM_EXIDX 507 | # define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */ 508 | # endif 509 | 510 | /* 如果提供了.ARM.exidx节则返回它在内存中的地址与长度. 511 | * 512 | * 输入: 513 | * phdr_table -> 程序头表 514 | * phdr_count -> 程序头的数量 515 | * load_bias -> 可加载的间隙 516 | * 输出: 517 | * arm_exidx -> address of table in memory (NULL on failure). 518 | * arm_exidx_count -> number of items in table (0 on failure). 519 | * Return: 520 | * 0 on error, -1 on failure (_no_ error code in errno) 521 | */ 522 | int 523 | phdr_table_get_arm_exidx(const Elf32_Phdr* phdr_table, 524 | int phdr_count, 525 | Elf32_Addr load_bias, 526 | Elf32_Addr** arm_exidx, 527 | unsigned* arm_exidx_count) 528 | { 529 | const Elf32_Phdr* phdr = phdr_table; 530 | const Elf32_Phdr* phdr_limit = phdr + phdr_count; 531 | 532 | for (phdr = phdr_table; phdr < phdr_limit; phdr++) { 533 | if (phdr->p_type != PT_ARM_EXIDX) 534 | continue; 535 | 536 | *arm_exidx = (Elf32_Addr*)(load_bias + phdr->p_vaddr); 537 | *arm_exidx_count = (unsigned)(phdr->p_memsz / 8); 538 | return 0; 539 | } 540 | *arm_exidx = NULL; 541 | *arm_exidx_count = 0; 542 | return -1; 543 | } 544 | #endif /* ANDROID_ARM_LINKER */ 545 | 546 | /* 返回ELF文件的.dynamic节在内存中的地址与长度.如果丢失返回NULL 547 | * 548 | * 输入: 549 | * phdr_table -> 程序头 550 | * phdr_count -> 程序头数量 551 | * load_bias -> 加载基地址 552 | * 输出: 553 | * dynamic -> .dynamic表的内存地址 554 | * dynamic_count -> .dynamic表项数量 555 | * Return: 556 | * void 557 | */ 558 | void 559 | phdr_table_get_dynamic_section(const Elf32_Phdr* phdr_table, 560 | int phdr_count, 561 | Elf32_Addr load_bias, 562 | Elf32_Addr** dynamic, 563 | size_t* dynamic_count) 564 | { 565 | const Elf32_Phdr* phdr = phdr_table; 566 | const Elf32_Phdr* phdr_limit = phdr + phdr_count; 567 | 568 | for (phdr = phdr_table; phdr < phdr_limit; phdr++) { 569 | if (phdr->p_type != PT_DYNAMIC) { 570 | continue; 571 | } 572 | 573 | /* 动态信息段的获取 */ 574 | *dynamic = (Elf32_Addr*)(load_bias + phdr->p_vaddr); 575 | if (dynamic_count) { 576 | *dynamic_count = (unsigned)(phdr->p_memsz / 8); 577 | } 578 | return; 579 | } 580 | *dynamic = NULL; 581 | if (dynamic_count) { 582 | *dynamic_count = 0; 583 | } 584 | } 585 | 586 | /* Return the address of the program header table as it appears in the loaded 587 | * segments in memory. This is in contrast with the input 'phdr_table' which 588 | * is temporary and will be released before the library is relocated. 589 | * 590 | * Input: 591 | * phdr_table -> program header table 592 | * phdr_count -> number of entries in tables 593 | * load_bias -> load bias 594 | * Return: 595 | * Address of loaded program header table on success (it has 596 | * 'phdr_count' entries), or NULL on failure (no error code). 597 | */ 598 | const Elf32_Phdr* 599 | phdr_table_get_loaded_phdr(const Elf32_Phdr* phdr_table, 600 | int phdr_count, 601 | Elf32_Addr load_bias) 602 | { 603 | const Elf32_Phdr* phdr = phdr_table; 604 | const Elf32_Phdr* phdr_limit = phdr + phdr_count; 605 | Elf32_Addr loaded = 0; 606 | Elf32_Addr loaded_end; 607 | 608 | /* If there is a PT_PHDR, use it directly */ 609 | for (phdr = phdr_table; phdr < phdr_limit; phdr++) { 610 | if (phdr->p_type == PT_PHDR) { 611 | loaded = load_bias + phdr->p_vaddr; 612 | goto CHECK; 613 | } 614 | } 615 | 616 | /* Otherwise, check the first loadable segment. If its file offset 617 | * is 0, it starts with the ELF header, and we can trivially find the 618 | * loaded program header from it. */ 619 | for (phdr = phdr_table; phdr < phdr_limit; phdr++) { 620 | if (phdr->p_type == PT_LOAD) { 621 | if (phdr->p_offset == 0) { 622 | Elf32_Addr elf_addr = load_bias + phdr->p_vaddr; 623 | const Elf32_Ehdr* ehdr = (const Elf32_Ehdr*)(void*)elf_addr; 624 | Elf32_Addr offset = ehdr->e_phoff; 625 | loaded = (Elf32_Addr)ehdr + offset; 626 | goto CHECK; 627 | } 628 | break; 629 | } 630 | } 631 | 632 | /* We didn't find it, let the client know. He may be able to 633 | * keep a copy of the input phdr_table instead. */ 634 | return NULL; 635 | 636 | CHECK: 637 | /* Ensure that our program header is actually within a loadable 638 | * segment. This should help catch badly-formed ELF files that 639 | * would cause the linker to crash later when trying to access it. 640 | */ 641 | loaded_end = loaded + phdr_count*sizeof(Elf32_Phdr); 642 | 643 | for (phdr = phdr_table; phdr < phdr_limit; phdr++) { 644 | if (phdr->p_type != PT_LOAD) 645 | continue; 646 | Elf32_Addr seg_start = phdr->p_vaddr + load_bias; 647 | Elf32_Addr seg_end = phdr->p_filesz + seg_start; 648 | 649 | if (seg_start <= loaded && loaded_end <= seg_end) { 650 | return (const Elf32_Phdr*)loaded; 651 | } 652 | } 653 | return NULL; 654 | } 655 | -------------------------------------------------------------------------------- /src/linker_phdr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Android Open Source Project 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 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, 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 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef LINKER_PHDR_H 29 | #define LINKER_PHDR_H 30 | 31 | /* Declarations related to the ELF program header table and segments. 32 | * 33 | * The design goal is to provide an API that is as close as possible 34 | * to the ELF spec, and does not depend on linker-specific data 35 | * structures (e.g. the exact layout of struct soinfo). 36 | */ 37 | 38 | #include "linker.h" 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | /* See linker_phdr.c for all usage documentation */ 45 | 46 | int 47 | phdr_table_load(int fd, 48 | Elf32_Addr phdr_offset, 49 | Elf32_Half phdr_num, 50 | void** phdr_mmap, 51 | Elf32_Addr* phdr_size, 52 | const Elf32_Phdr** phdr_table); 53 | 54 | void 55 | phdr_table_unload(void* phdr_mmap, Elf32_Addr phdr_memsize); 56 | 57 | Elf32_Addr 58 | phdr_table_get_load_size(const Elf32_Phdr* phdr_table, 59 | size_t phdr_count); 60 | 61 | int 62 | phdr_table_reserve_memory(const Elf32_Phdr* phdr_table, 63 | size_t phdr_count, 64 | void** load_start, 65 | Elf32_Addr* load_size, 66 | Elf32_Addr* load_bias); 67 | 68 | int 69 | phdr_table_load_segments(const Elf32_Phdr* phdr_table, 70 | int phdr_count, 71 | Elf32_Addr load_bias, 72 | int fd); 73 | 74 | int 75 | phdr_table_protect_segments(const Elf32_Phdr* phdr_table, 76 | int phdr_count, 77 | Elf32_Addr load_bias); 78 | 79 | int 80 | phdr_table_unprotect_segments(const Elf32_Phdr* phdr_table, 81 | int phdr_count, 82 | Elf32_Addr load_bias); 83 | 84 | int 85 | phdr_table_protect_gnu_relro(const Elf32_Phdr* phdr_table, 86 | int phdr_count, 87 | Elf32_Addr load_bias); 88 | 89 | const Elf32_Phdr* 90 | phdr_table_get_loaded_phdr(const Elf32_Phdr* phdr_table, 91 | int phdr_count, 92 | Elf32_Addr load_bias); 93 | 94 | #ifdef ANDROID_ARM_LINKER 95 | int 96 | phdr_table_get_arm_exidx(const Elf32_Phdr* phdr_table, 97 | int phdr_count, 98 | Elf32_Addr load_bias, 99 | Elf32_Addr** arm_exidx, 100 | unsigned* arm_exidix_count); 101 | #endif 102 | 103 | void 104 | phdr_table_get_dynamic_section(const Elf32_Phdr* phdr_table, 105 | int phdr_count, 106 | Elf32_Addr load_bias, 107 | Elf32_Addr** dynamic, 108 | size_t* dynamic_count); 109 | 110 | #ifdef __cplusplus 111 | }; 112 | #endif 113 | 114 | #endif /* LINKER_PHDR_H */ 115 | -------------------------------------------------------------------------------- /src/options.cpp: -------------------------------------------------------------------------------- 1 | #include "options.h" 2 | #include 3 | #include 4 | #include 5 | //#define _GNU_SOURCE /* 为了支持getopt_long */ 6 | #include 7 | 8 | void usage() { 9 | printf("udog [options] file\n"); 10 | printf("http://www.nagapt.com\n"); 11 | show_version(); 12 | } 13 | 14 | void show_version() { 15 | printf("V%s\n", UDOG_VERSION_STRING); 16 | } 17 | 18 | void show_help() { 19 | printf("\t----------------------------------------\n"); 20 | printf("\t|==== Android Native Lib Cracker ==== |\n"); 21 | printf("\t----------------------------------------\n"); 22 | printf("udog [options] file\n"); 23 | printf("-d, --dump=file dump load so to file\n"); 24 | printf("--clear-entry clear DT_INIT value\n"); 25 | printf("-c, --check print code sign\n"); 26 | printf("--xcto=offset(hex) set xct offset\n"); 27 | printf("--xcts=size(hex) set xct size\n"); 28 | printf("-h, --help show help\n"); 29 | printf("-v, --version show version\n"); 30 | printf("--debug=level show debug information\n"); 31 | printf("http://www.nagapt.com\n"); 32 | show_version(); 33 | printf("\n"); 34 | } 35 | 36 | struct options_t* handle_arguments(int argc, char* argv[]) { 37 | static struct options_t opts; 38 | memset(&opts, 0, sizeof(opts)); 39 | opts.call_dt_init = true; 40 | opts.call_dt_init_array = true; 41 | opts.call_dt_finit = true; 42 | opts.call_dt_finit_array = true; 43 | opts.load_pre_libs = true; 44 | opts.load_needed_libs = true; 45 | 46 | int opt; 47 | int longidx; 48 | int dump = 0, help = 0, version = 0, 49 | debug = 0, check = 0, xcto = 0, 50 | xcts = 0, clear_entry = 0; 51 | 52 | if (argc == 1) { 53 | return NULL; 54 | } 55 | 56 | const char* short_opts = ":hvcd:"; 57 | struct option long_opts[] = { 58 | { "dump", 1, &dump, 1 }, 59 | { "help", 0, &help, 2 }, 60 | { "version", 0, &version, 3 }, 61 | { "debug", 1, &debug, 4 }, 62 | { "check", 0, &check, 5 }, 63 | { "xcto", 1, &xcto, 6 }, 64 | { "xcts", 1, &xcts, 7 }, 65 | { "clear-entry",0, &clear_entry, 8 }, 66 | { 0, 0, 0, 0 } 67 | }; 68 | 69 | while ((opt = getopt_long(argc, argv, short_opts, long_opts, &longidx)) != -1) { 70 | switch (opt) { 71 | case 0: 72 | if (dump == 1) { 73 | opts.dump = true; 74 | opts.not_relocal = false; 75 | opts.make_sectabs = true; 76 | strcpy(opts.dump_file, optarg); 77 | opts.load = true; 78 | dump = 0; 79 | } else if (help == 2) { 80 | opts.help = true; 81 | help = 0; 82 | } else if (version == 3) { 83 | opts.version = true; 84 | version = 0; 85 | } else if (debug == 4) { 86 | opts.debug = true; 87 | opts.debuglevel = atoi(optarg); 88 | debug = 0; 89 | } else if (check == 5) { 90 | opts.check = true; 91 | check = 0; 92 | } else if (xcto == 6) { 93 | opts.xct_offset = strtol(optarg, NULL, 16); 94 | xcto = 0; 95 | } else if (xcts == 7) { 96 | opts.xct_size = strtol(optarg, NULL, 16); 97 | xcts = 0; 98 | } else if (clear_entry == 8) { 99 | opts.clear_entry = true; 100 | clear_entry = 0; 101 | } else { 102 | //printf("unknow options: %c\n", optopt); 103 | return NULL; 104 | } 105 | break; 106 | case 'c': 107 | opts.check = true; 108 | break; 109 | case 'h': 110 | opts.help = true; 111 | break; 112 | case 'v': 113 | opts.version = true; 114 | break; 115 | case 'd': 116 | opts.dump = true; 117 | opts.not_relocal = false; 118 | opts.make_sectabs = true; 119 | strcpy(opts.dump_file, optarg); 120 | opts.load = true; 121 | break; 122 | case '?': 123 | //printf("unknow options: %c\n", optopt); 124 | return NULL; 125 | break; 126 | case ':': 127 | //printf("option need a option\n"); 128 | return NULL; 129 | break; 130 | }/* end switch */ 131 | }/* end while */ 132 | 133 | /* 无文件 */ 134 | if (optind == argc) { 135 | return NULL; 136 | } 137 | 138 | strcpy(opts.target_file, argv[optind]); 139 | 140 | return &opts; 141 | } 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /src/options.h: -------------------------------------------------------------------------------- 1 | #ifndef __OPTIONS_H__ 2 | #define __OPTIONS_H__ 3 | 4 | #define UNUSED __attribute__((unused)) 5 | #define UDOG_VERSION_STRING "1.0" 6 | 7 | struct options_t { 8 | bool call_dt_init; 9 | bool call_dt_init_array; 10 | bool call_dt_finit; 11 | bool call_dt_finit_array; 12 | bool load_pre_libs; 13 | bool load_needed_libs; 14 | 15 | bool load; 16 | bool not_relocal; /* 不进行重定位 */ 17 | bool make_sectabs; /* 制作节表 */ 18 | bool dump; 19 | bool help; 20 | bool version; 21 | bool debug; 22 | bool check; 23 | bool clear_entry; 24 | 25 | int debuglevel; 26 | unsigned xct_offset; 27 | unsigned xct_size; 28 | char dump_file[128]; 29 | char target_file[128]; 30 | }; 31 | 32 | struct options_t* handle_arguments(int argc, char* argv[]); 33 | void usage(); 34 | void show_help(); 35 | void show_version(); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/rt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 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 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, 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 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | /* 30 | * This function is an empty stub where GDB locates a breakpoint to get notified 31 | * about linker activity. It canʼt be inlined away, canʼt be hidden. 32 | */ 33 | #ifdef NOTIFY_GDB 34 | void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity(void) 35 | { 36 | } 37 | #endif 38 | 39 | -------------------------------------------------------------------------------- /src/tool: -------------------------------------------------------------------------------- 1 | # MAKEFILE for linux GCC 2 | # 3 | 4 | # The version 5 | VERSION=1.0 6 | 7 | PLATFORM := $(shell uname | sed -e 's/_.*//') 8 | 9 | # tools 10 | ifndef COPY 11 | COPY=cp 12 | endif 13 | 14 | ifndef RM 15 | RM=rm 16 | endif 17 | 18 | ifndef MAKE 19 | MAKE=make 20 | endif 21 | 22 | # NDK tools 23 | SYSROOT := $(NDK_HOME)/platforms/android-8/arch-arm/ 24 | ADDR2LINE := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line 25 | AR := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar 26 | AS := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-as 27 | CC := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=$(SYSROOT) 28 | CXX := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ --sysroot=$(SYSROOT) 29 | GDB := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb 30 | GDBTUI := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdbtui 31 | GPROF := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gprof 32 | LD := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld --sysroot=$(SYSROOT) 33 | NM := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-nm 34 | OBJCOPY := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-objcopy 35 | OBJDUMP := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-objdump 36 | RANLIB := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ranlib 37 | READELF := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-readelf 38 | RUN := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-run 39 | SIZE := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-size 40 | STRINGS := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strings 41 | STRIP := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip 42 | 43 | # 打包选项 44 | ARFLAGS := cr 45 | 46 | # 开启调试选项 47 | ifdef DEBUG 48 | CFLAGS += -g3 -O0 49 | CFLAGS += -DDEBUG 50 | endif 51 | 52 | # 是否使用地址无关代码 53 | ifdef PIC 54 | CFLAGS += -fpic 55 | endif 56 | 57 | # 是否要编译APP 58 | ifdef APP 59 | CFLAGS += -DAPP 60 | ifdef PIC 61 | CFLAGS += -fpie 62 | endif 63 | endif 64 | 65 | OBJECTS=hello1.o hello2.o 66 | SOURCES=hello1.c hello2.c 67 | HEADERS= 68 | 69 | # 这里有一个链接顺序的问题,必须首先链接.o文件以及.c文件x 70 | # 随后才可以 链接.a文件,否则将找不到一些符号的定义 71 | hello: $(OBJECTS) $(SOURCES) $(HEADERS) 72 | $(CC) $(CFLAGS) $(OBJECTS) -o $@ 73 | 74 | libhello.a: $(OBJECTS) $(SOURCES) $(HEADERS) 75 | $(AR) $(ARFLAGS) $@ $(OBJECTS) 76 | $(RANLIB) $@ 77 | 78 | libhello.so: $(OBJECTS) $(SOURCES) $(HEADERS) 79 | $(CC) -Wl,-init=my_init -shared $(OBJECTS) $(LIBS) -o $@ 80 | 81 | hello1.o: hello1.c 82 | $(CC) $(CFLAGS) -c $< -o $@ 83 | 84 | hello2.o: hello2.c 85 | $(CC) $(CFLAGS) -c $< -o $@ 86 | 87 | objdump: $(OBJDUMP) 88 | $(OBJDUMP) $(CMD) 89 | 90 | objcopy: $(OBJCOPY) 91 | $(OBJCOPY) $(CMD) 92 | 93 | readelf: $(READELF) 94 | $(READELF) $(CMD) 95 | 96 | nm: $(NM) 97 | $(NM) $(CMD) 98 | 99 | clean_local: 100 | -$(RM) -f *.o 101 | -$(RM) -f *.a 102 | -$(RM) -f hello 103 | 104 | clean: 105 | -$(RM) -f `find . -type f | grep "[.]o" | xargs` 106 | -$(RM) -f `find . -type f | grep "[.]a" | xargs` -------------------------------------------------------------------------------- /src/xdlfcn.h: -------------------------------------------------------------------------------- 1 | #ifndef __XDLFCN_H__ 2 | #define __XDLFCN_H__ 3 | 4 | #include 5 | 6 | //#ifdef __USE_GNU 7 | /* If the first argument of `dlsym' or `dlvsym' is set to RTLD_NEXT 8 | the run-time address of the symbol called NAME in the next shared 9 | object is returned. The "next" relation is defined by the order 10 | the shared objects were loaded. */ 11 | # define RTLD_NEXT ((void *) -1l) 12 | 13 | /* If the first argument to `dlsym' or `dlvsym' is set to RTLD_DEFAULT 14 | the run-time address of the symbol called NAME in the global scope 15 | is returned. */ 16 | # define RTLD_DEFAULT ((void *) 0) 17 | 18 | 19 | /* Type for namespace indeces. */ 20 | typedef long int Lmid_t; 21 | 22 | /* Special namespace ID values. */ 23 | # define LM_ID_BASE 0 /* Initial namespace. */ 24 | # define LM_ID_NEWLM -1 /* For dlmopen: request new namespace. */ 25 | //#endif 26 | 27 | /* These are the possible values for the FLAGS argument to `dladdr1'. 28 | This indicates what extra information is stored at *EXTRA_INFO. 29 | It may also be zero, in which case the EXTRA_INFO argument is not used. */ 30 | enum 31 | { 32 | /* Matching symbol table entry (const ElfNN_Sym *). */ 33 | RTLD_DL_SYMENT = 1, 34 | 35 | /* The object containing the address (struct link_map *). */ 36 | RTLD_DL_LINKMAP = 2 37 | }; 38 | 39 | /* These are the possible values for the REQUEST argument to `dlinfo'. */ 40 | enum 41 | { 42 | /* Treat ARG as `lmid_t *'; store namespace ID for HANDLE there. */ 43 | RTLD_DI_LMID = 1, 44 | 45 | /* Treat ARG as `struct link_map **'; 46 | store the `struct link_map *' for HANDLE there. */ 47 | RTLD_DI_LINKMAP = 2, 48 | 49 | RTLD_DI_CONFIGADDR = 3, /* Unsupported, defined by Solaris. */ 50 | 51 | /* Treat ARG as `Dl_serinfo *' (see below), and fill in to describe the 52 | directories that will be searched for dependencies of this object. 53 | RTLD_DI_SERINFOSIZE fills in just the `dls_cnt' and `dls_size' 54 | entries to indicate the size of the buffer that must be passed to 55 | RTLD_DI_SERINFO to fill in the full information. */ 56 | RTLD_DI_SERINFO = 4, 57 | RTLD_DI_SERINFOSIZE = 5, 58 | 59 | /* Treat ARG as `char *', and store there the directory name used to 60 | expand $ORIGIN in this shared object's dependency file names. */ 61 | RTLD_DI_ORIGIN = 6, 62 | 63 | RTLD_DI_PROFILENAME = 7, /* Unsupported, defined by Solaris. */ 64 | RTLD_DI_PROFILEOUT = 8, /* Unsupported, defined by Solaris. */ 65 | 66 | /* Treat ARG as `size_t *', and store there the TLS module ID 67 | of this object's PT_TLS segment, as used in TLS relocations; 68 | store zero if this object does not define a PT_TLS segment. */ 69 | RTLD_DI_TLS_MODID = 9, 70 | 71 | /* Treat ARG as `void **', and store there a pointer to the calling 72 | thread's TLS block corresponding to this object's PT_TLS segment. 73 | Store a null pointer if this object does not define a PT_TLS 74 | segment, or if the calling thread has not allocated a block for it. */ 75 | RTLD_DI_TLS_DATA = 10, 76 | 77 | RTLD_DI_MAX = 10 78 | }; 79 | 80 | typedef struct 81 | { 82 | const char *dli_fname; /* File name of defining object. */ 83 | void *dli_fbase; /* Load address of that object. */ 84 | const char *dli_sname; /* Name of nearest symbol. */ 85 | void *dli_saddr; /* Exact value of nearest symbol. */ 86 | } Dl_info; 87 | 88 | typedef struct 89 | { 90 | char *dls_name; /* Name of library search path directory. */ 91 | unsigned int dls_flags; /* Indicates where this directory came from. */ 92 | } Dl_serpath; 93 | 94 | /* This is the structure that must be passed (by reference) to `dlinfo' for 95 | the RTLD_DI_SERINFO and RTLD_DI_SERINFOSIZE requests. */ 96 | typedef struct 97 | { 98 | size_t dls_size; /* Size in bytes of the whole buffer. */ 99 | unsigned int dls_cnt; /* Number of elements in `dls_serpath'. */ 100 | Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. */ 101 | } Dl_serinfo; 102 | 103 | void *dlopen(const char *filename, int flag); 104 | const char *dlerror(void); 105 | void *dlsym(void *handle, const char *symbol); 106 | int dladdr(const void *addr, Dl_info* info); 107 | int dlclose(void* handle); 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /src/xor.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devilogic/udog/a1672a932ef089bfd0320bce53297b4ed34e7319/src/xor.cpp -------------------------------------------------------------------------------- /src/xor.h: -------------------------------------------------------------------------------- 1 | #if !defined(__XOR_H__) 2 | #define __XOR_H__ 3 | 4 | unsigned PolyXorKey(unsigned dwKey); 5 | void XorArray(unsigned dwKey, unsigned char* pPoint, 6 | unsigned char* pOut, unsigned iLength); 7 | void XorCoder(unsigned char* pKey, unsigned char* pBuffer, unsigned iLength); 8 | void XorKey32Bits(unsigned dwKeyContext, unsigned char* pKey, 9 | unsigned iKeyLength); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | # MAKEFILE for linux GCC 2 | # 3 | 4 | # The version 5 | VERSION=1.0 6 | 7 | PLATFORM := $(shell uname | sed -e 's/_.*//') 8 | 9 | # tools 10 | ifndef COPY 11 | COPY=cp 12 | endif 13 | 14 | ifndef RM 15 | RM=rm 16 | endif 17 | 18 | ifndef MAKE 19 | MAKE=make 20 | endif 21 | 22 | # NDK tools 23 | SYSROOT := $(NDK_HOME)/platforms/android-8/arch-arm/ 24 | ADDR2LINE := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line 25 | AR := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar 26 | AS := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-as 27 | CC := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=$(SYSROOT) 28 | CXX := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ --sysroot=$(SYSROOT) 29 | GDB := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb 30 | GDBTUI := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdbtui 31 | GPROF := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gprof 32 | LD := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld --sysroot=$(SYSROOT) 33 | NM := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-nm 34 | OBJCOPY := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-objcopy 35 | OBJDUMP := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-objdump 36 | RANLIB := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ranlib 37 | READELF := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-readelf 38 | RUN := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-run 39 | SIZE := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-size 40 | STRINGS := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strings 41 | STRIP := $(NDK_HOME)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip 42 | 43 | # 打包选项 44 | ARFLAGS := cr 45 | 46 | # 开启调试选项 47 | ifdef DEBUG 48 | CFLAGS += -g3 -O0 49 | CFLAGS += -DDEBUG 50 | endif 51 | 52 | # 是否使用地址无关代码 53 | ifdef PIC 54 | CFLAGS += -fpic 55 | endif 56 | 57 | # 是否要编译APP 58 | ifdef APP 59 | CFLAGS += -DAPP 60 | ifdef PIC 61 | CFLAGS += -fpie 62 | endif 63 | endif 64 | 65 | OBJECTS=hello1.o hello2.o hello3.o 66 | SOURCES=hello1.c hello2.c hello3.c 67 | HEADERS= 68 | 69 | # 这里有一个链接顺序的问题,必须首先链接.o文件以及.c文件x 70 | # 随后才可以 链接.a文件,否则将找不到一些符号的定义 71 | hello: $(OBJECTS) $(SOURCES) $(HEADERS) 72 | $(CC) $(CFLAGS) $(OBJECTS) -o $@ 73 | 74 | libhello.a: $(OBJECTS) $(SOURCES) $(HEADERS) 75 | $(AR) $(ARFLAGS) $@ $(OBJECTS) 76 | $(RANLIB) $@ 77 | 78 | libhello.so: $(OBJECTS) $(SOURCES) $(HEADERS) 79 | $(CC) -shared -Wl,-init=my_init $(OBJECTS) $(LIBS) -o $@ 80 | # $(CC) -Wl,-init=my_init -shared $(OBJECTS) $(LIBS) -o $@ 81 | 82 | # libfuck.so: fuck.c 83 | # $(CC) -shared fuck.c $(LIBS) -o $@ 84 | 85 | hello1.o: hello1.c 86 | $(CC) $(CFLAGS) -c $< -o $@ 87 | 88 | hello2.o: hello2.c 89 | $(CC) $(CFLAGS) -c $< -o $@ 90 | 91 | hello3.o: hello3.c 92 | $(CC) $(CFLAGS) -c $< -o $@ 93 | 94 | objdump: $(OBJDUMP) 95 | $(OBJDUMP) $(CMD) 96 | 97 | objcopy: $(OBJCOPY) 98 | $(OBJCOPY) $(CMD) 99 | 100 | readelf: $(READELF) 101 | $(READELF) $(CMD) 102 | 103 | nm: $(NM) 104 | $(NM) $(CMD) 105 | 106 | clean_local: 107 | -$(RM) -f *.o 108 | -$(RM) -f *.a 109 | -$(RM) -f hello 110 | 111 | clean: 112 | -$(RM) -f `find . -type f | grep "[.]o" | xargs` 113 | -$(RM) -f `find . -type f | grep "[.]a" | xargs` 114 | -------------------------------------------------------------------------------- /test/hello1.c: -------------------------------------------------------------------------------- 1 | /* hello1.c */ 2 | #include 3 | 4 | int g_a = 1; 5 | int g_b = 2; 6 | int g_x; 7 | 8 | extern bar(); 9 | extern foo2(); 10 | 11 | #if !defined(APP) 12 | void foo(); 13 | #endif 14 | 15 | void my_init() { 16 | printf("hello world from my_init\r\n"); 17 | foo(); 18 | foo2(); 19 | } 20 | 21 | #if !defined(APP) 22 | extern int g_y; 23 | void foo() { 24 | #else 25 | int main() { 26 | #endif 27 | int a = 3; 28 | int b = 4; 29 | g_x = a + g_a; 30 | printf("foo:a = %d\nb = %d\ng_x=%d\n", a, b, g_x); 31 | return; 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/hello2.c: -------------------------------------------------------------------------------- 1 | /* hello2.c */ 2 | #include 3 | 4 | int g_y = 1; 5 | 6 | void bar() { 7 | g_y = 2; 8 | } 9 | 10 | void foo2() { 11 | bar(); 12 | printf("foo2:g_y = %d\n", g_y); 13 | } 14 | 15 | -------------------------------------------------------------------------------- /test/hello3.c: -------------------------------------------------------------------------------- 1 | /* hello3.c */ 2 | /* #include */ 3 | 4 | /* extern int g_ywb = 1210; */ 5 | 6 | /* extern void bar() { */ 7 | /* g_ywb &= 1993; */ 8 | /* } */ 9 | --------------------------------------------------------------------------------