Чтобы получить аргументы системного вызова, вы должны прочитать регистры один за другим. Для этого вам нужно знать, какие регистры будут хранить какие параметры системного вызова. Несколько месяцев назад я сам написал одну такую программу. В основном, каждый регистр хранит следующее:
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
strace()
, вы получите некоторое представление. Кроме того, чтобы показать вам то, что вы здесь спросили, на самом деле нужен очень большой ответ. - person Haris   schedule 30.10.2015