简体   繁体   English

PTRACE_GET_SYSCALL_INFO 未声明:包括 sys/ptrace.h 似乎没有得到所有的 ptrace 代码

[英]PTRACE_GET_SYSCALL_INFO undeclared: including sys/ptrace.h doesn't seem to get all ptrace code

From the man page:从手册页:

PTRACE_GET_SYSCALL_INFO (since Linux 5.3) PTRACE_GET_SYSCALL_INFO(从 Linux 5.3 开始)

Retrieve information about the system call that caused the stop.检索有关导致停止的系统调用的信息。 The information is placed into the buffer pointed by the data argument, which should be a pointer to a buffer of type struct ptrace_syscall_info.信息被放置在数据参数指向的缓冲区中,该缓冲区应该是指向 struct ptrace_syscall_info 类型缓冲区的指针。 The addr argument contains the size of the buffer pointed to by the data argument (ie, sizeof(struct ptrace_syscall_info)). addr 参数包含 data 参数指向的缓冲区的大小(即 sizeof(struct ptrace_syscall_info))。 The return value contains the number of bytes available to be written by the kernel.返回值包含内核可写入的字节数。 If the size of the data to be written by the kernel exceeds the size specified by the addr argument, the output data is truncated.如果内核要写入的数据大小超过 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)
>

Now, I have this small program I've written, consisting of two files.现在,我编写了这个小程序,它由两个文件组成。

helpers.h 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);
}

#endif

tracetest.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, &regs),
            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);
}

All things considered, my code should run normally without errors, but it seems like the PTRACE_GET_SYSCALL_INFO stuff isn't actually included, as gcc is complaining:考虑到所有因素,我的代码应该正常运行而不会出错,但似乎 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),
      |                                                ^~~~~~

However, if I #include <linux/ptrace.h> , then I don't get these errors, but instead it says implicit declaration of function ptrace.h, which to be honest I think isn't very good either.但是,如果我#include <linux/ptrace.h> ,那么我不会收到这些错误,而是显示函数 ptrace.h 的隐式声明,老实说,我认为这也不是很好。

What am I supposed to be including to make this function as intended?我应该包括什么才能使这个功能按预期进行? I also included sys/types.h , but I'm still getting errors about __u8 being an unknown type name, but it's a type used in the ptrace.c source code, so it shouldn't be throwing any errors.我还包含了sys/types.h ,但我仍然收到关于__u8是未知类型名称的错误,但它是 ptrace.c 源代码中使用的类型,所以它不应该抛出任何错误。

The top of the ptrace man page says: ptrace 手册页的顶部说:

#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
            void *addr, void *data);`

So I would have thought this single include would be enough, but it's not working.所以我会认为这个单一的包含就足够了,但它不起作用。

Thanks in advance.提前致谢。

This is because glibc is not fully up-to-date on all the latest Linux features.这是因为 glibc 并没有完全更新所有最新的 Linux 功能。 You can #include <linux/ptrace.h> and #include <sys/ptrace.h> to get PTRACE_GET_SYSCALL_INFO .您可以#include <linux/ptrace.h>#include <sys/ptrace.h>来获取PTRACE_GET_SYSCALL_INFO

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM