使用ptrace向已运行进程中注入.so并执行相关函数

这个总结的很好,从前一个项目也用到这中技术
转自:http://blog.csdn.net/myarrow/article/details/9630377

1. 简介

使用ptrace向已运行进程中注入.so并执行相关函数,其中的“注入”二字的真正含义为:此.so被link到已运行进程(以下简称为:目标进程)空间中,从而.so中的函数在目标进程空间中有对应的地址,然后通过此地址便可在目标进程中进行调用。

到底是如何注入的呢?

本文实现方案为:在目标进程中,通过dlopen把需要注入的.so加载到目标进程的空间中。

2. 如何让目标进程执行dlopen加载.so?

显然,目标进程本来是没有实现通过dlopen来加载我们想注入的.so,为了实现此功能,我们需要目标进程执行一段我们实现的代码,此段代码的功能为通过dlopen来加载一个.so。

3. 【加载.so的实现代码】

加载需要注入的.so的实现代码如下所示:

[cpp] view plaincopy

  1. .global _dlopen_addr_s       @dlopen函数在目标进程中的地址     注:以下全局变化在C中可读写
  2. .global _dlopen_param1_s     @dlopen参数1<.so>在目标进程中的地址
  3. .global _dlopen_param2_s     @dlopen参数2在目标进程中的地址
  4. .global _dlsym_addr_s        @dlsym函数在目标进程中的地址
  5. .global _dlsym_param2_s      @dlsym参数2在目标进程中的地址,其实为函数名
  6. .global _dlclose_addr_s      @dlcose在目标进程中的地址
  7. .global _inject_start_s      @汇编代码段的起始地址
  8. .global _inject_end_s        @汇编代码段的结束地址
  9. .global _inject_function_param_s  @hook_init参数在目标进程中的地址
  10. .global _saved_cpsr_s        @保存CPSR,以便执行完hook_init之后恢复环境
  11. .global _saved_r0_pc_s       @保存r0-r15,以便执行完hook_init之后恢复环境
  12. .data
  13. _inject_start_s:
  14. @ debug loop
  15. 3:
  16. @sub r1, r1, #0
  17. @B 3b
  18. @ dlopen
  19. ldr r1, _dlopen_param2_s        @设置dlopen第二个参数, flag
  20. ldr r0, _dlopen_param1_s        @设置dlopen第一个参数 .so
  21. ldr r3, _dlopen_addr_s          @设置dlopen函数
  22. blx r3                          @执行dlopen函数,返回值位于r0中
  23. subs r4, r0, #0                 @把dlopen的返回值soinfo保存在r4中,以方便后面dlclose使用
  24. beq 2f
  25. @dlsym
  26. ldr r1, _dlsym_param2_s        @设置dlsym第二个参数,第一个参数已经在r0中了
  27. ldr r3, _dlsym_addr_s          @设置dlsym函数
  28. blx r3                         @执行dlsym函数,返回值位于r0中
  29. subs r3, r0, #0                @把返回值<hook_init在目标进程中的地址>保存在r3中
  30. beq 1f
  31. @call our function
  32. ldr r0, _inject_function_param_s  @设置hook_init第一个参数
  33. blx r3                            @执行hook_init
  34. subs r0, r0, #0
  35. beq 2f
  36. 1:
  37. @dlclose
  38. mov r0, r4                        @把dlopen的返回值设为dlcose的第一个参数
  39. ldr r3, _dlclose_addr_s           @设置dlclose函数
  40. blx r3                            @执行dlclose函数
  41. 2:
  42. @restore context
  43. ldr r1, _saved_cpsr_s             @恢复CPSR
  44. msr cpsr_cf, r1
  45. ldr sp, _saved_r0_pc_s            @恢复寄存器r0-r15
  46. ldmfd sp, {r0-pc}
  47. _dlopen_addr_s:                           @初始化_dlopen_addr_s
  48. .word 0x11111111
  49. _dlopen_param1_s:
  50. .word 0x11111111
  51. _dlopen_param2_s:
  52. .word 0x2                                 @RTLD_GLOBAL
  53. _dlsym_addr_s:
  54. .word 0x11111111
  55. _dlsym_param2_s:
  56. .word 0x11111111
  57. _dlclose_addr_s:
  58. .word 0x11111111
  59. _inject_function_param_s:
  60. .word 0x11111111
  61. _saved_cpsr_s:
  62. .word 0x11111111
  63. _saved_r0_pc_s:
  64. .word 0x11111111
  65. _inject_end_s:                     @代码结束地址
  66. .space 0x400, 0                    @代码段空间大小
  67. .end

4. 如何把【加载.so的实现代码】写入目标进程并启动执行?

为了把【加载.so的实现代码】写入目标进程,主要有以下两步操作:

1) 在目标进程中找到存放【加载.so的实现代码】的空间(通过mmap实现)

2) 把【加载.so的实现代码】写入目标进程指定的空间

3) 启动执行

4.1 在目标进程中找到存放【加载.so的实现代码】的空间

通过mmap来实现,其实现步骤如下:

1) 获取目标进程中mmap地址
   2) 把mmap参数据放入r0-r3,另外两个写入目标进程sp 
   3) pc设置为mmap地址,lr设置为0
   4) 把准备好的寄存器写入目标进程(PTRACE_SETREGS),并启动目标进程运行(PTRACE_CONT)
   5) 分配的内存首地址位于r0 (PTRACE_GETREGS)

4.2 为【加载.so的实现代码】中的全局变量赋值

1) 获取目标进程中dlopen地址并赋值给_dlopen_addr_s

2) 获取目标进程中dlsym地址并赋值给_dlsym_addr_s

3) 获取目标进程中dlclose地址并赋值给_dlclose_addr_s

4) 把需要加载的.so的路径放入 汇编代码中,并获取此路径在目标进程中的地址然后赋值给_dlopen_param1_s

5) 把需要加载的.so中的hook_init放入 汇编代码中,并获取此路径在目标进程中的地址然后赋值给_dlsym_param2_s

6) 把目标进程中的cpsr保存在_saved_cpsr_s中

7) 把目标进程中的r0-r15存入汇编代码中,并获取此变量在目标进程中的地址然后赋值给_saved_r0_pc_s

8) 通过ptrace( PTRACE_POKETEXT,...)把汇编代码写入目标进程中,起始地址由前面的mmap所分配

9) 把目标进程的pc设置为汇编代码的起始地址,然后调用ptrace(PTRACE_DETACH,...)以启动目标进程执行

5. 把汇编代码写入目标进程并执行的实现代码

5.1 主函数 writecode_to_targetproc

[cpp] view plaincopy

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <asm/ptrace.h>
  4. #include <asm/user.h>
  5. #include <asm/ptrace.h>
  6. #include <sys/wait.h>
  7. #include <sys/mman.h>
  8. #include <dlfcn.h>
  9. #include <dirent.h>
  10. #include <unistd.h>
  11. #include <string.h>
  12. #include <android/log.h>
  13. #include <sys/types.h>
  14. #include <sys/socket.h>
  15. #include <netinet/in.h>
  16. #include <sys/stat.h>
  17. #define MAX_PATH 0x100
  18. #define REMOTE_ADDR( addr, local_base, remote_base ) ( (uint32_t)(addr) + (uint32_t)(remote_base) - (uint32_t)(local_base) )
  19. /* write the assembler code into target proc,
  20. * and invoke it to execute
  21. */
  22. int writecode_to_targetproc(
  23. pid_t target_pid, // target process pid
  24. const char *library_path, // the path of .so that will be
  25. // upload to target process
  26. const char *function_name, // .so init fucntion e.g. hook_init
  27. void *param, // the parameters of init function
  28. size_t param_size ) // number of parameters
  29. {
  30. int ret = -1;
  31. void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr;
  32. void *local_handle, *remote_handle, *dlhandle;
  33. uint8_t *map_base;
  34. uint8_t *dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr;
  35. struct pt_regs regs, original_regs;
  36. // extern global variable in the assembler code
  37. extern uint32_t _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, \
  38. _dlsym_addr_s, _dlsym_param2_s, _dlclose_addr_s, \
  39. _inject_start_s, _inject_end_s, _inject_function_param_s, \
  40. _saved_cpsr_s, _saved_r0_pc_s;
  41. uint32_t code_length;
  42. long parameters[10];
  43. // make target_pid as its child process and stop
  44. if ( ptrace_attach( target_pid ) == -1 )
  45. return -1;
  46. // get the values of 18 registers from target_pid
  47. if ( ptrace_getregs( target_pid, ®s ) == -1 )
  48. goto exit;
  49. // save original registers
  50. memcpy( &original_regs, ®s, sizeof(regs) );
  51. // get mmap address from target_pid
  52. // the mmap is the address of mmap in the cur process
  53. mmap_addr = get_remote_addr( target_pid, "/system/lib/libc.so", (void *)mmap );
  54. // set mmap parameters
  55. parameters[0] = 0;  // addr
  56. parameters[1] = 0x4000; // size
  57. parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC;  // prot
  58. parameters[3] =  MAP_ANONYMOUS | MAP_PRIVATE; // flags
  59. parameters[4] = 0; //fd
  60. parameters[5] = 0; //offset
  61. // execute the mmap in target_pid
  62. if ( ptrace_call( target_pid, (uint32_t)mmap_addr, parameters, 6, ®s ) == -1 )
  63. goto exit;
  64. // get the return values of mmap <in r0>
  65. if ( ptrace_getregs( target_pid, ®s ) == -1 )
  66. goto exit;
  67. // get the start address for assembler code
  68. map_base = (uint8_t *)regs.ARM_r0;
  69. // get the address of dlopen, dlsym and dlclose in target process
  70. dlopen_addr = get_remote_addr( target_pid, "/system/bin/linker", (void *)dlopen );
  71. dlsym_addr = get_remote_addr( target_pid, "/system/bin/linker", (void *)dlsym );
  72. dlclose_addr = get_remote_addr( target_pid, "/system/bin/linker", (void *)dlclose );
  73. // set the start address for assembler code in target process
  74. remote_code_ptr = map_base + 0x3C00;
  75. // set the start address for assembler code in cur process
  76. local_code_ptr = (uint8_t *)&_inject_start_s;
  77. // set global variable of assembler code
  78. // and these address is in the target process
  79. _dlopen_addr_s = (uint32_t)dlopen_addr;
  80. _dlsym_addr_s = (uint32_t)dlsym_addr;
  81. _dlclose_addr_s = (uint32_t)dlclose_addr;
  82. code_length = (uint32_t)&_inject_end_s - (uint32_t)&_inject_start_s;
  83. dlopen_param1_ptr = local_code_ptr + code_length + 0x20;
  84. dlsym_param2_ptr = dlopen_param1_ptr + MAX_PATH;
  85. saved_r0_pc_ptr = dlsym_param2_ptr + MAX_PATH;
  86. inject_param_ptr = saved_r0_pc_ptr + MAX_PATH;
  87. // save library path to assembler code global variable
  88. strcpy( dlopen_param1_ptr, library_path );
  89. _dlopen_param1_s = REMOTE_ADDR( dlopen_param1_ptr, local_code_ptr, remote_code_ptr );
  90. // save function name to assembler code global variable
  91. strcpy( dlsym_param2_ptr, function_name );
  92. _dlsym_param2_s = REMOTE_ADDR( dlsym_param2_ptr, local_code_ptr, remote_code_ptr );
  93. // save cpsr to assembler code global variable
  94. _saved_cpsr_s = original_regs.ARM_cpsr;
  95. // save r0-r15 to assembler code global variable
  96. memcpy( saved_r0_pc_ptr, &(original_regs.ARM_r0), 16 * 4 ); // r0 ~ r15
  97. _saved_r0_pc_s = REMOTE_ADDR( saved_r0_pc_ptr, local_code_ptr, remote_code_ptr );
  98. // save function parameters to assembler code global variable
  99. memcpy( inject_param_ptr, param, param_size );
  100. _inject_function_param_s = REMOTE_ADDR( inject_param_ptr, local_code_ptr, remote_code_ptr );
  101. // write the assembler code into target process
  102. // now the values of global variable is in the target process space
  103. ptrace_writedata( target_pid, remote_code_ptr, local_code_ptr, 0x400 );
  104. memcpy( ®s, &original_regs, sizeof(regs) );
  105. // set sp and pc to the start address of assembler code
  106. regs.ARM_sp = (long)remote_code_ptr;
  107. regs.ARM_pc = (long)remote_code_ptr;
  108. // set registers for target process
  109. ptrace_setregs( target_pid, ®s );
  110. // make the target_pid is not a child process of cur process
  111. // and make target_pid continue to running
  112. ptrace_detach( target_pid );
  113. // now finish it successfully
  114. ret = 0;
  115. exit:
  116. return ret;
  117. }

5.2 attach目标进程ptrace_attach

[cpp] view plaincopy

  1. int ptrace_attach( pid_t pid )
  2. {
  3. // after PTRACE_ATTACH, the proc<pid> will stop
  4. if ( ptrace( PTRACE_ATTACH, pid, NULL, 0  ) < 0 )
  5. {
  6. perror( "ptrace_attach" );
  7. return -1;
  8. }
  9. // wait proc<pid> stop
  10. waitpid( pid, NULL, WUNTRACED );
  11. // after PTRACE_SYSCALL, the proc<pid> will continue,
  12. // but when exectue sys call function, proc<pid> will stop
  13. if ( ptrace( PTRACE_SYSCALL, pid, NULL, 0  ) < 0 )
  14. {
  15. perror( "ptrace_syscall" );
  16. return -1;
  17. }
  18. // wait proc<pid> stop
  19. waitpid( pid, NULL, WUNTRACED );
  20. return 0;
  21. }

5.3 获取目标进程寄存器值ptrace_getregs

[cpp] view plaincopy

  1. int ptrace_getregs( pid_t pid, struct pt_regs* regs )
  2. {
  3. if ( ptrace( PTRACE_GETREGS, pid, NULL, regs ) < 0 )
  4. {
  5. perror( "ptrace_getregs: Can not get register values" );
  6. return -1;
  7. }
  8. return 0;
  9. }

5.4 获取目标进程中指定模块中指定函数的地址get_remote_addr

[cpp] view plaincopy

  1. /* find the start address of module whose name is module_name
  2. * in the designated process
  3. */
  4. void* get_module_base( pid_t pid, const char* module_name )
  5. {
  6. FILE *fp;
  7. long addr = 0;
  8. char *pch;
  9. char filename[32];
  10. char line[1024];
  11. if ( pid < 0 )
  12. {
  13. /* self process */
  14. snprintf( filename, sizeof(filename), "/proc/self/maps", pid );
  15. }
  16. else
  17. {
  18. snprintf( filename, sizeof(filename), "/proc/%d/maps", pid );
  19. }
  20. fp = fopen( filename, "r" );
  21. if ( fp != NULL )
  22. {
  23. while ( fgets( line, sizeof(line), fp ) )
  24. {
  25. if ( strstr( line, module_name ) )
  26. {
  27. pch = strtok( line, "-" );
  28. addr = strtoul( pch, NULL, 16 );
  29. if ( addr == 0x8000 )
  30. addr = 0;
  31. break;
  32. }
  33. }
  34. fclose( fp ) ;
  35. }
  36. return (void *)addr;
  37. }
  38. void* get_remote_addr( pid_t target_pid, const char* module_name, void* local_addr )
  39. {
  40. void* local_handle, *remote_handle;
  41. local_handle = get_module_base( -1, module_name );
  42. remote_handle = get_module_base( target_pid, module_name );
  43. return (void *)( (uint32_t)local_addr + (uint32_t)remote_handle - (uint32_t)local_handle );
  44. }

5.5 在目标进程中执行指定函数ptrace_call

[cpp] view plaincopy

  1. int ptrace_call( pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct pt_regs* regs )
  2. {
  3. uint32_t i;
  4. // put the first 4 parameters into r0-r3
  5. for ( i = 0; i < num_params && i < 4; i ++ )
  6. {
  7. regs->uregs[i] = params[i];
  8. }
  9. // push remained params into stack
  10. if ( i < num_params )
  11. {
  12. regs->ARM_sp -= (num_params - i) * sizeof(long) ;
  13. ptrace_writedata( pid, (void *)regs->ARM_sp, (uint8_t *)¶ms[i], (num_params - i) * sizeof(long) );
  14. }
  15. // set the pc to func <e.g: mmap> that will be executed
  16. regs->ARM_pc = addr;
  17. if ( regs->ARM_pc & 1 )
  18. {
  19. /* thumb */
  20. regs->ARM_pc &= (~1u);
  21. regs->ARM_cpsr |= CPSR_T_MASK;
  22. }
  23. else
  24. {
  25. /* arm */
  26. regs->ARM_cpsr &= ~CPSR_T_MASK;
  27. }
  28. // when finish this func, pid will stop
  29. regs->ARM_lr = 0;
  30. // set the regsister and start to execute
  31. if ( ptrace_setregs( pid, regs ) == -1
  32. || ptrace_continue( pid ) == -1 )
  33. {
  34. return -1;
  35. }
  36. // wait pid finish work and stop
  37. waitpid( pid, NULL, WUNTRACED );
  38. return 0;
  39. }

5.6 把代码写入目标进程指定地址ptrace_writedata

[cpp] view plaincopy

  1. int ptrace_writedata( pid_t pid, uint8_t *dest, uint8_t *data, size_t size )
  2. {
  3. uint32_t i, j, remain;
  4. uint8_t *laddr;
  5. union u {
  6. long val;
  7. char chars[sizeof(long)];
  8. } d;
  9. j = size / 4;
  10. remain = size % 4;
  11. laddr = data;
  12. for ( i = 0; i < j; i ++ )
  13. {
  14. memcpy( d.chars, laddr, 4 );
  15. ptrace( PTRACE_POKETEXT, pid, dest, d.val );
  16. dest  += 4;
  17. laddr += 4;
  18. }
  19. if ( remain > 0 )
  20. {
  21. d.val = ptrace( PTRACE_PEEKTEXT, pid, dest, 0 );
  22. for ( i = 0; i < remain; i ++ )
  23. {
  24. d.chars[i] = *laddr ++;
  25. }
  26. ptrace( PTRACE_POKETEXT, pid, dest, d.val );
  27. }
  28. return 0;
  29. }

5.7 设置目标进程寄存器ptrace_setregs

[cpp] view plaincopy

  1. int ptrace_setregs( pid_t pid, struct pt_regs* regs )
  2. {
  3. if ( ptrace( PTRACE_SETREGS, pid, NULL, regs ) < 0 )
  4. {
  5. perror( "ptrace_setregs: Can not set register values" );
  6. return -1;
  7. }
  8. return 0;
  9. }

5.8 detach目标进程ptrace_detach

[cpp] view plaincopy

  1. int ptrace_detach( pid_t pid )
  2. {
  3. if ( ptrace( PTRACE_DETACH, pid, NULL, 0 ) < 0 )
  4. {
  5. perror( "ptrace_detach" );
  6. return -1;
  7. }
  8. return 0;
  9. }

6.  需要被加载的.so

需要被加载的.so例子程序如下,其目的是替换目标进程libapp.so中的strlen函数。其主要实现见hook_init。

[cpp] view plaincopy

  1. int g_isInit = 0;
  2. pthread_t g_hThread;
  3. __attribute__((visibility("default"))) void hook_init( char *args )
  4. {
  5. if( g_isInit == 1 )
  6. {
  7. printf("i am already in!");
  8. return;
  9. }
  10. void* soHandle = NULL;
  11. // the libapp.so is a .so of target process, and it call strcmp
  12. soHandle  = dlopen( "libapp.so", RTLD_GLOBAL );
  13. if( soHandle != NULL )
  14. {
  15. g_realstrcmp = NULL;
  16. replaceFunc( soHandle, "strcmp", my_strcmp, (void**)&g_realstrcmp );
  17. int ret = pthread_create( &g_hThread, NULL, my_thread, NULL );
  18. if( ret != 0 )
  19. {
  20. printf("create thread error:%d", ret );
  21. }
  22. g_isInit = 1;
  23. }
  24. }

6.1 替换函数replaceFunc

[cpp] view plaincopy

  1. // replace function of libapp.so
  2. // e.g: replace strcmp of libapp.so with my_strcmp
  3. void replaceFunc(void *handle,const char *name, void* pNewFun, void** pOldFun )
  4. {
  5. if(!handle)
  6. return;
  7. soinfo *si = (soinfo*)handle;
  8. Elf32_Sym *symtab = si->symtab;
  9. const char *strtab = si->strtab;
  10. Elf32_Rel *rel = si->plt_rel;
  11. unsigned count = si->plt_rel_count;
  12. unsigned idx;
  13. // these external functions that are called by libapp.so
  14. // is in the plt_rel
  15. for(idx=0; idx<count; idx++)
  16. {
  17. unsigned type = ELF32_R_TYPE(rel->r_info);
  18. unsigned sym = ELF32_R_SYM(rel->r_info);
  19. unsigned reloc = (unsigned)(rel->r_offset + si->base);
  20. char *sym_name = (char *)(strtab + symtab[sym].st_name);
  21. if(strcmp(sym_name, name)==0)
  22. {
  23. *pOldFun = (void *)*((unsigned*)reloc);
  24. *((unsigned*)reloc)= pNewFun;
  25. break;
  26. }
  27. rel++;
  28. }
  29. }

6.2 新函数及其它函数

[cpp] view plaincopy

  1. // global function variable, save the address of strcmp of libapp.so
  2. int (*g_realstrcmp)(const char *s1, const char *s2);
  3. // my strcmp function
  4. int my_strcmp(const char *s1, const char *s2)
  5. {
  6. if( g_realstrcmp != NULL )
  7. {
  8. int nRet = g_realstrcmp( s1, s2 );
  9. printf("***%s: s1=%s, s2=%s\n",__FUNCTION__, s1, s2 );
  10. return nRet;
  11. }
  12. return -1;
  13. }
  14. // create a thread
  15. void* my_thread( void* pVoid )
  16. {
  17. int sock;
  18. sock = socket(AF_INET, SOCK_DGRAM, 0);
  19. if( sock < -1 )
  20. {
  21. printf("create socket failed!\n");
  22. return 0;
  23. }
  24. struct sockaddr_in addr_serv;
  25. int len;
  26. memset(&addr_serv, 0, sizeof(struct sockaddr_in));
  27. addr_serv.sin_family = AF_INET;
  28. addr_serv.sin_port = htons(9999);
  29. addr_serv.sin_addr.s_addr = inet_addr("127.0.0.1");
  30. len = sizeof(addr_serv);
  31. int flags = fcntl( sock, F_GETFL, 0);
  32. fcntl( sock, F_SETFL, flags | O_NONBLOCK);
  33. int nPreState = -1;
  34. unsigned char data=0;
  35. while( 1 )
  36. {
  37. data++;
  38. sendto( sock, &data,  sizeof( data ), 0, (struct sockaddr *)&addr_serv, sizeof( addr_serv ) );
  39. usleep( 30000 );
  40. }
  41. }

使用ptrace向已运行进程中注入.so并执行相关函数

时间: 2024-08-06 15:55:34

使用ptrace向已运行进程中注入.so并执行相关函数的相关文章

使用ptrace向已运行进程中注入.so并执行相关函数(转)

1. 简介 使用ptrace向已运行进程中注入.so并执行相关函数,其中的“注入”二字的真正含义为:此.so被link到已运行进程(以下简称为:目标进程)空间中,从而.so中的函数在目标进程空间中有对应的地址,然后通过此地址便可在目标进程中进行调用. 到底是如何注入的呢? 本文实现方案为:在目标进程中,通过dlopen把需要注入的.so加载到目标进程的空间中. 2. 如何让目标进程执行dlopen加载.so? 显然,目标进程本来是没有实现通过dlopen来加载我们想注入的.so,为了实现此功能,

如何实现在线查看进程中的变量以及执行调试函数

本程序实现了查看进程中的全局变量,以及执行进程中的调试函数的功能. 程序运行后,init_symbol函数会创建一个线程,此线程从标准输入读取 用户输入的变量名或函数调用命令,然后输出相应的结果. 例如, 输入 my_var,即可查看变量my_var的信息. 输入 my_func(1, "good", 0x123) 即可使用输入的参数执行函数my_func 目前最大支持8个参数,且每个参数size必须等于sizeof(long) my_func函数的各个入参就是一个符合要求的例子. 输

2.添加键盘钩子。向进程中注入dll

学习笔记 1.首先要建立mfc的动态链接库.在def文件中放入要导出的函数名. 2.添加函数如下 //安装钩子 //HHOOK SetWindowsHookEx( // int idHook,//钩子的类型WH_KEYBOARD键盘钩子 // HOOKPROC lpfn,//钩子的回调函数,钩子类型不同回调函数不同 // HINSTANCE hwnd,//dll动态链接库的句柄 // DWORD dwthreadid//游戏主进程的id 是GetWindowThreadProcessId的返回值

将dll文件注入到其他进程中的一种新方法

http://www.45it.com/windowszh/201212/33946.htm http://www.hx95.cn/Article/OS/201212/65095.html 我们知道将动态连接库注入到其他进程中有很多种方法.最常见的方法是使用钩子函数(Hook),但是这种方法主要有两个缺点:第一如果某个进程没有加载User32.dll,那么Hook DLL将永远也不会被加载.第二Hook DLL加载的时机问题,只有在进程发出User32调用的时候, Hook DLL才有可能被加载

IIS网站不可用:同一 IIS 进程中运行两个不同的 ASP.NET 版本问题

出错现象: 在IIS中的网站刚部署的网站可以用,过一段时间就不能用了.然后出现网站不可用的提示. 查看系统日志: 发现在系统日志中有这么一条信息:"在同一 IIS 进程中不可能运行两个不同的 ASP.NET 版本.请使用 IIS 管理工具重新配置服务器以在一个单独的进程中运行应用程序." 解决方案: 因为在同一个IIS应用程序池中不能运行两个asp.net的版本.将不同asp.net版本的网站分配不同的应用程序池就好了

citrix 6.5运行在检测进程中使用HYDROCEN时出错

一:在部署思杰6.5铂金版本虚拟应用服务器时候,配置连接FARM使用域管理员账号密码及数据库SA账号连接数据都测试成功了顺利安装完成了:运行自检时候一直报错"在检测进程中使用HYDROCEN时出错" 二:解决办法: 开始-管理工具-数据源(ODBC)-文件DSN(路径为:C:\Program Files (x86)\Citrix\Independent Management Architecture的mf20文件) 1.域空管理员连接方式 C:\Users\Administrator.

在进程中运行新代码

摘要:本文主要讲述如何在进程中运行新代码,以及exec系列函数的基本使用方法. 在进程中运行新代码 用函数fork创建子进程后,如果希望在当前子进程中运行新的程序,可以调用exec函数执行另一个程序.当进程调用exec函数时,该进程用户空间资源(正文.数据.堆和栈)完全由新程序替代,新程序则从main函数开始执行.因为调用exec函数并没有创建新的进程,所以前后的进程ID并没有改变,也即内核信息基本不做修改. exec系列函数共有7函数可供使用,这些函数的区别在于:指示新程序的位置是使用路径还是

pgrep---以名称为依据从运行进程队列中查找进程

pgrep命令以名称为依据从运行进程队列中查找进程,并显示查找到的进程id.每一个进程ID以一个十进制数表示,通过一个分割字符串和下一个ID分开,默认的分割字符串是一个新行.对于每个属性选项,用户可以在命令行上指定一个以逗号分割的可能值的集合. 语法 pgrep(选项)(参数) 选项 -o:仅显示找到的最小(起始)进程号: -n:仅显示找到的最大(结束)进程号: -l:显示进程名称: -P:指定父进程号: -g:指定进程组: -t:指定开启进程的终端: -u:指定进程的有效用户ID. 参数 进程

在Linux中通过Top运行进程查找最高内存和CPU使用率

按内存使用情况查找前15个进程,在批处理模式下为“top” 使用top命令查看有关当前状态,系统使用情况的更详细信息:正常运行时间,负载平均值和进程总数. 分类:Linux命令操作系统 2016-07-27 00:00:00 类似于前面的技巧有关找出由RAM和CPU使用率最高的进程 ,还可以使用top命令来查看相同的信息. 也许有相比前一个这种方法的一个额外的优势:顶级的“头”,提供有关当前状态和使用该系统的额外信息:正常运行时间,平均负载和进程总数,仅举几例例子. 按顶部查找按内存使用的进程