6

Насколько я знаю, ptrace может получить номер системного вызова только через PTRACE_SYSCALL, но номер системного вызова отличается в x86 и x64. Так есть ли способ выяснить, где этот системный вызов реального происхождения?

Сейчас я пишу программу, чтобы ограничить системный вызов некоторых других по номеру системного вызова, я знаю номер системного вызова на x86 и x64, но некоторые программы используют int 80h вместо syscall, чтобы они могли делать опасные вещи, которые Я ограничился на х64. Например, я запретил fork() на x64, они могут использовать 'int 80h(2)'(fork()), и я упал, что они используют 'syscall(2)'(open()), таким образом, они могут преодолеть ограничение , Хотя ptrace может отследить их обоих и получить номер системного вызова, я не могу различить, где фактически происходит системный вызов.

2 ответа2

1

Похоже, на момент написания (2019-02-08)это невозможно.

И даже strace это неправильно.

Редактировать: Линус Торвальдс говорит об этом здесь, также анализируя возможные (но закомментированные) обходные пути в коде strace которые непосредственно смотрят на инструкции, сделанные в двоичном файле. Этот код был удален здесь как часть набора патчей, который я упоминаю ниже. Он говорит, что It works, but is too complicated, and strictly speaking, unreliable , но мне неясно, в каких случаях применяется «строго говоря, ненадежный», если это происходит только в случае многопоточного исполняемого файла, перезаписывающего себя в время выполнения (таким образом, не подходит для запрета определенных системных вызовов для случаев использования в целях безопасности), а также в других случаях.

Изменить: "ненадежная" часть была добавлена в этот коммит.

Редактировать: теперь я попробовал реализацию стракса с проверкой кода операции (версия v4.25) и подозреваю, что она содержит ошибки : при активации этого пути к коду путем изменения этой строки на #if 0 и этой строки на #elif 1 никаких системных вызовов нет напечатан, потому что scno не установлен вообще. Я добавил scno = x86_64_regs.orig_rax; после этой строки, чтобы заставить его работать.

Смотрите презентацию « Как сделать страсти счастливыми», слайд 2, задача 2:

Не существует надежного способа различить системные вызовы x86_64 и x86.

Детали показаны на слайдах 4-6. Существует предлагаемое решение для добавления в ядро:

Расширьте API ptrace с помощью запроса PTRACE_GET_SYSCALL_INFO

Но это решение не объединено с ядром.

Набор патчей называется ptrace: add PTRACE_GET_SYSCALL_INFO request и он все еще работает в январе 2019 года. Надеюсь, это скоро будет объединено.


strace уже имеет поддержку для этого с выпуска 4.26 (но он не должен работать, если вы не примените исправление ядра вручную):

Реализовано получение информации о системных вызовах с помощью ptrace API PTRACE_GET_SYSCALL_INFO .

-2

Это системный вызов sys_rt_sigtimedwait (начиная с ядра 2.2). Смотрите справочную страницу по:

man 2 rt_sigtimedwait

Этот системный вызов приостанавливает выполнение до тех пор, пока не будет доставлен сигнал (или набор singals), указанный в аргументе. Тайм-аут также был дан.

Чтобы быть на 100% уверенным, существует файл с именем unistd_64.h . Найдите в вашей системе этот файл. В основном он находится в папке include (/usr/include/x86_64-linux-gnu/asm/unistd_64.h). Есть определенные номера. Вот соответствующая строка в моем случае (это тоже 64-битная система, ядро 3.2.0-58):

#define __NR_rt_sigtimedwait                    128
__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait)

Примечание 128 является десятичным для 80 в шестнадцатеричном.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .