Updated ruby bindings (#744)

* added methods for uc_context_save, uc_context_restore

* added test for context_save

* changed version of the lib
This commit is contained in:
Sascha Schirra 2017-01-29 01:13:17 +01:00 committed by Nguyen Anh Quynh
parent 89d536df5a
commit eb4dc61c66
4 changed files with 104 additions and 3 deletions

View file

@ -5,7 +5,7 @@
# Use bundle install && rake to install gem and test
install: gen_const
cd unicorn_gem && rake build
cd unicorn_gem && gem install --local pkg/unicorn-0.9.0.gem
cd unicorn_gem && gem install --local pkg/unicorn-1.0.0.gem
gen_const:
cd .. && python const_generator.py ruby

View file

@ -258,7 +258,7 @@ def test_i386_invalid_mem_write()
r_ecx = mu.reg_read(UC_X86_REG_ECX)
r_edx = mu.reg_read(UC_X86_REG_EDX)
puts ">>> ECX = 0x%x" % r_ecx
puts ">>> ECX = 0x%x" % r_ecx
puts ">>> EDX = 0x%x" % r_edx
begin
@ -282,6 +282,47 @@ def test_i386_invalid_mem_write()
end
end
def test_i386_context_save()
puts("Save/restore CPU context in opaque blob")
address = 0
code = '\x40' # inc eax
begin
# Initialize emulator
mu = Uc.new UC_ARCH_X86, UC_MODE_32
# map 8KB memory for this emulation
mu.mem_map(address, 8 * 1024, UC_PROT_ALL)
# write machine code to be emulated to memory
mu.mem_write(address, code)
# set eax to 1
mu.reg_write(UC_X86_REG_EAX, 1)
puts(">>> Running emulation for the first time")
mu.emu_start(address, address+1)
puts(">>> Emulation done. Below is the CPU context")
puts(">>> EAX = 0x%x" %(mu.reg_read(UC_X86_REG_EAX)))
puts(">>> Saving CPU context")
saved_context = mu.context_save()
puts(">>> Running emulation for the second time")
mu.emu_start(address, address+1)
puts(">>> Emulation done. Below is the CPU context")
puts(">>> EAX = 0x%x" %(mu.reg_read(UC_X86_REG_EAX)))
puts(">>> CPU context restored. Below is the CPU context")
mu.context_restore(saved_context)
puts(">>> EAX = 0x%x" %(mu.reg_read(UC_X86_REG_EAX)))
rescue UcError => e
puts("ERROR: %s" % e)
end
end
# Test X86 32 bit with IN/OUT instruction
def test_i386_inout()
puts("Emulate i386 code with IN/OUT instructions")
@ -500,6 +541,8 @@ test_i386_invalid_mem_read()
puts("=" * 20)
test_i386_invalid_mem_write()
puts("=" * 20)
test_i386_context_save()
puts("=" * 20)
test_i386_inout()
puts("=" * 20)
test_x86_64()

View file

@ -26,12 +26,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
VALUE UnicornModule = Qnil;
VALUE UcClass = Qnil;
VALUE UcError = Qnil;
VALUE SavedContext = Qnil;
void Init_unicorn() {
rb_require("unicorn/unicorn_const");
UnicornModule = rb_define_module("Unicorn");
UcError = rb_define_class_under(UnicornModule, "UcError", rb_eStandardError);
SavedContext = rb_define_class_under(UnicornModule, "SavedContext", rb_cObject);
UcClass = rb_define_class_under(UnicornModule, "Uc", rb_cObject);
rb_define_method(UcClass, "initialize", m_uc_initialize, 2);
@ -47,6 +49,9 @@ void Init_unicorn() {
rb_define_method(UcClass, "hook_add", m_uc_hook_add, -1);
rb_define_method(UcClass, "hook_del", m_uc_hook_del, 1);
rb_define_method(UcClass, "query", m_uc_hook_del, 1);
rb_define_method(UcClass, "context_save", m_uc_context_save, 0);
rb_define_method(UcClass, "context_update", m_uc_context_update, 1);
rb_define_method(UcClass, "contest_restore", m_uc_context_restore, 1);
}
VALUE m_uc_initialize(VALUE self, VALUE arch, VALUE mode) {
@ -422,3 +427,53 @@ VALUE m_uc_query(VALUE self, VALUE query_mode){
}
return INT2NUM(result);
}
VALUE m_uc_context_save(VALUE self){
uc_err err;
uc_engine *_uc;
Data_Get_Struct(rb_iv_get(self,"@uch"), uc_engine, _uc);
uc_context *_context;
err = uc_context_alloc(_uc, &_context);
if (err != UC_ERR_OK) {
rb_raise(UcError, "%s", uc_strerror(err));
}
err = uc_context_save(_uc, _context);
if (err != UC_ERR_OK) {
rb_raise(UcError, "%s", uc_strerror(err));
}
VALUE sc = Data_Wrap_Struct(SavedContext, 0, uc_free, _context);
return sc;
}
VALUE m_uc_context_update(VALUE self, VALUE context){
uc_err err;
uc_engine *_uc;
Data_Get_Struct(rb_iv_get(self,"@uch"), uc_engine, _uc);
uc_context *_context;
Data_Get_Struct(context, uc_context, _context);
err = uc_context_save(_uc, _context);
if (err != UC_ERR_OK) {
rb_raise(UcError, "%s", uc_strerror(err));
}
return Qnil;
}
VALUE m_uc_context_restore(VALUE self, VALUE context){
uc_err err;
uc_engine *_uc;
Data_Get_Struct(rb_iv_get(self,"@uch"), uc_engine, _uc);
uc_context *_context;
Data_Get_Struct(context, uc_context, _context);
err = uc_context_restore(_uc, _context);
if (err != UC_ERR_OK) {
rb_raise(UcError, "%s", uc_strerror(err));
}
return Qnil;
}

View file

@ -30,4 +30,7 @@ VALUE m_uc_mem_unmap(VALUE self, VALUE address, VALUE size);
VALUE m_uc_mem_protect(VALUE self, VALUE address, VALUE size, VALUE perms);
VALUE m_uc_hook_add(int argc, VALUE* argv, VALUE self);
VALUE m_uc_hook_del(VALUE self, VALUE hook);
VALUE m_uc_query(VALUE self, VALUE query_mode);
VALUE m_uc_query(VALUE self, VALUE query_mode);
VALUE m_uc_context_save(VALUE self);
VALUE m_uc_context_update(VALUE self, VALUE context);
VALUE m_uc_context_restore(VALUE self, VALUE context);