Tag Archives: ptrace

Ptrace IV.

This blogpost has first been published in my old blog at spin.

This code uses the ptrace debug interface to attach to a process wait for a write syscall and replace the word “windows” with “*******”.


#include <stdio.h>
#include <string.h>
#include <sys/ptrace.h>
#include <asm/ptrace-abi.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <unistd.h>
#include <bits/wordsize.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
    pid_t pid;
    int i;

    struct user_regs_struct regs;

    union u
    {
        long val;
        char str[sizeof(long)+1];
    } data;

    union u olddata;

    union uu
    {
        struct
        {
            long v1;
            long v2;
        } val;
        char str[(2*sizeof(long))+1];
    } ldata;

    char *winstring;

    printf("wordsize: %d\n", __WORDSIZE);

    printf("pid: ");
    scanf("%d", &pid);

    printf("connecting to %d\n", pid);

    ptrace(PTRACE_ATTACH, pid, NULL, NULL);
    perror("connect");
    getchar();

    while (regs.orig_rax != 0xe7)
    {
        wait(NULL);

        ptrace(PTRACE_GETREGS, pid, NULL, &regs);

        switch (regs.orig_rax)
        {
            case 0:
                printf("read-");
                break;
            case 1:
                printf("write-");
                break;
            case 2:
                printf("open-");
                break;
            case 3:
                printf("close-");
                break;
        }

        if (regs.orig_rax != -1)
        {
            printf("syscall: 0x%lx 0x%lx 0x%lx 0x%lx => 0x%lx\n",
                    regs.orig_rax, regs.rbx, regs.rcx, regs.rdx,
                    regs.rax);
            printf("\t rdi: 0x%lx rsi: 0x%lx\n", regs.rdi, regs.rsi);
        }

        if (regs.orig_rax == 1)
        {
            //printf("txt: ");
            data.val = 0;

            for (i = 0; i < regs.rdx; i+=sizeof(long))
            {
                olddata.val = data.val;

                data.val = ptrace(PTRACE_PEEKDATA, pid, regs.
                        rsi+i, NULL);
                if (i == 0)
                    data.str[regs.rdx] = '\0';
                else
                    data.str[sizeof(long)] = '\0';
                //printf("%s", data.str);

                if (olddata.val != 0)
                {
                    ldata.val.v1 = olddata.val;
                    ldata.val.v2 = data.val;

                    printf("ldata.str: %s\n", ldata.str);

                    winstring = strstr(ldata.str, "windows");

                    if (winstring != NULL)
                    {
                        strncpy(winstring, "*******", 7);
                        printf("new-ldata.str: %s\n", ldata.str);
                        ptrace(PTRACE_POKEDATA, pid, regs.rsi, ldata.val.v1);
                        ptrace(PTRACE_POKEDATA, pid, regs.rsi+sizeof(long), ldata.val.v2);
                        i+=sizeof(long);
                    }
                }

            }

            printf("\n");

        }

        //printf("cont ...\n");
        //getchar();

        ptrace(PTRACE_SYSCALL, pid, 1, 0);

    }

    ptrace(PTRACE_CONT, pid, NULL, NULL);
    ptrace(PTRACE_DETACH, pid, NULL, NULL);

    return 0;
}

“0xe7” is the syscall for exit; so it quits instructing the process when that process exits.

A simple program for testing purposes:

#include <stdio.h>

int main()
{
        while (1)
        {
                printf("   windows   \n");
                sleep(1);
        }

}