首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >未声明的PTRACE_GET_SYSCALL_INFO :包括sys/ptrace.h似乎没有得到所有的ptrace

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

Stack Overflow用户
提问于 2019-12-30 23:50:41
回答 1查看 1.1K关注 0票数 1

从手册页:

PTRACE_GET_SYSCALL_INFO (自Linux5.3以来)

检索导致停止的系统调用的信息。该信息被放置到数据参数所指向的缓冲区中,该缓冲区应该是一个指向结构ptrace_syscall_info类型缓冲区的指针。addr参数包含数据参数所指向的缓冲区的大小(即size of (Struct ptrace_syscall_info))。返回值包含内核可以写入的字节数。如果要由内核写入的数据的大小超过addr参数指定的大小,则输出数据将被截断。

代码语言:javascript
复制
>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

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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);
}

考虑到所有因素,我的代码应该正常运行,不会出现错误,但似乎实际上并没有包含PTRACE_GET_SYSCALL_INFO内容,正如gcc抱怨的那样:

代码语言:javascript
复制
>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手册页的顶部写着:

代码语言:javascript
复制
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
            void *addr, void *data);`

所以我本以为这个单曲就足够了,但它不起作用。

提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2019-12-30 23:58:08

这是因为glibc并不是所有最新Linux特性的最新版本。你可以用#include <linux/ptrace.h>#include <sys/ptrace.h>来得到PTRACE_GET_SYSCALL_INFO

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59538074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档