Извлечение имени и аргументов системного вызова с помощью ptrace

Я работаю над заданием, в котором мне нужно реализовать strace подобную функциональность, используя ptrace. До сих пор я узнал, как извлечь номер системного вызова и возвращаемое значение следующим образом:

//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;

Но я не смог найти, как извлечь имя и аргументы системного вызова. Может ли кто-нибудь предложить способ?


person G.Kumar    schedule 30.10.2015    source источник
comment
вам следует просмотреть код strace(), вы получите некоторое представление. Кроме того, чтобы показать вам то, что вы здесь спросили, на самом деле нужен очень большой ответ.   -  person Haris    schedule 30.10.2015
comment
Хорошо, я пишу вам ответ, добавляя все, что знаю. Надеюсь, это поможет.   -  person Haris    schedule 30.10.2015


Ответы (2)


Чтобы получить аргументы системного вызова, вы должны прочитать регистры один за другим. Для этого вам нужно знать, какие регистры будут хранить какие параметры системного вызова. Несколько месяцев назад я сам написал одну такую ​​программу. В основном, каждый регистр хранит следующее:

regs.rdi — сохраняет первый аргумент

regs.rsi — сохраняет второй аргумент

regs.rdx — сохраняет третий аргумент

regs.r10 - Сохраняет четвертый аргумент

regs.r8 - Сохраняет пятый аргумент

regs.r9 - Сохраняет шестой аргумент

В этой таблице представлено более подробное описание (обратите внимание, что оно относится к архитектуре x86-64).

Теперь вам нужно просмотреть документацию по каждому системному вызову, чтобы понять и закодировать их отдельно. Существуют разные способы прочтения различных аргументов.


Давайте рассмотрим системный вызов read(), чтобы продемонстрировать это.

Мы увидим различные типы аргументов и посмотрим, как получить к ним доступ.

1-й аргумент (целое fd)

Поскольку это число, оно будет сохранено непосредственно в регистре regs.rdi.

В моем коде мне нужно было получить файл, на который указывал fd, поэтому я использовал следующий код.

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);

2-й аргумент (void *buf) указатель на входной буфер

Чтобы прочитать это, вам нужно будет использовать запрос PTRACE_PEEKDATA / PTRACE_PEEKTEXT (первый аргумент ptrace()) для чтения байтов. Поскольку ptrace() считывает и возвращает только 8 байт за раз, вам нужно делать это итеративно, используя переменную long. В начале памяти должен быть еще один char *, который будет использоваться позже для чтения строки.

Код, который я использовал, следующий.

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);

Это все, что я могу сказать. Думаю, таким образом можно прочитать почти все параметры большинства системных вызовов.

Что касается имени системного вызова. Я сопоставил ОС и сделал ручное switch дело, чтобы получить имя системного вызова.


Надеюсь это поможет. :)

person Haris    schedule 30.10.2015
comment
Как насчет возвращаемых значений? Они так же легко хранятся в одном реестре? - person ; 10.10.2019
comment
@traducerad, на самом деле да.. Он хранится в регистре regs.rax.. - person Haris; 10.10.2019

Я бы сопоставил regs.orig_rax с постоянным списком системных вызовов, вы можете получить список из /usr/include/x86_64-linux-gnu/asm/unistd_64.

если вы хотите узнать, на что указывают адреса реестров, предлагаю вам прочитать https://groogroot.eu/the-ptrace-system-call/ метод read_addr_into_buff, я использовал его для чтения regs.rsi, когда был обнаружен __NR_write SC.

person Barnum Castillo    schedule 25.04.2021