遇到一个技术点,记一下,.net 有一个 Delegate Marshall.GetDelegateForFunctionPointer(IntPtr ptr, Type t) 用来将内存地址映射为一个 delegate,转为 delegate 后就可以对内存段的二进制代码进行 .net 内的调用了。例如 ptr 是 VirtualAlloc 的地址,t 是具有 IntPtr(IntPtr lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect) 签名的代理类型,那么获得的就是一个这个 delegate 的实例:

delegate IntPtr VirtualAllocDelegate(IntPtr lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);

VirtualAllocDelegate d = Marshall.GetDelegateForFunctionPointer(ptr, typeof(VirtualAllocDelegate))

d(IntPtr.Zero, 200, 1, 0)

这是把 API 映射为 .net 的一个重要方法。

现在我要做的是拦截它,抓取调用。我要提供一个万能函数,然后所有调用都先回调到这个函数:

class Hook{
void Invoke(params object[] args){...}
}

我需要实现两个环节:

  1. 把这个函数适配到任意的 Type t,把参数发到 params object[] args
  2. 要先调用我这个钩子函数

下面是实现:

            var h = Marshal.GetDelegateForFunctionPointer(entrance, delegateType);   // 指针对应的 delegate
// 构造一个头和 delegateType 对齐的 lambda expression
var invoke = delegateType.GetMethod("Invoke");
var parameters = invoke.GetParameters().Select(p => ParameterExpression.Variable(p.ParameterType)).ToArray();
var args = Expression.NewArrayInit(typeof(object),
parameters.Select(p => Expression.TypeAs(p, typeof(object))).ToArray());
MethodCallExpression callExpression = Expression.Call(Expression.Constant(new Hook()), "Invoke", null, args); // 参数转发到 new Hook().Invoke
LambdaExpression lambdaExpression;
if (invoke.ReturnType == typeof(void))
{
lambdaExpression = Expression.Lambda(t, callExpression, parameters); // t 是 void 类型,lambda 无需返回
}
else
{
var block = Expression.Block(callExpression, Expression.Default(invoke.ReturnType)); // 否则返回默认值,注意这里只要加一个 Expression.Default(..) 就行,不需要 Expression.Return()...
lambdaExpression = Expression.Lambda(t, block, parameters);
}
dynamic h2 = Delegate.Combine(lambdaExpression.Compile(), h); // Combine 在一起,先调用我再调用原来的指针,目标达到!

至于怎么替掉原来的 Marshall.GetDelegateForFunctionPointer 就不展开了。

总体来说,.net 的 delegate 对应的级别很低,它是内存函数指针的类型化,其 DynamicInvoke Invoke 等方法既不暴露也不能覆盖,是一个魔法原子。相比来说 Java 面向对象的更彻底。

class Hook {
void invoke(object... args)
}
class VirtualAllocDelegate {
IntPrt invoke(IntPtr a, IntPtr b, IntPtr c)
}
// 这里也要用到 Java 的动态技术,生成一个临时类 MyDel extends VirtualAllocDelegate
dynamic class MyDel extends VirtualAllocDelegate{
MyDel(VirtualAllocDelegate inner, Hook h){
}
override IntPtr invoke(IntPtr a, IntPtr b, IntPtr c){
hook.invoke(a,b,c);
return inner.invoke(a,b,c);
}
}
var d = new MyDel(new VirtualAllocDelegate(offset), new Hook());
d.invoke(...)

Java 里 invoke 会是一个符合 OO 思想的 override,而不是 Delegate.Combine 这种更 c-style 还带点 fp 的玩意儿。

和 java 相比 c# 的面向对象程度不够彻底,有时像是 C 和 FP 结合的怪胎,一个典型的特点是 c# 从一开始就没有匿名内部类。

.net delegate 万能适配的更多相关文章

  1. Android TV开发总结(五)TV上屏幕适配总结

    前言:前面几篇总结一些TV上的小Sample,开源到GitHub:https://github.com/hejunlin2013/TVSample, 点击链接,可以持续关注.今天总结下TV上屏幕适配. ...

  2. 一行代码搞定所有屏幕适配AbViewUtil

    适配原理:抛弃google提供的dip理论与多套图片与布局方案,采用与UI设计师通用的px作为标准单位,原理是将UI设计师的设计图与当前查看的手机或其他设备的屏幕像素尺寸进行换算,得到缩放比例,在Ac ...

  3. Android Andbase应用开发框架

    [运行说明]运行AndbaseDemo需要将文件中的Andbase库Add进demo中.1.andbase中包含了大量的开发常用手段.如网络下载,多线程与线程池的管理,数据库ORM,图片缓存管理,图片 ...

  4. android开源框架之 andbase

    andbase开发框架介绍:andbase是为Android开发人员量身打造的一款开源类库产品,您能够在本站中获取到最新的代码,演示样例以及开发文档. 下载地址:http://download.csd ...

  5. 一个漂亮而强大的RecyclerView

    代码地址如下:http://www.demodashi.com/demo/13470.html 简介 主要提供了简单易用强大的RecyclerView库,包括自定义刷新加载效果.极简通用的万能适配器A ...

  6. 9款Android经常使用的高速开发框架

    1.Afinal框架 项目地址:https://github.com/yangfuhai/afinal 项目地址:http://www.oschina.net/p/afinal 主要有四大模块:  ( ...

  7. Android 开源控件与常用开发框架开发工具类

    Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...

  8. iOS设计模式之适配器模式

    一,适配器的定义 定义 将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作 需求场景 需要使用以前开发的“一些现存的对象”,但是新环境中要求 ...

  9. iOS---iOS10适配iOS当前所有系统的远程推送

    一.iOS推送通知简介 众所周知苹果的推送通知从iOS3开始出现, 每一年都会更新一些新的用法. 譬如iOS7出现的Silent remote notifications(远程静默推送), iOS8出 ...

  10. Android—万能ListView适配器

    ListView是开发中最常用的控件了,但是总是会写重复的代码,浪费时间又没有意义. 最近参考一些资料,发现一个万能ListView适配器,代码量少,节省时间,总结一下分享给大家. 首先有一个自定义的 ...

随机推荐

  1. Qt构建cmake工程方法总结

    由于工作需要,最近打算统一将所有C/C++项目都改成使用cmake编译.传统后台业务问题不大,但是有些牵涉到跨平台的Qt项目还是折腾了一阵.下面对这段时间的收获做一个总结,也希望帮助看到本文的朋友少走 ...

  2. USB gadget functionfs

    FunctionFS (Function Filesystem) 是 Linux USB Gadget 框架的一部分,专门用于从用户空间实现和控制自定义的 USB 功能.它提供了一种文件系统接口,使用 ...

  3. Linux内存管理2.6 -反向映射RMAP(最终版本)

    所谓反向映射是相对于从虚拟地址到物理地址的映射,反向映射是从物理页面到虚拟地址空间VMA的反向映射. RMAP能否实现的基础是通过struct anon_vma.struct anon_vma_cha ...

  4. 在不需要WiFi密码的情况下进行断网攻击

    本教程只能用于学习研究之用 任何未经他人允许的攻击行为都是违法行为 参考教程 https://www.youtube.com/davidbombal 准备 * kali linux 系统 这里使用的是 ...

  5. 百度ai只能回答怎么关闭

        百度ai只能回答怎么关闭 要关闭‌百度的AI智能回答功能,可以通过以下几种方法实现: 使用广告拦截插件 安装广告拦截插件:如‌AdGuard.‌uBlock Origin等,这些插件可以帮助你 ...

  6. 蜘点云原生之 KubeSphere 落地实践过程

    作者:池晓东,蜘点商业网络服务有限公司技术总监,从事软件开发设计 10 多年,喜欢研究各类新技术,分享技术. 来源:本文由 11 月 25 日广州站 meetup 中讲师池晓东整理,整理于该活动中池老 ...

  7. python+ffmpeg视频转码转格式

    本文转发来自:https://blog.csdn.net/KH_FC/article/details/115771126 废话 python目前自己也是在学习当中,对python也不是特别精通,写视频 ...

  8. Matrix Calculus

    1 Scalar Function \(\text{If }f(\mathbf{x})\in\mathbf{R},\mathrm{then}\) \[df=\frac{\partial f}{\par ...

  9. git知识点,常用命令

    git理论知识 git的服务器端(remote)端包含多个repository,每个repository可以理解为一个项目. 而每个repository下有多个branch."origin& ...

  10. python机器学习(第一章 Python机器学习基础)

    第一章 Python机器学习基础 基础: Python官网:https://www.python.org/doc/: 历史版本下载与维护信息:https://www.python.org/downlo ...