Здесь важно отметить, что запрос PTRACE_SYSCALL сделает целевой процесс остановленным при входе в или выходе из системного вызова.Страница руководства говорит, что
Syscall-enter-stop и syscall-exit-stop трассировщик неотличимы друг от друга.Трассировщик должен отслеживать последовательность ptrace-stop, чтобы не интерпретировать syscall-enter-stop как syscall-exit-stop или наоборот.
Если вы используете ptrace для изменения целиРегистрируя значения, вы изменяете аргументы системного вызова, которые увидит ядро, или возвращаемое значение, которое увидит пользовательский процесс, в зависимости от того, делаете ли вы это с помощью syscall-enter-stop или syscall-exit-stop.
Ваш код здесь запускается по syscall-enter-stop:
if (regs.orig_eax == 26 && regs.ebx == PTRACE_TRACEME) {
regs.eax = 0;
PTRACE_E(PTRACE_SETREGS, pid, NULL, ®s);
break;
}
Он изменяет значение eax (которое равно -38 при входе в системный вызов) на 0. Поскольку вы намеревались изменить возвратКод из запроса PTRACE_TRACEME цели от -1 до 0, вам нужно сделать PTRACE_SYSCALL еще раз, чтобы цель остановилась на syscall-exit-stop, прежде чем запускать вышеуказанный код.
В настоящее время,ваш код выходит из цикла после запроса PTRACE_SETREGS, а затем выполняет
ptrace(PTRACE_DETACH, pid, NULL, NULL);
, который отсоединится от цели и продолжит ее.Цель (теперь ex-) завершает свой запрос PTRACE_TRACEME, который успешно выполняется, и его родитель снова становится трассировщиком.
execl("/usr/bin/gdb", "/usr/bin/gdb", "-p", buf, NULL);
GDB выдаст предупреждающее сообщение, поскольку неожиданно уже является трассировщиком дляцель.