Extracting system call name and arguments using ptrace

眉间皱痕 提交于 2019-12-24 00:10:03

问题


I am working on an assignment in which i have to implement strace like functionality using ptrace. So far, I have found out how to extract system call number and return value like this:

//In parent process
struct user_regs_struct regs;
ptrace( PTRACE_GETREGS, child_pid, 0, &regs ); 
//child_pid is the pid of child process executing the required program
//or system call passed as command line arguments
syscall_num = regs.orig_rax;
syscall_retval = regs.rax;

But I haven't been able to find how to extract system call name and arguments. Can anyone suggest a way?


回答1:


To get the arguments of the system call you have to read the registers one by one. For that you need to know which registers will be storing which parameters of the system call. Few months back I had written one such program myself. Basically what each register stores is this:

regs.rdi - Stores the first argument

regs.rsi - Stores the second argument

regs.rdx - Stores the third argument

regs.r10 - Stores the fourth argument

regs.r8 - Stores the fifth argument

regs.r9 - Stores the sixth argument

This table presents a more elaborated description (notice that it's specific to x86-64 architecture).

Now, you have to go through the documentation of each system call to understand and code for them separately. There are different ways to read different arguments.


Lets take the read() system call to demonstrate this.

We will see the different kinds of arguments and see how to access them.

1st argument (int fd)

Since it is a number it will be saved directly in the register regs.rdi.

In my code, i needed to get the file to which that fd was pointing at so i used the following code.

sprintf(fdpath,"/proc/%u/fd/%llu",proc,regs.rdi);
size = readlink(fdpath, filepath, 256);  //this gives the filepath for a particular fd
filepath[size] = '\0';
printf("File-%s-\n", filepath);

2nd argument (void *buf) ptr to input buffer

To read this you would need to use PTRACE_PEEKDATA / PTRACE_PEEKTEXT request (the first argument of ptrace()) to read the bytes. Since ptrace() reads and returns only 8 bytes at a time, you need to do this iteratively using a long variable. There should be another char * pointing in the beginning of the memory, that would be used later to read the string.

The code that I used is the following.

char message[1000];
char* temp_char2 = message;
int j = 0;
long temp_long;

while( j < (regs.rdx/8) ) //regs.rdx stores the size of the input buffer
{
    temp_long = ptrace(PTRACE_PEEKDATA, proc, regs.rsi + (j*8) , NULL);
    memcpy(temp_char2, &temp_long, 8);
    temp_char2 += sizeof(long);
    ++j;
}
message[regs.rdx] = '\0';
printf("Message-%s-\n\n", message);

Thats all I can say. I guess you can read almost all the parameters of most of the system calls this way.

As for the name of the system call. I the OS mapping and made a manual switch case to get the name of the system call.


Hope this helps. :)



来源:https://stackoverflow.com/questions/33431994/extracting-system-call-name-and-arguments-using-ptrace

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!