最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

linux - How can I track process creation using ptrace in C and ensure only one child process is allowed? - Stack Overflow

programmeradmin3浏览0评论

I'm trying to use ptrace.h to track the creation of new processes in a binary. My intent is to only allow the creation of a single process (that in the future I will also track what it can write).

To monitor the program, I wrote the following code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <sys/syscall.h>

int main(int argc, char **argv)
{
    if (argc != 2)  {
        return 1;
    }

    struct user_regs_struct regs;
    int pid_parent = fork(), status_pai;
    char buffer_pai[0x1000];
    int pid_child = -1, status_filho;
    char buffer_filho[0x1000];
    int current_pid = - 1, new_pid, current_status, new_status;

    if (pid_parent == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execl(argv[1], argv[1], NULL);
    }

    waitpid(pid_parent, &status_pai, 0);

    // Track all kinds of clone
    ptrace(PTRACE_SETOPTIONS, pid_parent, 0, 
           PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | 
           PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC);
    
    ptrace(PTRACE_SYSCALL, pid_parent, 0, 0);

    int flag_fork = 1, pending_exits = 1;
    while (pending_exits) {
        current_pid = waitpid(-1, &current_status, __WALL);

        if (WIFEXITED(current_status) || WIFSIGNALED(current_status)) {
            pending_exits--;
            continue;
        }

        if (current_status >> 8 == (SIGTRAP | (PTRACE_EVENT_FORK << 8)) ||
            current_status >> 8 == (SIGTRAP | (PTRACE_EVENT_VFORK << 8)) ||
            current_status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8))) {
            
            ptrace(PTRACE_GETEVENTMSG, current_pid, 0, &new_pid);
            printf("\nParent pid: %d - Child pid: %d\n", pid_parent, pid_child);
            printf("Current pid: %d - New pid: %d\n", current_pid, new_pid);

            if (current_pid == pid_parent) {
                if ((new_pid != pid_parent) && (flag_fork)) {
                    pid_child = new_pid;
                    pending_exits++;
                    flag_fork = 0;          // Parent can fork only once
                    puts("Parent forked for the first time.");
                } else if ((new_pid != pid_parent) && (new_pid != pid_child) && (!flag_fork)) {
                    puts("Parent tried to fork again.");
                    exit(1);
                } else {
                    puts("Weird situation with parent.");
                    exit(1);
                }
            } else if (current_pid == pid_child) {
                if (new_pid != pid_child) {
                    puts("Child can not fork.");
                    exit(1);
                } else {
                    puts("Weird situation with child.");
                    exit(1);
                }
            }
        }
            
        if (pending_exits > 2) {
            puts("Fork overflow");
            exit(1);
        }

        ptrace(PTRACE_SYSCALL, current_pid, 0, 0);

    }

    return 0;

}

The program that I used to test is the following:

#include <stdio.h>
#include <unistd.h>

int main() {

    if (!fork()) {
        fork();
    }
    return 0;
}

In this case, after the parent fork, the child only will fork too. When I run this program tracking with the first one, I got the following output:

[1337] j3r3mias@serenity > ./tracker example

Parent pid: 2605006 - Child pid: 0
Current pid: 2605006 - New pid: 2605007
Parent forked for the first time.

Parent pid: 2605006 - Child pid: 0
Current pid: 2605007 - New pid: 2605008

The problem with the tracker is that pid_child even after being updated after the parent fork, shows the value 0 in the second interaction of the while. Are the any differences in the state of the program when using ptrace?

Some complementary infos about the environment I'm running theses tests:

  • OS: Ubuntu 24.04
  • Compiler: gcc 13.3.0
  • GLIBC 2.39-0ubuntu8.4
  • Kernel version: 5.15.167

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论