设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 2509|回复: 0
打印 上一主题 下一主题

[原创发布] ruby语言被机器语言回调的相关技术

[复制链接]

Lv3.寻梦者

梦石
0
星屑
1789
在线时间
951 小时
注册时间
2012-7-5
帖子
245
跳转到指定楼层
1
发表于 2016-11-28 21:58:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
OI惨遭退役,惨啊....(与本文内容无关)

大概就是造了个兰兰姐姐造过的轮子。

具体内容请看: http://sxysxy.org/blogs/69
备用地址: http://blog.csdn.net/u013632138/article/details/53385303 (哈,退役了也许博客都不开了,就在csdn上也留一份...)

相关代码,本地扩展库:

C 代码复制下载
  1. #include "ruby.h"
  2. VALUE get_rb_funcall(VALUE self)
  3. {
  4.     return INT2NUM((int)rb_funcall);
  5. }
  6. VALUE get_ptr_val(VALUE self)
  7. {
  8.     return INT2NUM(self);
  9. }
  10. VALUE get_intern(VALUE self, VALUE name)
  11. {
  12.     return INT2NUM(rb_intern(RSTRING_PTR(name)));
  13. }
  14. void Init_caller_ext()
  15. {
  16.     rb_define_method(rb_mKernel, "get_rb_funcall", get_rb_funcall, 0);
  17.     rb_define_method(rb_mKernel, "get_ptr_val", get_ptr_val, 0);
  18.     rb_define_method(rb_mKernel, "get_intern", get_intern, 1);
  19. }


测试用dll:
C 代码复制下载
  1. #include <windows.h>
  2. #define DLL_API __declspec(dllexport)
  3. DLL_API void caller(void (*f) (int x))
  4. {
  5.     f(2);
  6. }
  7. DLL_API BOOL WINAPI DllMain(HINSTANCE hInstance,
  8.                         DWORD uReason, DWORD lpReversed)
  9. {
  10.     switch(uReason)
  11.     {
  12.         case DLL_PROCESS_ATTACH:
  13.             puts("Dll Attached");
  14.         break;
  15.         case DLL_PROCESS_DETACH:
  16.             puts("Dll Detached");
  17.         break;
  18.     }
  19.     return TRUE;
  20. }


测试用ruby脚本:
RUBY 代码复制下载
  1. =begin
  2.  
  3.     动态生成机器语言,搭建机器语言 -> ruby解释器 -> ruby代码之间的桥梁
  4.         by sxysxy 2016.11.28
  5. =end
  6.  
  7. require 'fiddle'
  8. require './caller_ext.so'
  9. include Fiddle
  10.  
  11. class OpCode
  12.     attr_accessor :ptr
  13.     attr_accessor :length
  14.     #gen_code
  15.     #用法: obj,持有方法method的对象
  16.     #      method, 方法名(一个字符串)
  17.     #      argc, 被回调的ruby "函数" 需要的参数的个数
  18.     #      proto, 调用协议,默认cdecl
  19.     # stdcall的实现没写(留做作业噗)...如果需要支持stdcall,需要最后再把调用者的压栈平衡掉。(也就多两行代码..)
  20.     def gen_code(obj, method, argc, proto = :cdecl)  
  21.         s = ""
  22.         s += [0x55].pack("C") #push ebp
  23.         s += [0x89, 0xe5].pack("CC") #mov ebp, esp
  24.  
  25.         cnt = 4+argc*4;   #参数地址偏移量
  26.         argc.times do
  27.             s += [0x8b, 0x45].pack("CC")+[cnt].pack("C") #mov eax, [ebp+cnt]
  28.             s += [0xd1, 0xe0].pack("CC") #shl eax, 1
  29.             s += [0x40, 0x50].pack("CC") #inc eax, push eax
  30.             cnt -= 4
  31.         end
  32.  
  33.         s += ([0x68]+[argc].pack("L").bytes).pack("C*") #push dword argc
  34.         s += ([0x68]+[get_intern(method)].pack("L").bytes).pack("C*") #push dword method
  35.         s += ([0x68]+[obj.get_ptr_val].pack("L").bytes).pack("C*") #push dword obj
  36.  
  37.         #call rb_funcall
  38.         #s += [0x9a].pack("C")+[get_rb_funcall].pack("L")+[0].pack("S")
  39.         s += [0xb9].pack("C")+[get_rb_funcall].pack("L") #mov ecx, rb_funcall
  40.         s += [0xff, 0xd1].pack("CC")    #call ecx
  41.  
  42.         s += [0x89, 0xc3].pack("CC")   #mov ebx, eax
  43.         s += ([0xb8]+[argc].pack("L").bytes).pack("C*") #mov eax, argc
  44.         s += [0x83, 0xc0, 0x03].pack("CCC")  #add eax, byte 3
  45.         s += [0xc1, 0xe0, 0x02].pack("CCC")  #shl eax, byte 2
  46.         s += [0x01, 0xc4].pack("CC")    #add esp, eax
  47.         s += [0x89, 0xd8].pack("CC")    #mov eax, ebx
  48.         s += [0x5d, 0xc3].pack("CC")    #pop ebp, ret
  49.  
  50.         [url=home.php?mod=space&uid=2661269]@PTR[/url] = Fiddle::Pointer.malloc(s.length)
  51.         @ptr[0, s.length] = s
  52.         @length = s.length
  53.         self
  54.     end
  55.     def free
  56.         @ptr.free
  57.     end
  58.     def addr
  59.         @ptr.to_i
  60.     end
  61. end
  62.  
  63. def test_call(x)  #被测试调用的函数
  64.     puts "Called! arg x = #{x}"
  65. end
  66.  
  67. c = OpCode.new
  68. c.gen_code(Kernel, "test_call", 1)
  69. File.open("test_gen_code.bin", "wb") do |f|
  70.     f.write c.ptr[0, c.length]  #这里把生成的机器语言输出到文件,方便反汇编查看
  71. end
  72.  
  73. addr = dlopen("caller_test.dll")['caller']
  74. caller = Function.new(addr, [TYPE_LONG], TYPE_VOID)   
  75. caller.call c.addr  #把c.addr作为函数指针传入。
  76. c.free     #释放机器语言占用的内存


以上....

评分

参与人数 2星屑 +350 收起 理由
kuerlulu + 100 %%%
唯道集虚 + 250 (这次是以个人身份塞糖)安慰安慰我们的退.

查看全部评分

tan(pi/2)
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-12-4 03:28

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表