从手册页:
PTRACE_GET_SYSCALL_INFO (自Linux5.3以来)
检索导致停止的系统调用的信息。该信息被放置到数据参数所指向的缓冲区中,该缓冲区应该是一个指向结构ptrace_syscall_info类型缓冲区的指针。addr参数包含数据参数所指向的缓冲区的大小(即size of (Struct ptrace_syscall_info))。返回值包含内核可以写入的字节数。如果要由内核写入的数据的大小超过addr参数指定的大小,则输出数据将被截断。
>cat /proc/version
Linux version 5.3.0-kali2-amd64 (devel@kali.org) (gcc version 9.2.1 20191109 (Debian 9.2.1-19)) #1 SMP Debian 5.3.9-3kali1 (2019-11-20)
>现在,我已经编写了一个小程序,由两个文件组成。
helpers.h
#ifndef HELPERS
#define HELPERS
//helpers.h
#include <errno.h>
#include <sys/ptrace.h>
#include <sys/types.h>
const char* op_to_string(__u8 op)
{
switch (op) {
case (PTRACE_SYSCALL_INFO_ENTRY):
return "SYSCALL_INFO_ENTRY";
break;
case (PTRACE_SYSCALL_INFO_EXIT):
return "SYSCALL_INFO_EXIT";
break;
case (PTRACE_SYSCALL_INFO_SECCOMP):
return "SYSCALL_INFO_SECCOMP";
break;
default:
fprintf(stderr, "op-to-string: Invalid op code");
}
}
void err_wrap(const int ret, const int success, const char *msg)
{
if (ret != success)
{
perror(msg);
}
}
void print_regs(const struct user_regs_struct regs) {
printf ("r15: %16llx %30s\n", regs.r15, "general purpose registers");
printf ("r14: %16llx\n", regs.r14);
printf ("r13: %16llx\n", regs.r13);
printf ("r12: %16llx\n", regs.r12);
printf ("rbp: %16llx\n", regs.rbp);
printf ("rbx: %16llx\n", regs.rbx);
printf ("r11: %16llx\n", regs.r11);
printf ("r10: %16llx\n", regs.r10);
printf ("r9: %16llx %s\n", regs.r9, "6.");
printf ("r8: %16llx %s\n", regs.r8, "5.");
printf ("rax: %16llx\n", regs.rax);
printf ("rcx: %16llx %s\n", regs.rcx, "4.");
printf ("rdx: %16llx %s\n", regs.rdx, "3.");
printf ("rsi: %16llx %s\n", regs.rsi, "2.");
printf ("rdi: %16llx %30s\n", regs.rdi, "1. function/syscall argument"); // aka "parameter registers"
printf ("orig_rax:%16llx\n", regs.orig_rax);
printf ("rip: %16llx %30s\n", regs.rip, "instruction pointer");
printf ("cs: %16llx\n", regs.cs);
printf ("eflags: %16llx\n", regs.eflags);
printf ("rsp: %16llx %30s\n", regs.rsp, " Stack Pointer (current location in stack)");
printf ("ss: %16llx\n", regs.ss);
printf ("fs_base: %16llx\n", regs.fs_base);
printf ("gs_base: %16llx\n", regs.gs_base);
printf ("ds: %16llx\n", regs.ds);
printf ("es: %16llx\n", regs.es);
printf ("fs: %16llx\n", regs.fs);
printf ("gs: %16llx\n", regs.gs);
}
void print_syscall_info(struct ptrace_syscall_info sys_info) {
__u8 op = sys_info.op;
printf("Type of system call stop: %20s (%x)\n", op_to_string(op), op);
printf("Arch: %16llx\n", sys_info.arch);
}
#endiftracetest.c
#include <stdio.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <sys/user.h>
#include <syscall.h>
#include "helpers.h"
// long ptrace(enum __ptrace_request request, pid_t pid,
// void *addr, void *data);
void child_code();
void parent_code(pid_t pid);
int main(const int argc, char *argv[])
{
pid_t pid;
switch (pid = fork())
{
case -1:
perror("fork");
break;
case 0:
child_code();
break;
default: //parent code
parent_code(pid);
}
return 0;
}
void parent_code(pid_t pid)
{
printf("Parent code\n");
int status;
if (wait(&status) == -1)
{
perror("parent wait one");
}
printf("Finished waiting\n");
printf("PID wait status is: %llx\n", status);
printf("My PID is %d\n", getpid());
err_wrap(
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL),
0, "ptrace-set-options");
struct user_regs_struct regs;
struct ptrace_syscall_info syscall_info;
while(1)
{
err_wrap(ptrace(PTRACE_SYSCALL, pid, 0, 0), 0, "ptrace-syscall first"); //Stop at next syscall.
if (wait(&status) == -1)
{
perror("parent wait one");
}
printf("syscall-entry-stop\n");
err_wrap(
ptrace(PTRACE_GET_SYSCALL_INFO, pid, sizeof(struct ptrace_syscall_info), &syscall_info),
0, "ptrace-get-syscall-info");
err_wrap(
ptrace(PTRACE_GETREGS, pid, 0, ®s),
0,
"ptrace-getregs");
print_regs(regs);
print_syscall_info(syscall_info);
}
}
void child_code() {
printf("Child code\n");
printf("Parent is: %d\n", getppid());
err_wrap(ptrace(PTRACE_TRACEME, 0,0,0), 0, "ptrace-traceme");
err_wrap(raise(SIGSTOP), 0, "raise");
unsigned int pleb = 0xffbbcde8;
int x = 0;
printf("Hello WoRld\n");
printf("Pleb is: %llx\n", pleb);
printf("x is: %d\n", x);
}考虑到所有因素,我的代码应该正常运行,不会出现错误,但似乎实际上并没有包含PTRACE_GET_SYSCALL_INFO内容,正如gcc抱怨的那样:
>gcc -g -o tracetest tracetest.c
In file included from tracetest.c:10:
helpers.h:9:26: error: unknown type name ‘__u8’
9 | const char* op_to_string(__u8 op)
| ^~~~
helpers.h:72:32: warning: ‘struct ptrace_syscall_info’ declared inside parameter list will not be visible outside of this definition or declaration
72 | void print_syscall_info(struct ptrace_syscall_info sys_info) {
| ^~~~~~~~~~~~~~~~~~~
helpers.h:72:52: error: parameter 1 (‘sys_info’) has incomplete type
72 | void print_syscall_info(struct ptrace_syscall_info sys_info) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
helpers.h: In function ‘print_syscall_info’:
helpers.h:73:2: error: unknown type name ‘__u8’
73 | __u8 op = sys_info.op;
| ^~~~
helpers.h:74:54: warning: implicit declaration of function ‘op_to_string’ [-Wimplicit-function-declaration]
74 | printf("Type of system call stop: %20s (%x)\n", op_to_string(op), op);
| ^~~~~~~~~~~~
tracetest.c: In function ‘parent_code’:
tracetest.c:55:29: error: storage size of ‘syscall_info’ isn’t known
55 | struct ptrace_syscall_info syscall_info;
| ^~~~~~~~~~~~
tracetest.c:66:11: error: ‘PTRACE_GET_SYSCALL_INFO’ undeclared (first use in this function); did you mean ‘PTRACE_GETSIGINFO’?
66 | ptrace(PTRACE_GET_SYSCALL_INFO, pid, sizeof(struct ptrace_syscall_info), &syscall_info),
| ^~~~~~~~~~~~~~~~~~~~~~~
| PTRACE_GETSIGINFO
tracetest.c:66:11: note: each undeclared identifier is reported only once for each function it appears in
tracetest.c:66:48: error: invalid application of ‘sizeof’ to incomplete type ‘struct ptrace_syscall_info’
66 | ptrace(PTRACE_GET_SYSCALL_INFO, pid, sizeof(struct ptrace_syscall_info), &syscall_info),
| ^~~~~~但是,如果我是#include <linux/ptrace.h>,那么我不会得到这些错误,相反,它表示函数ptrace.h的隐式声明,老实说,我认为这也不是很好。
我应该包括什么来使这个函数像预期的那样?我也包含了sys/types.h,但是我仍然会收到关于__u8是一个未知类型名称的错误,但是它是ptrace.c源代码中使用的类型,所以它不应该抛出任何错误。
ptrace手册页的顶部写着:
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
void *addr, void *data);`所以我本以为这个单曲就足够了,但它不起作用。
提前谢谢。
发布于 2019-12-30 23:58:08
这是因为glibc并不是所有最新Linux特性的最新版本。你可以用#include <linux/ptrace.h>和#include <sys/ptrace.h>来得到PTRACE_GET_SYSCALL_INFO。
https://stackoverflow.com/questions/59538074
复制相似问题