我正在尝试读取子进程的堆栈,但是没有运气。我知道可以使用ptrace
,但是ptrace
的界面仅允许您一次只读取一个单词,而我正在尝试扫描堆栈的较大部分。
我也试着阅读/proc/$pid/mem
从堆栈的boundries从提取/proc/$pid/maps
使用ptrace的附加到它(如建议的文件后先在这里),但(以root运行时,即使)读不停地进行故障虽然尝试时相同的代码成功从过程的不同部分(例如堆)读取。
我究竟做错了什么?还有其他选择吗?
我正在尝试读取子进程的堆栈,但是没有运气。我知道可以使用ptrace
,但是ptrace
的界面仅允许您一次只读取一个单词,而我正在尝试扫描堆栈的较大部分。
我也试着阅读/proc/$pid/mem
从堆栈的boundries从提取/proc/$pid/maps
使用ptrace的附加到它(如建议的文件后先在这里),但(以root运行时,即使)读不停地进行故障虽然尝试时相同的代码成功从过程的不同部分(例如堆)读取。
我究竟做错了什么?还有其他选择吗?
Answers:
ptrace
的界面允许您一次只读取一个字,而我正尝试扫描堆栈的较大部分
好吧,那么就使用循环。老实说ptrace
,我看不出这是什么问题,我一直都在使用它来远程访问流程。
我用这样的东西:
static int memcpy_from_target(pid_t pid, char *dest, long src, size_t n)
{
static int const align = sizeof(long) - 1;
while (n)
{
size_t todo = MIN(n, sizeof(long) - (src & align));
long data = ptrace(PTRACE_PEEKTEXT, pid, src - (src & align), 0);
if (errno)
{
perror("ptrace_peektext (memcpy_from_target)");
return -1;
}
memcpy(dest, (char *)&data + (src & align), todo);
dest += todo; src += todo; n -= todo;
}
return 0;
}
这是另一种可能需要调整的策略,但对大数据量应该更有效。这个想法是在远程进程中执行系统调用,以检索堆栈内容。它将需要特定的体系结构代码,但是如果您仅针对x86 / x86_64,则应该不会太麻烦。
"/tmp/fifo"
在调用过程中创建一个命名管道。PTRACE_SYSCALL
来执行步骤,waitpid()
以等待和PTRACE_GETREGS
/ PTRACE_PEEKTEXT
检查当前执行的操作码。open("/tmp/fifo")
,write()
堆栈内容close()
和描述符,在远程进程上执行系统调用。命名管道可能会有更优雅的替代方法,但是我现在想不起来。我仅使用syscall的原因是由于各种安全保护,在现代系统上远程代码注入非常不可靠。缺点是它将挂起,直到远程进程执行系统调用为止(这对于某些主要执行计算的程序可能是个问题)。
您可以在此源文件中看到一些免费的代码来实现大部分工作。欢迎提供有关代码的反馈!
另一个建议。
当/如果它在主Linux内核树中被接受,您将能够使用Christopher Yeoh的Cross Memory Attach补丁。例如,请参阅有关process_vm_readv的文档。
您可以使用proc文件系统轻松读取另一个进程的堆栈(为此您将需要root访问权限)。在从/ proc / pid / mem任意读取之前,您需要查阅/ proc / pid / maps。对该文件进行简单的读取即可显示很多条目。我们对标记为堆栈的条目感兴趣。一旦掌握了这一点,就需要阅读堆栈的上下边界。现在,只需打开/ proc / pid / mem文件,找到堆栈的下限并读取正确的数据大小即可。
mems
,而不是maps
?(我mems
在/proc
文件系统下看不到任何条目。)OP已经提到从中读取堆栈边界/proc/$pid/maps
-您建议它们做些什么不同?
您可以尝试lsstack。就像其他所有成功的“读取另一个进程的堆栈”程序一样,它使用ptrace。我无法使用/ proc / $ pid / mem读取来运行程序。我相信您不能那样做,尽管从逻辑上讲您应该这样做。
waitpid
在ptrace(PTRACE_ATTACH,…)
和之间打过电话read
(否则可能存在比赛情况)?read
返回什么错误?该子对象是否在执行其内存映射所特有的操作-您可以像这样的简单子对象尝试代码sleep
吗?