Fun with DTrace in destructive mode

Most people use DTrace to see what their system is actually doing. What functions or systemcalls are being executed, what is my process doing, where is most time spent, etc. The possibilities are endless and DTrace is such an awesome tool that I just can’t stop talking about it.

Not everyone might know that DTrace is not only able to trace your system and applications, but it can also change memory on the fly. I knew this from the beginning but actually never took the time to dig into this, until now.

While reading DTrace’s documentation about copyout and copyoutstr it became immediately clear to me that this means even more fun! Extending the, already endless, possibilities.

Imagine the following example:

    open64("/etc/vfstab", O_RDONLY);

The open64 systemcall takes 2 arguments: arg0 and arg1, where arg0 is a const char pointing to a file and arg1 is the flag that specifies the access mode, in this example readonly.

We can easially dtrace all processes that are calling open64 and print arg0 and arg1:

    syscall::open64:entry
    {
        printf("%s: %s %i", execname, copyinstr(arg0), arg1);
    }

which will show something like:

    dtrace: description 'syscall::open64:entry ' matched 1 probe
    CPU ID    FUNCTION:NAME
      1 16560 open64:entry cron: /system/contract/process/template 2
      1 16560 open64:entry cron: /var/adm/lastlog 258
      1 16560 open64:entry cron: /dev/null 0
      1 16560 open64:entry cron: /tmp/croutUSLV2gaKT 1281
      3 16560 open64:entry cron: /system/contract/process/latest 0
      3 16560 open64:entry cron: /system/contract/all/117346/ctl 1
      0 16560 open64:entry cron: /system/contract/process/latest 0
      0 16560 open64:entry cron: /system/contract/all/117347/ctl 1
      2 16560 open64:entry cat: /etc/vfstab 0
      0 16560 open64:entry cron: /system/contract/process/template 2
      0 16560 open64:entry cron: /system/contract/process/latest 0

There is a cat process showing up with /etc/vfstab as arg0, and 0 (O_RDONLY) as arg1. Wouldn’t it be awesome if we could change arg0 into something different, like /etc/hosts, on the fly?

It’s quite simple to do this with DTrace. We only need to run DTrace in destructive mode (be carefull !!) and to use copyout to rewrite arg0:

    #pragma D option destructive

    syscall::open64:entry
    /execname == "cat" && copyinstr(arg0) == "/etc/vfstab"/
    {
        this->f="/etc/hosts";
        copyout(this->f, arg0, sizeof(this->f) + 1);
    }

It’s important to keep in mind that the size of /etc/hosts is smaller than /etc/vfstab. Writing data that doesn’t fit in the application buffer is dangerous!

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *