Cipher

Read registers with ruby

Posted in Articles, Projects by EK on August 19, 2009

A couple of days ago I needed to get the state of the cpu registers of a running process during some specific events. The project I was playing with was written in ruby so I wrote a tiny little module that does just that, gives you the value of the requested cpu register. The module is called reginfo and below is the process I followed to do it.

First I had to write the C part of it, for the instrumentation. A simple way to get the registers is to use ptrace. First we attach to a process, then we get the register, then we detach and finally return the value.

For this to work as a ruby module we have to use the ruby.h

#include "ruby.h"
#include <unistd.h>
#include <linux/ptrace.h>
#include <sys/user.h> 

VALUE RegInfo = Qnil;
void Init_reginfo();

VALUE method_getr(VALUE self,VALUE arg,VALUE pid);

void Init_reginfo()
{
        RegInfo = rb_define_module("RegInfo");
        rb_define_method(RegInfo, "getr", method_getr,2 );
}

VALUE method_getr(VALUE self, VALUE arg, VALUE pid)
{
	char* input=RSTRING_PTR(arg);
	pid_t  process = NUM2INT(pid);
	struct user_regs_struct registers;
	long out=0;
	char outreg[10];
	ptrace(PTRACE_ATTACH,process,0,0); //attach to process
	waitpid(process,NULL,0);
	ptrace(PTRACE_GETREGS,process,&registers,&registers); //get'em
	if (!strncasecmp(input,"eax",3)){out = registers.eax;}  //make sure we don't cmpr case
	else if (!strncasecmp(input,"edx",3)){out = registers.edx;}
	else if (!strncasecmp(input,"ebx",3)){out = registers.ebx;}
	else if (!strncasecmp(input,"ecx",3)){out = registers.ecx;}
	else if (!strncasecmp(input,"ebp",3)){out = registers.ebp;}
	else if (!strncasecmp(input,"esi",3)){out = registers.esi;}
	else if (!strncasecmp(input,"eip",3)){out = registers.eip;}
	else {out =  registers.eip;} //default
	ptrace(PTRACE_DETACH,process,0,0); //detach from process
	snprintf(outreg,10,"%lx",out);
	return rb_str_new2(outreg);
}

</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">

Next it’s straight forward, we create an extconf.rb file which when we execute generates the Makefile which will compile our module.

require 'mkmf'
extension_name = 'reginfo'
dir_config(extension_name)
create_makefile(extension_name)

And an example

require 'reginfo'
include  RegInfo

pid = fork do
system("tail -f txt")
end

puts getr("eip",pid) #here we get EIP

The above  prints something like b7f577d8

You can download reginfo from here, the source code from here and project updates here.

This is a very simple linux module at the moment that performs only this specific task, more functionality will be added soon. If you are looking for something a bit more elaborate, have a look at METASM.

Advertisement
Tagged with: , ,
Follow

Get every new post delivered to your Inbox.