如何ptracemultithreading应用程序?

编辑(制作进展):

我试图ptrace一个vsftpd守护进程。 我有以下代码附加到守护程序。 然后它成功显示第一个衍生进程的PID。 然而,对于这个衍生进程的子进程,它返回PID为2,3,..程序确实捕获了生成进程的退出,这让我觉得我很接近。

有任何想法吗?

void * trace_process(void * pid){ pid_t child = atoi((char *) pid); long orig_eax, eax; int status; int callmade = FALSE; long opt = PTRACE_O_TRACEFORK; long newpid; long trace = ptrace(PTRACE_ATTACH,child,NULL,NULL); ptrace(PTRACE_SETOPTIONS,child,NULL,opt); if(trace == FALSE) printf("Attached to %d\n",child); while(TRUE) { child = waitpid(-1, &status, __WALL); if (status >> 16 == PTRACE_EVENT_FORK) { ptrace(PTRACE_GETEVENTMSG, child, NULL, (long) &newpid); ptrace(PTRACE_SYSCALL, newpid, NULL, NULL); printf("Attached to offspring %ld\n", newpid); } else{ if(WIFEXITED(status)) printf("Child %d exited\n", child); } ptrace(PTRACE_SYSCALL,child, NULL, NULL); } } 

样本输出:

 Attached to 2015 // daemon Attached to offspring 5302 // new connection handler Attached to offspring 2 // should be authenticator Child 5303 exited // authenticator exiting on successful login Attached to offspring 3 // should be process serving files Child 5304 exited // logout: process serving files Child 5302 exited // connection closed Attached to offspring 5305 // new connection handler Attached to offspring 2 // ... repeat Child 5306 exited Attached to offspring 3 Child 5307 exited Child 5305 exited 

在进一步使用我的代码之后,我意识到它实际上可以捕获来自父代及其子代的所有系统调用。 唯一的问题是PID是作为相对数字返回的,而不是实际的PIds。 这导致不确定实际从父节点生成等待PID。 无论哪种方式,代码都将为您提供所有系统调用。 我仍然想知道为什么PID是相对的,据我所知,但代码工作正常。

让线程在下一个wait()之前运行。

尝试:

 ptrace(PTRACE_SYSCALL,child, NULL, NULL); 

之前:

 while(TURE) 

在阅读Play with ptrace文章的过程中,我发现了一条用户的评论 :

 /* After struggled a long time, I got a true way to make my ptrace worked * correct with multi-thread application. Here're my sample codes, hope it * can help others whom have the same confusion. */ char trapCode[] = {0, 0, 0, 0}; int status; ptrace(PTRACE_ATTACH, childProcess, NULL, NULL); //childProcess is the main thread wait(NULL); printf("\nchild %d created\n", childProcess); fflush(stdout); long ptraceOption = PTRACE_O_TRACECLONE; ptrace(PTRACE_SETOPTIONS, childProcess, NULL, ptraceOption); struct user_regs_struct regs; for(unsigned int i = 0; i < m_breakPoints.size(); i++) { BreakPoint_Info breakPointInfo = m_breakPoints[i]; if(!breakPointInfo.m_enabled) continue; unsigned int index = breakPointInfo.m_checkPointIndex; if(m_bytesBackup.find(m_checkPoints[index].m_offset) != m_bytesBackup.end()) continue; unsigned long readAddr = m_checkPoints[index].m_offset; One_Byte_With_Result *oneByte = new One_Byte_With_Result; getData(childProcess, readAddr, trapCode, 4); oneByte->m_char = trapCode[0]; trapCode[0] = 0xcc; putData(childProcess, readAddr, trapCode, 4); m_bytesBackup.insert(std::make_pair(m_checkPoints[index].m_offset, oneByte)); } std::set allThreads; std::set::iterator allThreadsIter; allThreads.insert(childProcess); int rec = ptrace(PTRACE_CONT, childProcess, NULL, NULL); while(true) { pid_t child_waited = waitpid(-1, &status, __WALL); if(child_waited == -1) break; if(allThreads.find(child_waited) == allThreads.end()) { printf("\nreceived unknown child %d\t", child_waited); break; } if(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { pid_t new_child; if(((status >> 16) & 0xffff) == PTRACE_EVENT_CLONE) { if(ptrace(PTRACE_GETEVENTMSG, child_waited, 0, &new_child) != -1) { allThreads.insert(new_child); ptrace(PTRACE_CONT, new_child, 0, 0); printf("\nchild %d created\t", new_child); } ptrace(PTRACE_CONT, child_waited, 0, 0); continue; } } if(WIFEXITED(status)) { allThreads.erase(child_waited); printf("\nchild %d exited with status %d\t", child_waited, WEXITSTATUS(status)); if(allThreads.size() == 0) break; } else if(WIFSIGNALED(status)) { allThreads.erase(child_waited); printf("\nchild %d killed by signal %d\t", child_waited, WTERMSIG(status)); if(allThreads.size() == 0) break; } else if(WIFSTOPPED(status)) { int stopCode = WSTOPSIG(status); if(stopCode == SIGTRAP) { ptrace(PTRACE_GETREGS, child_waited, NULL, &regs); unsigned long currentEip = regs.eip; //printf("%d\t%08x\n", child_waited, currentEip); Address_Bytes_Map::iterator iter = m_bytesBackup.find(currentEip - 1); if(iter != m_bytesBackup.end()) { iter->second->m_result = true; regs.eip = regs.eip - 1; getData(child_waited, regs.eip, trapCode, 4); trapCode[0] = iter->second->m_char; putData(child_waited, regs.eip, trapCode, 4); rec = ptrace(PTRACE_SETREGS, child_waited, NULL, &regs); } } } rec = ptrace(PTRACE_CONT, child_waited, 1, NULL); continue; }