Linux:有没有办法使用ptrace而不停止/暂停进程(SIGSTOP)?

我试图将一个程序从Windows移植到Linux。
当我发现Linux上没有“真正的” ReadProcessMemory对应项时,遇到了一个问题。 我寻找一个替代品,我发现ptrace ,一个强大的stream程debugging器。
我在C ++中快速地编写了两个小控制台应用程序来testingptrace ,然后在程序中使用它。

TestApp

这是微量元素。 它每隔50毫秒不断打印两个整数,每次增加1个值。

 #include <QCoreApplication> #include <QThread> #include <iostream> using namespace std; class Sleeper : public QThread { public: static void usleep(unsigned long usecs){QThread::usleep(usecs);} static void msleep(unsigned long msecs){QThread::msleep(msecs);} static void sleep(unsigned long secs){QThread::sleep(secs);} }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); int value = 145; int i = 0; do { cout << "i: " << i << " " << "Value: " << value << endl; value++; i++; Sleeper::msleep(50); } while (true); return a.exec(); } 

记忆testing

这是示踪剂; 它要求进程名称并使用命令pidof -s检索PID,然后ptrace附加进程并每隔500毫秒检索一次内存地址值,共10次。

 #include <QCoreApplication> #include <QThread> #include <iostream> #include <string> #include <sys/ptrace.h> #include <errno.h> using namespace std; class Sleeper : public QThread { public: static void usleep(unsigned long usecs){QThread::usleep(usecs);} static void msleep(unsigned long msecs){QThread::msleep(msecs);} static void sleep(unsigned long secs){QThread::sleep(secs);} }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); char process_name[50]; cout << "Process name: "; cin >> process_name; char command[sizeof(process_name) + sizeof("pidof -s ")]; snprintf(command, sizeof(command), "pidof -s %s", process_name); FILE* shell = popen(command, "r"); char pidI[sizeof(shell)]; fgets(pidI, sizeof(pidI), shell); pclose(shell); pid_t pid = atoi(pidI); cout << "The PID is " << pid << endl; long status = ptrace(PTRACE_ATTACH, pid, NULL, NULL); cout << "Status: " << status << endl; cout << "Error: " << errno << endl; unsigned long addr = 0x012345; // Example address, not the true one int i = 0; do { status = ptrace(PTRACE_PEEKDATA, pid, addr, NULL); cout << "Status: " << status << endl; cout << "Error: " << errno << endl; i++; Sleeper::msleep(500); } while (i < 10); status = ptrace(PTRACE_DETACH, pid, NULL, NULL); cout << "Status: " << status << endl; cout << "Error: " << errno << endl; return a.exec(); } 

一切正常,但TestApp暂停(SIGSTOP),直到ptrace从它分离。
另外,当它附加到进程时,状态为0,错误为2; 它第一次尝试检索内存地址值失败,状态-1和错误3.是否正常?
有没有办法阻止ptrace向进程发送SIGSTOP信号? 我已经尝试使用PTRACE_SEIZE而不是PTRACE_ATTACH ,但它不起作用:状态-1和错误3。

更新:即使秒,毫秒或微秒的值为0,在“do-while”循环之前使用MemoryTest中的Sleeper修复了第一个内存地址值检索的问题。为什么?

达维德

你有没有看过/ proc文件系统? 它包含可用于查看整个进程空间的内存映射文件。 您也可以在空间中写入来设置断点。 / proc中还有大量的其他信息。

PTRACE_CONT命令可用于继续进程。 一般来说,当调试器连接时,目标将被暂停PTRACE_ATTACH。

手册页说PTRACE_SIEZE不应该暂停过程。 你使用什么风味和版本的Linux? PTRACE_SIEZE已经有一段时间了,所以我不知道你为什么在那里遇到麻烦。

我注意到addr的值被设置为0x12345。 这是目标空间中的有效地址吗? 还是仅仅是一个例子? 在两个进程之间如何交换感兴趣的堆栈地址(&value)?

我不太清楚返回代码。 通常0表示一切都很好,错误号可能只是最后一个错误的宿醉值。

–Matt

经过大量的研究,我很确定,如果不停止这个过程,没有办法使用ptrace
我找到了一个名为process_vm_readv ReadProcessMemory process_vm_readv ,它比较简单。

我发布了代码,希望帮助处于我(以前)情况下的人。

非常感谢mkrautz为他的编程 MemoryTest的帮助与这个漂亮的功能。

 #include <QCoreApplication> #include <QThread> #include <sys/uio.h> #include <stdint.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <iostream> using namespace std; class Sleeper : public QThread { public: static void usleep(unsigned long usecs){QThread::usleep(usecs);} static void msleep(unsigned long msecs){QThread::msleep(msecs);} static void sleep(unsigned long secs){QThread::sleep(secs);} }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); char process_name[50]; cout << "Process name: "; cin >> process_name; char command[sizeof(process_name) + sizeof("pidof -s ")]; snprintf(command, sizeof(command), "pidof -s %s", process_name); FILE* shell = popen(command, "r"); char pidI[sizeof(shell)]; fgets(pidI, sizeof(pidI), shell); pclose(shell); pid_t pid = atoi(pidI); cout << "The PID is " << pid << endl; if (pid == 0) return false; struct iovec in; in.iov_base = (void *) 0x012345; // Example address, not the true one in.iov_len = 4; uint32_t foo; struct iovec out; out.iov_base = &foo; out.iov_len = sizeof(foo); do { ssize_t nread = process_vm_readv(pid, &out, 1, &in, 1, 0); if (nread == -1) { fprintf(stderr, "error: %s", strerror(errno)); } else if (nread != in.iov_len) { fprintf(stderr, "error: short read of %li bytes", (ssize_t)nread); } cout << foo << endl; Sleeper::msleep(500); } while (true); return a.exec(); }