Archive of

Fun with DTrace in destructive mode

Posted on March 21, 2012 by disharmony 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 copy out 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!