当所需的系统调用在父进程中恢复时,Ptrace选项不会设置正确的状态。我只能使用在这里看到的没有PEEKUSER,SYSGOOD或SYSCALL。在过去的几天里,我已经读过这篇文章,并寻找了一些例子,我精神上精疲力竭。
任何想法/建议,无论多小,都是受欢迎的。谢谢。
论点:/bin/bash -c "echo 'first test' | wc -c"
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
int wait_for_syscall(pid_t child) {
int status;
while (1) {
ptrace(PTRACE_CONT, child, 0, 0);
waitpid(child, &status, 0);
if (WIFSTOPPED(status) && WSTOPSIG(status) | 0x80)
return 0;
if (WIFEXITED(status))
return 1;
}
}
int main(int argc, char *argv[]) {
int status;
int counter = 0;
pid_t pid = fork();
if (pid < 0)
exit(1);
else if (pid == 0) {
ptrace(PTRACE_TRACEME, pid, NULL, NULL);
raise(SIGSTOP);
return execve(argv[1], &argv[1], NULL);
} else {
wait(&status);
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL | PTRACE_O_TRACEEXEC | PTRACE_O_TRACESECCOMP);
while (1) {
if (wait_for_syscall(pid) != 0) break;
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8)))
counter++;
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8)))
counter++;
if (wait_for_syscall(pid) != 0) break;
}
}
return 0;
}
发布于 2022-06-14 08:32:17
在主循环中,使用范围为status
的main
。
这不是您在wait_for_syscall
中设置的相同的wait_for_syscall
(它有自己的status
的私有副本)。
因此,status
in main
从未更新过。
要修复,可以传递指向wait_for_syscall
的指针
我保留了它的原样,但我相信循环中对wait_for_syscall
的第二个调用是无关的,实际上可能会悄悄地吸收syscall。
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
int
wait_for_syscall(pid_t child,int *stp)
{
int status;
while (1) {
ptrace(PTRACE_CONT, child, 0, 0);
waitpid(child, &status, 0);
*stp = status;
if (WIFSTOPPED(status) && WSTOPSIG(status) | 0x80)
return 0;
if (WIFEXITED(status))
return 1;
}
}
int
main(int argc, char *argv[])
{
int status;
int counter = 0;
pid_t pid = fork();
if (pid < 0)
exit(1);
if (pid == 0) {
ptrace(PTRACE_TRACEME, pid, NULL, NULL);
raise(SIGSTOP);
return execve(argv[1], &argv[1], NULL);
}
wait(&status);
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL | PTRACE_O_TRACEEXEC | PTRACE_O_TRACESECCOMP | PTRACE_O_TRACECLONE);
while (1) {
if (wait_for_syscall(pid,&status) != 0)
break;
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8)))
counter++;
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8)))
counter++;
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8)))
counter++;
if (wait_for_syscall(pid,&status) != 0)
break;
}
return 0;
}
更新:
我明白了。它关闭bc,现在它只进行一次迭代,然后就停止了。所以它不会继续/转到下一个系统调用。:( - Olivia22
好吧,我玩过一些变奏曲。以下是一些变化:
除了
PTRACE_O_TRACEFORK
之外,还需要PTRACE_O_TRACECLONE
(这是一件大事;-)PATH
)
execvp
来保存环境变量(例如,
waitpid
应该为pid获取-1
以捕获子节点,等等,。
我添加了调试打印(dbgprt
)
ptrace(PTRACE_CONT,...)
的
signo
下面是重构代码(包含大量调试):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#define SHOW(_sym) \
dbgprt(#_sym ": %8.8X %8.8X\n",_sym,SIGTRAP | (_sym << 8))
#define dbgprt(_fmt...) \
do { \
int sverr = errno; \
printf(_fmt); \
errno = sverr; \
} while (0)
#define ONERR(_expr) \
do { \
if (! (_expr)) \
break; \
dbgprt("ONERR " #_expr " line %d -- %s\n",__LINE__,strerror(errno)); \
exit(1); \
} while (0)
int
main(int argc, char *argv[])
{
int status;
int counter = 0;
long err;
pid_t pidm = getpid();
pid_t pid0 = fork();
if (pid0 < 0)
exit(1);
if (pid0 == 0) {
ptrace(PTRACE_TRACEME, pid0, NULL, NULL);
//raise(SIGSTOP);
#if 0
execve(argv[1], &argv[1], NULL);
#else
execvp(argv[1], &argv[1]);
#endif
exit(97);
}
dbgprt("main: pid0=%d/%d\n",pid0,pid0 - pidm);
dbgprt("main: SIGSTOP %d\n",SIGSTOP);
dbgprt("main: SIGTRAP %d\n",SIGTRAP);
SHOW(PTRACE_EVENT_EXEC);
SHOW(PTRACE_EVENT_SECCOMP);
SHOW(PTRACE_EVENT_CLONE);
#if 0
err = ptrace(PTRACE_ATTACH,pid0,0,0);
ONERR(err < 0);
#endif
err = waitpid(-1,&status,0);
ONERR(err < 0);
#if 1
unsigned int opt = 0;
opt |= PTRACE_O_EXITKILL;
opt |= PTRACE_O_TRACEEXEC;
opt |= PTRACE_O_TRACESECCOMP;
opt |= PTRACE_O_TRACECLONE;
opt |= PTRACE_O_TRACEFORK;
err = ptrace(PTRACE_SETOPTIONS, pid0, 0, opt);
ONERR(err < 0);
#endif
err = ptrace(PTRACE_CONT,pid0,0,0);
ONERR(err < 0);
while (1) {
#if 1
pid_t pid = waitpid(-1, &status, 0);
#else
pid_t pid = wait(&status);
#endif
unsigned int evmsk = status >> 16;
dbgprt("waitpid: pid=%d/%d status=%8.8X\n",pid,pid - pidm,status);
dbgprt("waitpid: status %8.8X %8.8X evmsk=%8.8X\n",
status >> 8,status & 0x7F,evmsk);
if (pid < 0) {
dbgprt("waitpid: errno=%d -- %s\n",errno,strerror(errno));
break;
}
if (WIFEXITED(status)) {
dbgprt("waitpid: WIFEXITED code=%d\n",WEXITSTATUS(status));
continue;
}
int signo = 0;
do {
if (WIFSTOPPED(status)) {
signo = WSTOPSIG(status);
dbgprt("waitpid: WIFSTOPPED signo=%d\n",signo);
}
if (WIFSIGNALED(status)) {
signo = WTERMSIG(status);
dbgprt("waitpid: WIFSIGNALED signo=%d\n",signo);
}
} while (0);
#if 0
if (WIFSTOPPED(status) && WSTOPSIG(status) | 0x80)
return 0;
if (WIFEXITED(status))
return 1;
#endif
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8))) {
dbgprt("EXEC\n");
counter++;
}
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) {
dbgprt("SECCOMP\n");
counter++;
}
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8))) {
dbgprt("CLONE\n");
counter++;
}
dbgprt("main: counter=%d\n",counter);
err = ptrace(PTRACE_CONT, pid, 0, signo);
ONERR(err < 0);
}
return 0;
}
下面是程序调用和输出:
+ ./fix3 /bin/bash -c 'cat /bin/bash | wc -c'
main: pid0=1905216/1
main: SIGSTOP 19
main: SIGTRAP 5
PTRACE_EVENT_EXEC: 00000004 00000405
PTRACE_EVENT_SECCOMP: 00000007 00000705
PTRACE_EVENT_CLONE: 00000003 00000305
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=0
waitpid: pid=1905217/2 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905217/2 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905217/2 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=0
waitpid: pid=1905218/3 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905218/3 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905218/3 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=0
waitpid: pid=1905219/4 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905219/4 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905220/5 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905219/4 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=0
waitpid: pid=1905220/5 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=0
waitpid: pid=1905219/4 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=0
waitpid: pid=1905220/5 status=0004057F
waitpid: status 00000405 0000007F evmsk=00000004
waitpid: WIFSTOPPED signo=5
EXEC
main: counter=1
waitpid: pid=1905220/5 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905219/4 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=1
waitpid: pid=1905219/4 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=1
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=1
waitpid: pid=1905221/6 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=1
waitpid: pid=1905221/6 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=1
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=1
waitpid: pid=1905221/6 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=1
waitpid: pid=191190216
05222/7 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=1
waitpid: pid=1905222/7 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=1
waitpid: pid=1905221/6 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=1
waitpid: pid=1905222/7 status=0004057F
waitpid: status 00000405 0000007F evmsk=00000004
waitpid: WIFSTOPPED signo=5
EXEC
main: counter=2
waitpid: pid=1905222/7 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905221/6 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=2
waitpid: pid=1905221/6 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=2
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=2
waitpid: pid=1905223/8 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=2
waitpid: pid=1905223/8 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=2
waitpid: pid=1905216/1 status=0001057F
waitpid: status 00000105 0000007F evmsk=00000001
waitpid: WIFSTOPPED signo=5
main: counter=2
waitpid: pid=1905224/9 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=2
waitpid: pid=1905224/9 status=0000137F
waitpid: status 00000013 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=19
main: counter=2
waitpid: pid=1905223/8 status=0004057F
waitpid: status 00000405 0000007F evmsk=00000004
waitpid: WIFSTOPPED signo=5
EXEC
main: counter=3
waitpid: pid=1905224/9 status=0004057F
waitpid: status 00000405 0000007F evmsk=00000004
waitpid: WIFSTOPPED signo=5
EXEC
main: counter=4
waitpid: pid=1905223/8 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905224/9 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=1905216/1 status=0000117F
waitpid: status 00000011 0000007F evmsk=00000000
waitpid: WIFSTOPPED signo=17
main: counter=4
waitpid: pid=1905216/1 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: WIFEXITED code=0
waitpid: pid=-1/-1905216 status=00000000
waitpid: status 00000000 00000000 evmsk=00000000
waitpid: errno=10 -- No child processes
更新2:
非常感谢,我会去研究它,看看它是如何工作的。如果0和1在这里意味着什么呢?- Olivia22
为了在这里进行说明,我使用cpp
条件来表示旧代码和新代码:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
有时,我会输入一些实验代码,但结果会是“不太好”。所以,我将把它包装在一个#if 0
中。我将保留它一段时间,以提醒自己,我做了,但它没有工作(例如,PTRACE_ATTACH
块)。
条件词是“注释掉”代码的快速方法,它比使用(例如)更干净。/*
和*/
对。
当我完成并且我认为代码是最终的,我将删除适当的条件。
一种简单的方法是通过unifdef -k
运行代码(我们得到):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#define SHOW(_sym) \
dbgprt(#_sym ": %8.8X %8.8X\n",_sym,SIGTRAP | (_sym << 8))
#define dbgprt(_fmt...) \
do { \
int sverr = errno; \
printf(_fmt); \
errno = sverr; \
} while (0)
#define ONERR(_expr) \
do { \
if (! (_expr)) \
break; \
dbgprt("ONERR " #_expr " line %d -- %s\n",__LINE__,strerror(errno)); \
exit(1); \
} while (0)
int
main(int argc, char *argv[])
{
int status;
int counter = 0;
long err;
pid_t pidm = getpid();
pid_t pid0 = fork();
if (pid0 < 0)
exit(1);
if (pid0 == 0) {
ptrace(PTRACE_TRACEME, pid0, NULL, NULL);
//raise(SIGSTOP);
execvp(argv[1], &argv[1]);
exit(97);
}
dbgprt("main: pid0=%d/%d\n",pid0,pid0 - pidm);
dbgprt("main: SIGSTOP %d\n",SIGSTOP);
dbgprt("main: SIGTRAP %d\n",SIGTRAP);
SHOW(PTRACE_EVENT_EXEC);
SHOW(PTRACE_EVENT_SECCOMP);
SHOW(PTRACE_EVENT_CLONE);
err = waitpid(-1,&status,0);
ONERR(err < 0);
unsigned int opt = 0;
opt |= PTRACE_O_EXITKILL;
opt |= PTRACE_O_TRACEEXEC;
opt |= PTRACE_O_TRACESECCOMP;
opt |= PTRACE_O_TRACECLONE;
opt |= PTRACE_O_TRACEFORK;
err = ptrace(PTRACE_SETOPTIONS, pid0, 0, opt);
ONERR(err < 0);
err = ptrace(PTRACE_CONT,pid0,0,0);
ONERR(err < 0);
while (1) {
pid_t pid = waitpid(-1, &status, 0);
unsigned int evmsk = status >> 16;
dbgprt("waitpid: pid=%d/%d status=%8.8X\n",pid,pid - pidm,status);
dbgprt("waitpid: status %8.8X %8.8X evmsk=%8.8X\n",
status >> 8,status & 0x7F,evmsk);
if (pid < 0) {
dbgprt("waitpid: errno=%d -- %s\n",errno,strerror(errno));
break;
}
if (WIFEXITED(status)) {
dbgprt("waitpid: WIFEXITED code=%d\n",WEXITSTATUS(status));
continue;
}
int signo = 0;
do {
if (WIFSTOPPED(status)) {
signo = WSTOPSIG(status);
dbgprt("waitpid: WIFSTOPPED signo=%d\n",signo);
}
if (WIFSIGNALED(status)) {
signo = WTERMSIG(status);
dbgprt("waitpid: WIFSIGNALED signo=%d\n",signo);
}
} while (0);
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8))) {
dbgprt("EXEC\n");
counter++;
}
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) {
dbgprt("SECCOMP\n");
counter++;
}
if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8))) {
dbgprt("CLONE\n");
counter++;
}
dbgprt("main: counter=%d\n",counter);
err = ptrace(PTRACE_CONT, pid, 0, signo);
ONERR(err < 0);
}
return 0;
}
https://stackoverflow.com/questions/72620023
复制相似问题