This article was reproduced from: http://blog.csdn.net/ixidof/article/details/7673568
Ptrace---Allows the interception and modification of system calls at the user level ;
Do you want to know how the system call was intercepted?
Have you tried to fool the kernel by modifying the parameters of the system call?
Have you ever thought about how the debugger pauses the running process and gives you control over it?
Without complex kernel programming,ptrace (Process trace) system calls can help you implement the above functionality.
Ptrace provides a mechanism that allows the parent process to observe and control other processes, which can examine and modify the kernel images of other processes, so it is preferred to implement breakpoint debugging and system call tracing.
This article will focus on how to intercept system calls and modify its parameters . In Part II, you'll learn some advanced tricks--- set breakpoints and inject code into a running program . We will spy on the registers and data segments of the child process and modify the contents. We will also talk about a code injection method that allows a process to stop and execute arbitrary instructions.
Basic knowledge
System Call---system calls are a bridge between the application layer and the kernel, and applications can access the underlying hardware and lower-level services (such as file systems) through system calls. When the application makes a system call, the parameter is placed in the register and the 0x80 soft interrupt is called. The soft interrupt is like a door into the kernel mode, and the kernel completes the parameter check and begins to perform the specific operation.
On the i386 architecture (the code in this article is based on the i386 architecture), the system call number is placed in the %eax Register, and the parameters of the system call are placed sequentially in %ebx,%ECX,%edx,%esi and %edi registers.
For example:
Write (2, "Hello", 5);
After translation into assembly language, roughly the following form:
MOVL $4,%EAXMOVL $2,%ebxmovl $hello,%ECXMOVL $5,%edx int $0x80
Where $hello point to the string constant "Hello".
So, where should ptrace appear?
Before the system call is performed, the kernel checks to see if the process is being traced ( being traced ), and if the kernel pauses the tracked process and gives control to the tracking process, the tracking process can modify the registers of the tracked process.
Let's look at an example to see how the process works:
#include <sys/ptrace.h>#include<sys/types.h>#include<sys/wait.h>#include<unistd.h>#include<linux/user.h>/*For constants Orig_eax etc*/intMain () {pid_t child; LongOrig_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\n", Orig_eax); Ptrace (Ptrace_cont, child, NULL, NULL); } return 0;}
( Note : The header file to be included is related to the specific system, such as the <sys/reg.h> on my machine)
Run the program and print out:
The child made a system call 11
The results of the LS command are also output. (System call number can refer to/usr/include/asm/unistd.h)
As you can see, the parent process fork out a child process and executes the process we want to track (LS) in the subprocess. Before running exec , the child process calls Ptrace first and its first parameter is Ptrace_traceme. This tells the kernel that the process is a tracked process, and when it executes the EXECVE system call, it hands over the control to its parent (the parent process waits for notifications from the kernel through the Wait () call), and then the parent process can check the parameters of the system call or do something else, such as viewing registers, and so on.
When a system call occurs, the kernel saves the original value in the EAX register (that is, the system call number), and the first parameter of Ptrace is set to Ptrace_peekuser, which can be read to the value of the user data segment.
Setting the first parameter of Ptrace to Ptrace_cont allows the system calls in the child process to continue executing.
Parameters of the Ptrace
Long Ptrace (enum __ptrace_request request,
pid_t PID,
void *addr,
void *data);
Where the first parameter determines the behavior of ptrace and how other parameters are used, the value of the request may be one of the following:
Ptrace_traceme,
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.
1) ptrace_traceme
Form: Ptrace (ptrace_traceme,0, 0, 0)
Description: This process is tracked by its parent process. Its parent process should want to track child processes.
2) Ptrace_peektext, Ptrace_peekdata
Form: Ptrace (Ptrace_peektext, PID, addr, data)
Ptrace (Ptrace_peekdata, PID, addr, data)
Description: Reads a byte from the memory address, the PID represents the child process being traced, the memory address is given by addr, and data is used for the user variable address to return the read data. In Linux (i386), the user code segment coincides with the user data segment so that the read code snippet and data segment are processed the same.
3) Ptrace_poketext, Ptrace_pokedata
Form: Ptrace (Ptrace_poketext, PID, addr, data)
Ptrace (Ptrace_pokedata, PID, addr, data)
Description: Writes a byte to the memory address. The PID represents the child process being traced, the memory address is given by addr, and data is what is to be written.
4) PTRACE_PEEKUSR
Form: Ptrace (PTRACE_PEEKUSR, PID, addr, data)
Description: Reads a byte from the user area, the PID represents the child process being traced, the user zone address is given by addr, and data is used for the user variable address to return the read data. The user structure is the previous part of the core file, which describes some of the state of the process when it aborts, such as: Register value, code, data segment size, code, data segment start address, and so on. The data in Linux (i386) that can access the user structure through Ptrace_peekuser and PTRACE_POKEUSR has registers and debug registers.
5) Ptrace_pokeusr
Form: Ptrace (PTRACE_POKEUSR, PID, addr, data)
Description: Writes a byte to the user area, the PID represents the child process being traced, the user zone address is given by addr, and data is the one that needs to be written.
6) Ptrace_cont
Form: Ptrace (Ptrace_cont, PID, 0, signal)
Description: Continue execution. The PID indicates the child process being traced, signal 0 ignores the signal that caused the debug process to abort, and if not 0 continues to process the signal signal.
7) Ptrace_syscall
Form: Ptrace (Ptrace_sys, PID, 0, signal)
Description: Continue execution. The PID indicates the child process being traced, signal 0 ignores the signal that caused the debug process to abort, and if not 0 continues to process the signal signal. Unlike Ptrace_cont, system call tracking is performed. When the tracked process continues to run until the call system call begins or ends, the tracked process is aborted and the parent process is notified.
8) Ptrace_kill
Form: Ptrace (ptrace_kill,pid)
Description: Kill the child process and make it exit. The PID represents the child process being traced.
9) Ptrace_singlestep
Form: Ptrace (Ptrace_kill, PID, 0, Signle)
Description: Sets the step flag to step through a single instruction. The PID represents the child process being traced. A signal of 0 ignores the signal that caused the debug process to abort and, if not 0, continues to process the signal signal. The tracked process is aborted and the parent process is notified when the tracked process steps through a single instruction.
) Ptrace_attach
Form: Ptrace (ptrace_attach,pid)
Description: Tracks the specified PID process. The PID indicates the process being traced. The tracked process becomes the child process of the current process and enters the abort state.
One) Ptrace_detach
Form: Ptrace (ptrace_detach,pid)
Description: Ends the trace. The PID represents the child process being traced. The tracked process will continue to execute after the trace is closed.
Ptrace_getregs)
Form: Ptrace (ptrace_getregs, PID, 0, data)
Description: Read the Register value, PID indicates the child process being traced, and data is the user variable address used to return the read data. This feature will read the values of all 17 basic registers.
Ptrace_setregs)
Form: Ptrace (ptrace_setregs, PID, 0, data)
Description: Sets the value of the register, PID indicates the child process being traced, and data is the address of the user. This feature sets the values for all 17 basic registers.
Ptrace_getfpregs)
Form: Ptrace (ptrace_getfpregs, PID, 0, data)
Description: Read the floating-point register value, PID indicates the child process being traced, and data is the user variable address used to return the read data. This feature reads the values of all registers for all floating-point coprocessor 387.
Ptrace_setfpregs)
Form: Ptrace (ptrace_setregs, PID, 0, data)
Description: Sets the value of the floating-point register, PID indicates the child process being traced, and data is the address of the user. This feature sets the value of all registers for all floating-point coprocessor 387.
[Reprint]playing with Ptrace (part I)---first knowledge of ptrace