Wednesday, October 19, 2011

Using ptrace()'s GETREGSET on x86

Using ptrace()'s GETREGSET on x86

The following program shows how to obtain a snapshot of register values on x86 machine using ptrace()'s GETREGSET command.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <elf.h>

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <linux/ptrace.h>

const char *str = "linux is awesome\n";

struct iovec {
        void *iov_base;
        unsigned int iov_len;
};

struct user_regs_struct32 {
        __u32 ebx, ecx, edx, esi, edi, ebp, eax;
        unsigned short ds, __ds, es, __es;
        unsigned short fs, __fs, gs, __gs;
        __u32 orig_eax, eip;
        unsigned short cs, __cs;
        __u32 eflags, esp;
        unsigned short ss, __ss;
};

int main(void)
{
        struct user_regs_struct32 uregs;
        struct iovec iov;
        pid_t c_pid, w_pid;
        int status;
        long ret;

        switch (c_pid = fork()) {
        case -1:
                perror("fork");
                exit(1);
                break;

        case 0:
                ret = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
                if (ret == -1) {
                        perror("ptrace");
                        exit(1);
                }

                raise(SIGUSR1);

                write(1, str, strlen(str));

                printf("Child process exiting.\n");

                exit(0);

                break;

        default:
                break;
        }

        /* Parent's code */
        w_pid = wait(&status);
        if (w_pid == -1) {
                perror("wait");
                goto out1;
        }

        ret = ptrace(PTRACE_SYSCALL, c_pid, NULL, NULL);
        if (ret == -1) {
                perror("ptrace");
                goto out1;
        }

        w_pid = wait(&status);
        if (w_pid == -1) {
                perror("wait");
                goto out1;
        }

        memset(&uregs, 0, sizeof(uregs));

        iov.iov_len = sizeof(uregs);
        iov.iov_base = &uregs;
        ret = ptrace(PTRACE_GETREGSET, c_pid, NT_PRSTATUS, &iov);
        if (ret == -1) {
                perror("ret");
                goto out1;
        }

        printf("uregs.orig_eax = %u.\n", uregs.orig_eax);

        exit(0);
out1:
        exit(1);
}

HTML generated by org-mode 7.3 in emacs 23

No comments:

Post a Comment