【转】玩转ptrace(一)

在Android使用上ptrace的尝试(一) Ptrace功能强大,可以用于调试跟踪。跑了蒸米大神写的例子,学习一下。 实验1:获取system call的编号 要ptrace的目标程序target,用来一直循环输出 #include int count = 0; void sevenWeapons(int number){ char* str = "hello!"; printf("%s, %d\n",str,n 阅读详情

原文:http://blog.youkuaiyun.com/silentvoid/archive/2007/01/08/1477439.aspx

 

by Pradeep Padala

Created 2002-11-01 02:00

翻译 : Magic.D E-mail: adamgic@163.com

 

译者序:在开发Hust Online Judge的过程中,查阅了不少资料,关于调试器技术的资料在网上是很少,即便是UNIX编程巨著《UNIX环境高级编程》中,相关内容也不多,直到我在http://www.linuxjournal.com上找到这篇文章,如获至宝,特翻译之,作为鄙人翻译技术文档的第一次尝试,必定会有不少蹩脚之处,各位就将就一下吧,欢迎大力拍砖。


你想过怎么实现对系统调用的拦截吗?你尝试过通过改变系统调用的参数来愚弄你的系统 kernel 吗?你想过调试器是如何使运行中的进程暂停并且控制它吗?

你可能会开始考虑怎么使用复杂的 kernel 编程来达到目的,那么,你错了。实际上 Linux 提供了一种优雅的机制来完成这些: ptrace 系统函数。   ptrace 提供了一种使父进程得以监视和控制其它进程的方式,它还能够改变子进程中的寄存器和内核映像,因而可以实现断点调试和系统调用的跟踪。

使用 ptrace ,你可以在用户层拦截和修改系统调用 (sys call)

在这篇文章中,我们将学习如何拦截一个系统调用,然后修改它的参数。在本文的第二部分我们将学习更先进的技术:设置断点,插入代码到一个正在运行的程序中;我们将潜入到机器内部,偷窥和纂改进程的寄存器和数据段。

 

基本知识

操作系统提供了一种标准的服务来让程序员实现对底层硬件和服务的控制(比如文件系统),叫做系统调用 (system calls) 。当一个程序需要作系统调用的时候,它将相关参数放进系统调用相关的寄存器,然后调用软中断 0x80 ,这个中断就像一个让程序得以接触到内核模式的窗口,程序将参数和系统调用号交给内核,内核来完成系统调用的执行。

 

在 i386 体系中 ( 本文中所有的代码都是面向 i386 体系 ) ,系统调用号将放入 %eax, 它的参数则依次放入 %ebx, %ecx, %edx, %esi  和   %edi 。   比如,在以下的调用

 

        Write(2, “Hello”, 5)

 

的汇编形式大概是这样的

      

     movl    $4, %eax

     movl    $2, %ebx

     movl    $hello, %ecx

     movl    $5, %edx

    int    $0x80

 

这里的 $hello 指向的是标准字符串 ”Hello” 。

 

那么, ptrace 会在什么时候出现呢?在执行系统调用之前,内核会先检查当前进程是否处于被“跟踪” (traced) 的状态。如果是的话,内核暂停当前进程并将控制权交给跟踪进程,使跟踪进程得以察看或者修改被跟踪进程的寄存器。

 

让我们来看一个例子,演示这个跟踪程序的过程

 

#include  < sys / ptrace.h >
#include 
< sys / types.h >
#include 
< sys / wait.h >
#include 
< unistd.h >
#include 
< linux / user.h >     /*  For constants 
                                   ORIG_EAX etc 
*/

int  main()
{
   pid_t child;
    
long  orig_eax;
    child 
=  fork();
    
if (child  ==   0 )  {
        ptrace(PTRACE_TRACEME, 
0 , NULL, NULL);
        execl(
" /bin/ls " ,  " ls " , NULL);
    }

    
else   {
        wait(NULL);
        orig_eax 
=  ptrace(PTRACE_PEEKUSER, 
                          child, 
4   *  ORIG_EAX, 
                          NULL);
        printf(
" The child made a  "
               
" system call %ld  " , orig_eax);
        ptrace(PTRACE_CONT, child, NULL, NULL);
    }

    
return   0 ;
}

运行这个程序,将会在输出 ls 命令的结果的同时,输出 :

 

The child made a system call 11

 

说明: 11 是 execve 的系统调用号,这是该程序调用的第一个系统调用。

想知道系统调用号的详细内容,察看   /usr/include/asm/unistd.h 。

 

在以上的示例中,父进程 fork 出了一个子进程,然后跟踪它。在调用 exec 函数之前,子进程用 PTRACE_TRACEME 作为第一个参数调用了 ptrace 函数,它告诉内核:让别人跟踪我吧!然后,在子进程调用了 execve() 之后,它将控制权交还给父进程。当时父进程正使用 wait() 函数来等待来自内核的通知,现在它得到了通知,于是它可以开始察看子进程都作了些什么,比如看看寄存器的值之类。

 

出现系统调用之后,内核会将 eax 中的值(此时存的是系统调用号)保存起来,我们可以使用 PTRACE_PEEKUSER 作为 ptrace 的第一个参数来读到这个值。

我们察看完系统调用的信息后,可以使用 PTRACE_CONT 作为 ptrace 的第一个参数,调用 ptrace 使子进程继续系统调用的过程。

 

ptrace 函数的参数

 

Ptrace 有四个参数

long ptrace(enum __ptrace_request request,


            

pid_t pid,


            

void *addr,


            

void *data);


 

第一个参数决定了 ptrace 的行为与其它参数的使用方法,可取的值有 :

PTRACE_ME

PTRACE_PEEKTEXT

PTRACE_PEEKDATA

PTRACE_PEEKUSER

PTRACE_POKETEXT

PTRACE_POKEDATA

PTRACE_POKEUSER

PTRACE_GETREGS

PTRACE_GETFPREGS,

PTRACE_SETREGS

PTRACE_SETFPREGS

PTRACE_CONT

PTRACE_SYSCALL,

PTRACE_SINGLESTEP

PTRACE_DETACH

在下文中将对这些常量的用法进行说明。

 

读取系统调用的参数

 

通过将 PTRACE_PEEKUSER 作为 ptrace  的第一个参数进行调用,可以取得与子进程相关的寄存器值。

 

先看下面这个例子

 

#include  < sys / ptrace.h >
#include 
< sys / types.h >
#include 
< sys / wait.h >
#include 
< unistd.h >
#include 
< linux / user.h >
#include 
< sys / syscall.h >     /*  For SYS_write etc  */

int  main()
{   
    pid_t child;
    
long  orig_eax, eax;
    
long   params [ 3 ];
    
int  status;
    
int  insyscall  =   0 ;
    child 
=  fork();
    
if (child  ==   0 )  {
        ptrace(PTRACE_TRACEME, 
0 , NULL, NULL);
        execl(
" /bin/ls " ,  " ls " , NULL);
    }

    
else   {
       
while ( 1 )  {
          wait(
& status);
          
if (WIFEXITED(status))
              
break ;
          orig_eax 
=  ptrace(PTRACE_PEEKUSER, 
                     child, 
4   *  ORIG_EAX, NULL);
          
if (orig_eax  ==  SYS_write)  {
             
if (insyscall  ==   0 )  {    
                
/*  Syscall entry  */
                insyscall 
=   1 ;
                
params [ 0 ]  =  ptrace(PTRACE_PEEKUSER,
                                   child, 
4   *  EBX, 
                                   NULL);
                
params [ 1 ]  =  ptrace(PTRACE_PEEKUSER,
                                   child, 
4   *  ECX, 
                                   NULL);
                
params [ 2 ]  =  ptrace(PTRACE_PEEKUSER,
                                   child, 
4   *  EDX, 
                                   NULL);
                printf(
" Write called with  "
                       
" %ld, %ld, %ld  " ,
                       
params [ 0 ],  params [ 1 ],
                       
params [ 2 ]);
                }

          
else   {  /*  Syscall exit  */
                eax 
=  ptrace(PTRACE_PEEKUSER, 
                             child, 
4   *  EAX, NULL);
                    printf(
" Write returned  "
                           
" with %ld  " , eax);
                    insyscall 
=   0 ;
                }

            }

            ptrace(PTRACE_SYSCALL, 
                   child, NULL, NULL);
        }

    }

    
return   0 ;
}

 

这个程序的输出是这样的

 

ppadala@linux:~/ptrace > ls


a.out        

dummy.s     
ptrace.txt  


libgpm.html  

registers.c 
syscallparams.c


dummy        

ptrace.html 
simple.c


ppadala@linux:~/ptrace > ./a.out


Write called with 1, 1075154944, 48


a.out        

dummy.s     
ptrace.txt


Write returned with 48


Write called with 1, 1075154944, 59


libgpm.html  

registers.c 
syscallparams.c


Write returned with 59


Write called with 1, 1075154944, 30


dummy        

ptrace.html 
simple.c


Write returned with 30


 

 

以上的例子中我们跟踪了 write 系统调用,而 ls 命令的执行将产生三个 write 系统调用。使用 PTRACE_SYSCALL 作为 ptrace 的第一个参数,使内核在子进程做出系统调用或者准备退出的时候暂停它。这种行为与使用 PTRACE_CONT ,然后在下一个系统调用 / 进程退出时暂停它是等价的。

 

在前一个例子中,我们用 PTRACE_PEEKUSER 来察看 write 系统调用的参数。系统调用的返回值会被放入 %eax 。

 

wait 函数使用 status 变量来检查子进程是否已退出。它是用来判断子进程是被 ptrace 暂停掉还是已经运行结束并退出。有一组宏可以通过 status 的值来判断进程的状态,比如 WIFEXITED 等,详情可以察看 wait(2) man 。

 

读取寄存器的值

 

如果你想在系统调用或者进程终止的时候读取它的寄存器,使用前面那个例子的方法是可以的,但是这是笨拙的方法。使用 PRACE_GETREGS 作为 ptrace 的第一个参数来调用,可以只需一次函数调用就取得所有的相关寄存器值。

获得寄存器值得例子如下:

#include  < sys / ptrace.h >
#include 
< sys / types.h >
#include 
< sys / wait.h >
#include 
< unistd.h >
#include 
< linux / user.h >
#include 
< sys / syscall.h >

int  main()
{   
    pid_t child;
    
long  orig_eax, eax;
    
long   params [ 3 ];
    
int  status;
    
int  insyscall  =   0 ;
    
struct  user_regs_struct regs;
    child 
=  fork();
    
if (child  ==   0 )  {
        ptrace(PTRACE_TRACEME, 
0 , NULL, NULL);
        execl(
" /bin/ls " ,  " ls " , NULL);
    }

    
else   {
       
while ( 1 )  {
          wait(
& status);
          
if (WIFEXITED(status))
              
break ;
          orig_eax 
=  ptrace(PTRACE_PEEKUSER, 
                            child, 
4   *  ORIG_EAX, 
                            NULL);
          
if (orig_eax  ==  SYS_write)  {
              
if (insyscall  ==   0 )  {
                 
/*  Syscall entry  */
                 insyscall 
=   1 ;
                 ptrace(PTRACE_GETREGS, child, 
                        NULL, 
& regs);
                 printf(
" Write called with  "
                        
" %ld, %ld, %ld  " ,
                        regs.ebx, regs.ecx, 
                        regs.edx);
             }

             
else   {  /*  Syscall exit  */
                 eax 
=  ptrace(PTRACE_PEEKUSER, 
                              child, 
4   *  EAX, 
                              NULL);
                 printf(
" Write returned  "
                        
" with %ld  " , eax);
                 insyscall 
=   0 ;
             }

          }

          ptrace(PTRACE_SYSCALL, child,
                 NULL, NULL);
       }

   }

   
return   0 ;
}

这段代码与前面的例子是比较相似的,不同的是它使用了 PTRACE_GETREGS 。   其中的 user_regs_struct 结构是在 <linux/user.h> 中定义的。

 

 

来点好玩的

 

现在该做点有意思的事情了,我们将要把传给 write 系统调用的字符串给反转。

 

#include  < sys / ptrace.h >
#include 
< sys / types.h >
#include 
< sys / wait.h >
#include 
< unistd.h >
#include 
< linux / user.h >
#include 
< sys / syscall.h >

const   int  long_size  =   sizeof ( long );

void  reverse( char   * str)
{   
    
int  i, j;
    
char  temp;
    
for (i  =   0 , j  =  strlen(str)  -   2 ; 
        i 
<=  j;  ++ i,  -- j)  {
        temp 
=  str[i];
        str[i] 
=  str[j];
        str[j] 
=  temp;
    }

}


void  getdata(pid_t child,  long  addr, 
             
char   * str,  int  len)
{   
    
char   * laddr;
    
int  i, j;
    union u 
{
            
long  val;
            
char  chars[long_size];
    }
data;

    i 
=   0 ;
    j 
=  len  /  long_size;
    laddr 
=  str;
    
while (i  <  j)  {
        data.val 
=  ptrace(PTRACE_PEEKDATA, 
                          child, addr 
+  i  *   4 , 
                          NULL);
        memcpy(laddr, data.chars, long_size);
        
++ i;
        laddr 
+=  long_size;
    }

    j 
=  len  %  long_size;
    
if (j  !=   0 )  {
        data.val 
=  ptrace(PTRACE_PEEKDATA, 
                          child, addr 
+  i  *   4 , 
                          NULL);
        memcpy(laddr, data.chars, j);
    }

    str[len] 
=   ' ' ;
}


void  putdata(pid_t child,  long  addr, 
             
char   * str,  int  len)
{   
    
char   * laddr;
    
int  i, j;
    union u 
{
            
long  val;
            
char  chars[long_size];
    }
data;

    i 
=   0 ;
    j 
=  len  /  long_size;
    laddr 
=  str;
    
while (i  <  j)  {
        memcpy(data.chars, laddr, long_size);
        ptrace(PTRACE_POKEDATA, child, 
               addr 
+  i  *   4 , data.val);
        
++ i;
        laddr 
+=  long_size;
    }

    j 
=  len  %  long_size;
    
if (j  !=   0 )  {
        memcpy(data.chars, laddr, j);
        ptrace(PTRACE_POKEDATA, child, 
               addr 
+  i  *   4 , data.val);
    }

}


int  main()
{   
   pid_t child;
   child 
=  fork();
   
if (child  ==   0 )  {
      ptrace(PTRACE_TRACEME, 
0 , NULL, NULL);
      execl(
" /bin/ls " ,  " ls " , NULL);
   }

   
else   {
      
long  orig_eax;
      
long   params [ 3 ];
      
int  status;
      
char   * str,  * laddr;
      
int  toggle  =   0 ;
      
while ( 1 )  {
         wait(
& status);
         
if (WIFEXITED(status))
             
break ;
         orig_eax 
=  ptrace(PTRACE_PEEKUSER, 
                           child, 
4   *  ORIG_EAX, 
                           NULL);
         
if (orig_eax  ==  SYS_write)  {
            
if (toggle  ==   0 )  {
               toggle 
=   1 ;
               
params [ 0 ]  =  ptrace(PTRACE_PEEKUSER, 
                                  child, 
4   *  EBX, 
                                  NULL);
               
params [ 1 ]  =  ptrace(PTRACE_PEEKUSER, 
                                  child, 
4   *  ECX, 
                                  NULL);
               
params [ 2 ]  =  ptrace(PTRACE_PEEKUSER,
                                  child, 
4   *  EDX, 
                                  NULL);
               str 
=  ( char   * )calloc(( params [ 2 ] + 1 )
                                 
*   sizeof ( char ));
               getdata(child, 
params [ 1 ], str, 
                       
params [ 2 ]);
               reverse(str);
               putdata(child, 
params [ 1 ], str, 
                       
params [ 2 ]);
            }

            
else   {
               toggle 
=   0 ;
            }

         }

      ptrace(PTRACE_SYSCALL, child, NULL, NULL);
      }

   }

   
return   0 ;
}

输出是这样的:

 

ppadala@linux:~/ptrace > ls


a.out        

dummy.s     
ptrace.txt


libgpm.html  

registers.c 
syscallparams.c


dummy        

ptrace.html 
simple.c


ppadala@linux:~/ptrace > ./a.out


txt.ecartp      

s.ymmud     
tuo.a


c.sretsiger     

lmth.mpgbil 
c.llacys_egnahc


c.elpmis        lmth.ecartp  ymmud



 

 

这个例子中涵盖了前面讨论过的所有知识点,当然还有些新的内容。这里我们用 PTRACE_POKEDATA 作为第一个参数,以此来改变子进程中的变量值。它以与 PTRACE_PEEKDATA 相似的方式工作,当然,它不只是偷窥变量的值了,它可以修改它们。

 

单步

 

ptrace 提供了对子进程进行单步的功能。   ptrace(PTRACE_SINGLESTEP, …)  会使内核在子进程的每一条指令执行前先将其阻塞,然后将控制权交给父进程。下面的例子可以查出子进程当前将要执行的指令。为了便于理解,我用汇编写了这个受控程序,而不是让你为 c 的库函数到底会作那些系统调用而头痛。

 

以下是被控程序的代码   dummy1.s ,使用 gcc   –o dummy1 dummy1.s 来编译

 

.data


hello:


    

.string "hello world/n"


.globl  

main


main:


    

movl   
$4, %eax


    

movl   
$2, %ebx


    

movl   
$hello, %ecx


    

movl   
$12, %edx


    

int    
$0x80


    

movl   
$1, %eax


    

xorl   
%ebx, %ebx


    

int    
$0x80


    ret



 

 

以下的程序则用来完成单步:

 

#include  < sys / ptrace.h >
#include 
< sys / types.h >
#include 
< sys / wait.h >
#include 
< unistd.h >
#include 
< linux / user.h >  
#include 
< sys / syscall.h >
int  main()
{
    pid_t child;
    
const   int  long_size  =   sizeof ( long );
    child 
=  fork();
    
if (child  ==   0 )  {
        ptrace(PTRACE_TRACEME, 
0 , NULL, NULL);
        execl(
" ./dummy1 " ,  " dummy1 " , NULL);
    }

    
else   {
        
int  status;
        union u 
{
            
long  val;
            
char  chars[long_size];
        }
data;
        
struct  user_regs_struct regs;
        
int  start  =   0 ;
        
long  ins;
        
while ( 1 )  {
            wait(
& status);
            
if (WIFEXITED(status))
                
break ;
            ptrace(PTRACE_GETREGS, 
                   child, NULL, 
& regs);
            
if (start  ==   1 )  {
                ins 
=  ptrace(PTRACE_PEEKTEXT, 
                             child, regs.eip, 
                             NULL);
                printf(
" EIP: %lx Instruction  "
                       
" executed: %lx  " , 
                       regs.eip, ins);
            }

            
if (regs.orig_eax  ==  SYS_write)  {
                start 
=   1 ;
                ptrace(PTRACE_SINGLESTEP, child, 
                       NULL, NULL);
            }

            
else
                ptrace(PTRACE_SYSCALL, child, 
                       NULL, NULL);
        }

    }

    
return   0 ;
}


程序的输出是这样的:

你可能需要察看 Intel 的用户手册来了解这些指令代码的意思。

更复杂的单步,比如设置断点,则需要很仔细的设计和更复杂的代码才可以实现。

 

 

在第二部分,我们将会看到如何在程序中加入断点,以及将代码插入到已经在运行的程序中。

GDB 源码分析系列文章一:ptrace 系统调用和事件循环(Event Loop) 关于 gdb 内部实现介绍的文章非常少,本人计划通过阅读 gdb 源码,推出系列文章介绍 gdb 内部实现的机制,以窥视 gdb 内部是如何控制和调试程序的。 阅读详情

相关推荐

zynq+LWIP 裸机双网口实现(MIO+EMIO)+程序下载

芯片型号: ZYNQ: XC7Z010clg400开发软件:Vivado2022 + Xilinx Vitis 2022网卡芯片:RTL8211FDI(需要根据网口芯片型号修改对应的硬件配置代码。

thinking in 小宇宙 3404

玩转ptrace(一)

by Pradeep PadalaCreated 2002-11-01 02:00翻译: Magic.D E-mail: adamgic@163.com译者序:在开发Hust Online Judge的过程中,查阅了不少资料,关于调试器技术的资料在网上是很少,即便是UNIX编程巨著《UNIX环境高级编程》中,相关内容也不多,直到我在http://www.linuxjournal.c

5838

PID控制器(位置式和增量式)

PID控制算法

zhinian_hao的博客 4512

linux后门程序利用,利用Linux的共享库编写出injectso后门程序

下面让我们来写一个简单后门程序。第1步,我们可以调用上面给出的ptrace_attach()完成。第2步,可以通过find_symbol()找到_dl_open的地址。第3步我们可以调用ptrace_call()来调用_dl_open,但是要注意_dl_open定义为’internal_function’,这说明它的传递方式是通过寄存器而不是堆栈,这样看来在调用_dl_open之前还需做一些琐碎的...

weixin_42458217的博客 425

基于PLC智能立体车库控制系统设计

摘要 本系统设计以三层立体车库为研究对象,通过对立体车库的原理分析、动作流程设计和一系列的软硬件设计,达到立体车库自动化控制的目的。系统采用可编程控制器作为立体车库控制系统的控制单元,实现该系统的工艺要求,通过程序仿真调试,完成系统的各种动作要求,达到自动控制的目的。系统设计分为总体设计、硬件设计以及软件设计。按照立体车库控制系统的控制策略进行图纸设计;重点分析工艺流程图,对立体车库控制系统进行程序编译和MCGS上位机调试,通过系统的调试和修改,达到了基本控制的要求。系统设计明确了工艺要求,确定

DX884164131的博客 3600

4G LTE 与 5G 无线网络规划对比:从 BBU/RRU 到 CU/DU/AAU 的架构演进解析

本文深度解析4G LTE与5G无线网络架构的演进差异,从BBU/RRU分立式架构到CU/DU/AAU三级重构,揭示移动通信代际跃迁的技术本质。重点对比了网络规划中的覆盖能力、容量规划、传输网络等九大维度,为通信工程师提供实用的技术对照手册,助力5G网络高效部署。

weixin_32821533的博客 287

玩转ptrace(一) [z](转帖真的很好)

 玩转ptrace(一) [z]  by Pradeep Padala Created 2002-11-01 02:00翻译: Magic.D E-mail: adamgic@163.com译者序:在开发Hust Online Judge的过程中,查阅了不少资料,关于调试器技术的资料在网上是

zgl07的专栏 899

YOLOv5轻量化实战:从Ghost模块到工业级部署的完整指南

本文详细介绍了YOLOv5轻量化实战,重点解析了Ghost模块在工业检测中的应用及其优化策略。通过Ghost卷积技术,模型参数量和GFLOPs显著降低,同时保持高精度,适用于实时性要求严格的工业场景。文章还提供了从模型优化到TensorRT加速的完整部署指南,助力开发者实现高效工业级应用。

weixin_28223453的博客 487

Linux共享库注入后门

LINUX共享库 类似Windows系统中的动态链接库,Linux中也有相应的共享库用以支持代码的复用。Windows中为*.dll,而Linux中为*.so。下 面详细介绍如何创建、使用Linux的共享库。 一个例子: #include int sayhello( void ) {     printf("hello form sayhello function!/n");

kfy2011的专栏 901

【HALCON工业视觉应用探索】02. C# + Halcon铸件毛刺机器人打磨引导:点云处理从实验室到工业现场的全流程落地

摘要:铸件毛刺的自动化打磨是机械制造领域的重要难题,其随机性(高度0.1-3mm)和复杂工况导致人工打磨效率低(3分钟/件)、工伤率高。本文基于Halcon 24.11与.NET 6,构建了一套点云处理方案:通过线激光扫描仪获取三维点云,经预处理、毛刺检测、路径规划三大模块,引导机器人完成打磨。虚拟实验测试显示,对高度>1mm的毛刺检出率达100%,定位误差±0.08mm,但工业现场受油污、粉尘影响,性能降至检出率68-75%、处理时间>45秒。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1127

x265开源编码器源码框架深度解析

x265开源编码器源码框架深度解析

世界那么大,我想去看看~【随心更新,看世界去了😄】 668

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

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

MyArrow的专栏 1万+

【GameFramework框架内置模块】8、文件系统(File System)

最近好忙,鸽了好久。不能颓废了,继续发力。今天分享的是GF框架的文件系统。首先,引用比较官方的说法:GF的FileSystem虚拟文件系统,使用类似磁盘存储的感念对零散的文件进行集中管理,优化资源加载时产生的内存分配,也可以对资源进行局部片段加载,极大的提升了资源加载的性能。通俗点讲就是,我这个模块就是加载磁盘文件的,优化加载时产生的内存分配。那么,它是怎么优化的呢?

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 2449

玩转ptrace(一) [转]

原文:http://blog.chinaunix.net/u/19651/showart_362901.html英文原文:http://www.linuxjournal.com/article/6100code:ftp.ssc.com/pub/lj/listings/issue103/6011.tgz-------------------------------------------------

scancsdn的专栏 568

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

[转] Playing with ptrace, Part I — 玩转ptrace(一)

Playing with ptrace, Part Iby Pradeep Padala p_padala@yahoo.com http://www.cise.ufl.edu/~ppadalaCreated 2002-11-01 02:00 翻译: Magic.D E-mail: adamgic@163.com 译者序: 在开发Hust Online Judge的过程中,查阅了不少资料,关于调试器...

weixin_30740295的博客 84

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

玩转ptrace(二)

by Pradeep PadalaCreated 2002-11-01 02:00翻译: Magic.D 在第一部分中我们已经看到ptrace怎么获取子进程的系统调用以及改变系统调用的参数。在这篇文章中,我们将要研究如何在子进程中设置断点和往运行中的程序里插入代码。实际上调试器就是用这种方法来设置断点和执行调试句柄。与前面一样,这里的所有代码都是针对i386平台的。 附着在

4914

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

玩转ptrace

原文地址:http://www.cnblogs.com/catch/p/3476280.html点击打开链接 二点击打开链接 [译] 玩转ptrace (一) [本文翻译自这里: http://www.linuxjournal.com/article/6100?page=0,0,作者:Pradeep Padaia]   你是否曾经想过怎样才能拦截系统调用?你是否曾经想过通过修改一

yang_chen_shi_wo的博客 372

linux ptrace反调试之抢占ptrace

ptrace和debugger原理 ptrace ptrace可以让一个进程监视和控制另一个进程的执行,并且修改被监视进程的内存、寄存器等,主要应用于断点调试和系统调用跟踪. 函数原型: long ptrace(int request, pid_t pid, void * addr, void * data) 其中,request代表请求类型,pid代表被调试进程的pid. 部分...

whatday的专栏 1821

linux ptrace 图文详解(一)基础介绍

ptrace 是 linux内核 提供的一个系统调用,并非一个标准的posix接口,ptrace 主要用于进程跟踪和调试。它运行一个用户态进程(通常称为跟踪器, Tracer)控制和监视另一个进程(称为被调试进程, Tracee)的执行。ptrace是许多调试跟踪工具(如:GDB、strace 等)的 “基座”,其函数原型如下:用于标识一个需要执行的操作;标识目标线程ID一个内存地址和附加信息,其语义因选择的操作而不同;

h_b__k的博客 2342

ptrace的使用流程

参考链接: https://blog.youkuaiyun.com/imred/article/details/90141080 一、tracer和tracee的跟踪状态建立 两种方式:一种情况是tracer是tracee的父进程,进程tracee主动调用PTRACE_TRACEME.另外一种是进程tracer调用PTRACE_ATTACH或者或PTRACE_SEIZE。 处理PTRACE_ATTACH请求...

海棠花的博客 3705

strace原理、ptrace PTRACE_SYSCALL 调用跟踪

strace实现原理分析

kiraskyler的博客 2134

玩转ptrace(二) [转]

code:http://ftp.ssc.com/pub/lj/listings/issue104/6210.tgz 英文原文http://www.linuxjournal.com/article/6210-------------------------------------------------------------------------------------------------

scancsdn的专栏 422
上一篇: 【转】GTK+主循环(main loop)的工作原理
下一篇: 【转】玩转ptrace(二)
code09
博客等级 码龄18年 31粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值