赞 | 7 |
VIP | 0 |
好人卡 | 1 |
积分 | 18 |
经验 | 34644 |
最后登录 | 2024-11-18 |
在线时间 | 951 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 1789
- 在线时间
- 951 小时
- 注册时间
- 2012-7-5
- 帖子
- 245
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
OI惨遭退役,惨啊....(与本文内容无关)
大概就是造了个兰兰姐姐造过的轮子。
具体内容请看: http://sxysxy.org/blogs/69
备用地址: http://blog.csdn.net/u013632138/article/details/53385303 (哈,退役了也许博客都不开了,就在csdn上也留一份...)
相关代码,本地扩展库:
#include "ruby.h" VALUE get_rb_funcall(VALUE self) { return INT2NUM((int)rb_funcall); } VALUE get_ptr_val(VALUE self) { return INT2NUM(self); } VALUE get_intern(VALUE self, VALUE name) { return INT2NUM(rb_intern(RSTRING_PTR(name))); } void Init_caller_ext() { rb_define_method(rb_mKernel, "get_rb_funcall", get_rb_funcall, 0); rb_define_method(rb_mKernel, "get_ptr_val", get_ptr_val, 0); rb_define_method(rb_mKernel, "get_intern", get_intern, 1); }
#include "ruby.h"
VALUE get_rb_funcall(VALUE self)
{
return INT2NUM((int)rb_funcall);
}
VALUE get_ptr_val(VALUE self)
{
return INT2NUM(self);
}
VALUE get_intern(VALUE self, VALUE name)
{
return INT2NUM(rb_intern(RSTRING_PTR(name)));
}
void Init_caller_ext()
{
rb_define_method(rb_mKernel, "get_rb_funcall", get_rb_funcall, 0);
rb_define_method(rb_mKernel, "get_ptr_val", get_ptr_val, 0);
rb_define_method(rb_mKernel, "get_intern", get_intern, 1);
}
测试用dll:
#include <windows.h> #define DLL_API __declspec(dllexport) DLL_API void caller(void (*f) (int x)) { f(2); } DLL_API BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD uReason, DWORD lpReversed) { switch(uReason) { case DLL_PROCESS_ATTACH: puts("Dll Attached"); break; case DLL_PROCESS_DETACH: puts("Dll Detached"); break; } return TRUE; }
#include <windows.h>
#define DLL_API __declspec(dllexport)
DLL_API void caller(void (*f) (int x))
{
f(2);
}
DLL_API BOOL WINAPI DllMain(HINSTANCE hInstance,
DWORD uReason, DWORD lpReversed)
{
switch(uReason)
{
case DLL_PROCESS_ATTACH:
puts("Dll Attached");
break;
case DLL_PROCESS_DETACH:
puts("Dll Detached");
break;
}
return TRUE;
}
测试用ruby脚本:
=begin 动态生成机器语言,搭建机器语言 -> ruby解释器 -> ruby代码之间的桥梁 by sxysxy 2016.11.28 =end require 'fiddle' require './caller_ext.so' include Fiddle class OpCode attr_accessor :ptr attr_accessor :length #gen_code #用法: obj,持有方法method的对象 # method, 方法名(一个字符串) # argc, 被回调的ruby "函数" 需要的参数的个数 # proto, 调用协议,默认cdecl # stdcall的实现没写(留做作业噗)...如果需要支持stdcall,需要最后再把调用者的压栈平衡掉。(也就多两行代码..) def gen_code(obj, method, argc, proto = :cdecl) s = "" s += [0x55].pack("C") #push ebp s += [0x89, 0xe5].pack("CC") #mov ebp, esp cnt = 4+argc*4; #参数地址偏移量 argc.times do s += [0x8b, 0x45].pack("CC")+[cnt].pack("C") #mov eax, [ebp+cnt] s += [0xd1, 0xe0].pack("CC") #shl eax, 1 s += [0x40, 0x50].pack("CC") #inc eax, push eax cnt -= 4 end s += ([0x68]+[argc].pack("L").bytes).pack("C*") #push dword argc s += ([0x68]+[get_intern(method)].pack("L").bytes).pack("C*") #push dword method s += ([0x68]+[obj.get_ptr_val].pack("L").bytes).pack("C*") #push dword obj #call rb_funcall #s += [0x9a].pack("C")+[get_rb_funcall].pack("L")+[0].pack("S") s += [0xb9].pack("C")+[get_rb_funcall].pack("L") #mov ecx, rb_funcall s += [0xff, 0xd1].pack("CC") #call ecx s += [0x89, 0xc3].pack("CC") #mov ebx, eax s += ([0xb8]+[argc].pack("L").bytes).pack("C*") #mov eax, argc s += [0x83, 0xc0, 0x03].pack("CCC") #add eax, byte 3 s += [0xc1, 0xe0, 0x02].pack("CCC") #shl eax, byte 2 s += [0x01, 0xc4].pack("CC") #add esp, eax s += [0x89, 0xd8].pack("CC") #mov eax, ebx s += [0x5d, 0xc3].pack("CC") #pop ebp, ret [url=home.php?mod=space&uid=2661269]@PTR[/url] = Fiddle::Pointer.malloc(s.length) @ptr[0, s.length] = s @length = s.length self end def free @ptr.free end def addr @ptr.to_i end end def test_call(x) #被测试调用的函数 puts "Called! arg x = #{x}" end c = OpCode.new c.gen_code(Kernel, "test_call", 1) File.open("test_gen_code.bin", "wb") do |f| f.write c.ptr[0, c.length] #这里把生成的机器语言输出到文件,方便反汇编查看 end addr = dlopen("caller_test.dll")['caller'] caller = Function.new(addr, [TYPE_LONG], TYPE_VOID) caller.call c.addr #把c.addr作为函数指针传入。 c.free #释放机器语言占用的内存
=begin
动态生成机器语言,搭建机器语言 -> ruby解释器 -> ruby代码之间的桥梁
by sxysxy 2016.11.28
=end
require 'fiddle'
require './caller_ext.so'
include Fiddle
class OpCode
attr_accessor :ptr
attr_accessor :length
#gen_code
#用法: obj,持有方法method的对象
# method, 方法名(一个字符串)
# argc, 被回调的ruby "函数" 需要的参数的个数
# proto, 调用协议,默认cdecl
# stdcall的实现没写(留做作业噗)...如果需要支持stdcall,需要最后再把调用者的压栈平衡掉。(也就多两行代码..)
def gen_code(obj, method, argc, proto = :cdecl)
s = ""
s += [0x55].pack("C") #push ebp
s += [0x89, 0xe5].pack("CC") #mov ebp, esp
cnt = 4+argc*4; #参数地址偏移量
argc.times do
s += [0x8b, 0x45].pack("CC")+[cnt].pack("C") #mov eax, [ebp+cnt]
s += [0xd1, 0xe0].pack("CC") #shl eax, 1
s += [0x40, 0x50].pack("CC") #inc eax, push eax
cnt -= 4
end
s += ([0x68]+[argc].pack("L").bytes).pack("C*") #push dword argc
s += ([0x68]+[get_intern(method)].pack("L").bytes).pack("C*") #push dword method
s += ([0x68]+[obj.get_ptr_val].pack("L").bytes).pack("C*") #push dword obj
#call rb_funcall
#s += [0x9a].pack("C")+[get_rb_funcall].pack("L")+[0].pack("S")
s += [0xb9].pack("C")+[get_rb_funcall].pack("L") #mov ecx, rb_funcall
s += [0xff, 0xd1].pack("CC") #call ecx
s += [0x89, 0xc3].pack("CC") #mov ebx, eax
s += ([0xb8]+[argc].pack("L").bytes).pack("C*") #mov eax, argc
s += [0x83, 0xc0, 0x03].pack("CCC") #add eax, byte 3
s += [0xc1, 0xe0, 0x02].pack("CCC") #shl eax, byte 2
s += [0x01, 0xc4].pack("CC") #add esp, eax
s += [0x89, 0xd8].pack("CC") #mov eax, ebx
s += [0x5d, 0xc3].pack("CC") #pop ebp, ret
[url=home.php?mod=space&uid=2661269]@PTR[/url] = Fiddle::Pointer.malloc(s.length)
@ptr[0, s.length] = s
@length = s.length
self
end
def free
@ptr.free
end
def addr
@ptr.to_i
end
end
def test_call(x) #被测试调用的函数
puts "Called! arg x = #{x}"
end
c = OpCode.new
c.gen_code(Kernel, "test_call", 1)
File.open("test_gen_code.bin", "wb") do |f|
f.write c.ptr[0, c.length] #这里把生成的机器语言输出到文件,方便反汇编查看
end
addr = dlopen("caller_test.dll")['caller']
caller = Function.new(addr, [TYPE_LONG], TYPE_VOID)
caller.call c.addr #把c.addr作为函数指针传入。
c.free #释放机器语言占用的内存
以上.... |
评分
-
查看全部评分
|