Вот еще одна стратегия, которая может нуждаться в доработке, но должна быть более эффективной с большими порциями данных. Идея состоит в том, чтобы выполнить syscalls в удаленном процессе, чтобы извлечь содержимое стека. Для этого потребуется конкретный код архитектуры, но если вы ориентируетесь только на x86 / x86_64, это не должно вызывать особых хлопот.
- Создайте именованный канал, такой как
"/tmp/fifo"
в вашем процессе вызова.
- Шагайте в отслеживаемый процесс до тех пор, пока он не вернется из системного вызова, используя
PTRACE_SYSCALL
шаг, waitpid()
чтобы подождать и PTRACE_GETREGS
/ PTRACE_PEEKTEXT
проверить текущий исполняемый код операции.
- Резервное копирование регистров удаленного процесса и небольшой области его стека.
- Выполнение системных вызовов на удаленном процессе, перекрывая его стек с вашими собственными данными:
open("/tmp/fifo")
, write()
содержимое стека, close()
дескриптор.
- Восстановить состояние удаленного процесса.
- Прочитайте данные fifo из вашего процесса вызова.
Могут быть более элегантные альтернативы именованным каналам, но я не могу сейчас придумать ни одного. Причина, по которой я использую только системные вызовы, заключается в том, что удаленное внедрение кода довольно ненадежно в современных системах из-за различных мер безопасности. Недостатком является то, что он будет зависать, пока удаленный процесс не выполнит системный вызов (что может быть проблемой для некоторых программ, которые в основном выполняют вычисления).
Вы можете увидеть бесплатный код, реализующий большую часть работы в этом исходном файле . Обратная связь по коду приветствуется!
waitpid
междуptrace(PTRACE_ATTACH,…)
иread
(иначе возможное состояние гонки)? Какую ошибкуread
возвращает? Делает ли ребенок что-то своеобразное с отображением памяти - можете ли вы попробовать свой код с простым ребенком, какsleep
?