一、前言

由于项目需要,最近研究了一下跨进程通讯改写第三方程序中的方法(运行中),把自己程序中的目标方法直接覆盖第三方程序中的方法函数;一直没有头绪,通过搜索引擎找了一大堆解决方案,资料甚是稀少,最后功夫不负有心人,经过两天的研究,终于在github 上找到两个开源的代码,通过两个开源代码结合起来即可实现我的需求。下面进一步来分析实践原理,后面会把源代码地址贴上来;

通过该文章分享,你会知道怎样通过注入一个dll模块改写第三方运行的程序中的某个方法,在里面实现自己的业务,这个场景在做外挂程序中特别实用!!!

二、场景

假如有一个第三方应用程序,这时候需要对第三方应用程序进行方法拦截,比如第三方应用程序中的某个操作需要用我们的业务覆盖掉他们的业务,那这种情况下我们有什么好的方案解决呢?我们不可能修改第三方程序的代码,那有什么方案可以解决呢?其实我们还是有办法进行”修改“第三方程序的代码的,怎么”修改“呢,请看下面实践原理,下面带你走入不一样的代码世界!!!!

三、实践

原理简化图:

这里实践我就直接写两个客户端程序来进行代码上的演示

3.1. 实现原理

  • Hook 目标方法:

    需要改写拦截第三方程序的指定的方法,那就得需要Hook 该方法,经过查找资料在github上找到开源代码DotNetDetour,但是开源作者是从.net framework 4.5开始支持,不支持.net framework 4.0, 我的需求需要运行在老爷机xp 上,故必须要支持4.0 的框架,所有我fork了一份把源代码做了修改支持到了.net framework 4.0 框架,fork 源代码地址:https://github.com/a312586670/DotNetDetour
  • Inject 注入dll到目标进程

    写好针对目标进程的方法Hooke dll 模块后需要考虑把该dll模块注入到第三方程序进程中,这样才可以实现完全的hook成功,改写目标进程的方法,我这里使用fastWin32 开源代码,代码地址如下:https://github.com/a312586670/FastWin32

3.2 创建第三方程序Demo

这里为了演示,我自己创建了一个目标客户端程序,主要有如下核心代码方法:

public class ProcessService
{
public string GetProcessInfo()
{
return "这是TargetClient 客户端(第三方程序)";
} public ProcessResponse GetProcessInfo(ProcessRequest request)
{
return new ProcessResponse()
{
Name = "这是TargetClient 客户端(第三方程序)",
Version = request.Version
};
}
}

UI界面交互代码如下:

 /// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} private void btnInfo_Click(object sender, RoutedEventArgs e)
{
var service = new ProcessService();
this.txtInfo.Text = service.GetProcessInfo();
} private void btnComplateInfo_Click(object sender, RoutedEventArgs e)
{
var service = new ProcessService();
var response = service.GetProcessInfo(new ProcessRequest() { Version = "v-Demo 1.0 版本" });
this.txtInfo.Text = response.Name + response.Version;
}
}

上面代码中有两个按钮事件,分别调用了ProcessService 的两个方法,我们先来运行目标客户端Demo程序,分别点击两个按钮运行结果如下:



3.3 创建核心Hook类库

好了,上面我们的目标第三方Demo程序已经写好了,接下来我们需要写一个核心的Jlion.Process.HookCore类库 改写目标的ProcessService 的两个方法。

我这里建了一个Jlion.Process.HookCore类库,通过nuget包引用我fork 后的DotNetDetour 类库,如下图:



应用成功后我们建立核心的hook 方法,代码如下:

  public class ProcessHookService : IMethodHook
{
[HookMethod("Jlion.Process.Target.Client.ProcessService", null, null)]
public string GetProcessInfo()
{
TextHelper.LogInfo($"这是Jlion.Process.HookCore.HookService dll. 改写TargetClient 客户端 的GetProcessInfo 方法后得到的结果");
return "这是Jlion.Process.HookCore.HookService dll. 改写TargetClient 客户端 的GetProcessInfo 方法后得到的结果";
} [OriginalMethod]
public string GetProcessInfo_Original()
{
return null;
} [HookMethod("Jlion.Process.Target.Client.ProcessService", null, null)]
public object GetProcessInfo([RememberType("Jlion.Process.Target.Client.Model.ProcessRequest", false)] object request)
{
var json = JsonConvert.SerializeObject(request);
TextHelper.LogInfo($"json:{json}"); var name = "这是Jlion.Process.HookCore.HookService dll. 改写TargetClient 客户端的GetProcessInfo(obj)后得到的结果";
return new ProcessResponse()
{
Name = name,
Version = "改写的dll 版本"
};
} [OriginalMethod]
public object GetProcessInfo_Original([RememberType("Jlion.Process.Target.Client.Model.ProcessRequest", false)] object request)
{
return null;
}
}

我这里就不详细的写DotNetDetour 的使用,需要知道它的使用可以访问 https://github.com/a312586670/DotNetDetour 查看具体的文档

核心的Jlion.Process.HookCore hook 类库 也已经创建完了,接下来还需要创建一个初始化Hook的服务类(特别重要),并且还必须是静态方法,代码如下:

 public class HookService
{
/// <summary>
/// Hook 初始化
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public static int Start(string msg)
{
try
{
TextHelper.LogInfo("开始"+msg);
MethodHook.Install();
}
catch
{
return -1;
}
return 1;
}
}

到这一步基本上Jlion.Process.HookCore Hook 核心的类库已经创建完了

3.4 模块注入客户端程序

创建客户端后需要引用FastWin32类库,如下图:

客户端注入Dll核心代码如下:

public class InjectService
{
//注入的核心dll 路径
public static string path = AppDomain.CurrentDomain.BaseDirectory+ "Jlion.Process.HookCore.dll"; /// <summary>
/// 进程id
/// </summary>
public static uint pid = 0; /// <summary>
/// 启动
/// </summary>
public static void Start()
{
Inject();
} #region 私有方法
private static void Inject()
{
try
{
Injector.InjectManaged(pid, path, "Jlion.Process.HookCore.HookService", "Start", "ss", out int returnValue);
}
catch (Exception ex)
{
}
} #endregion
}

代码中核心的代码是Injector.InjectManaged(),该方法有如下两个重构方法:

参数说明:

  • processId:目标进程的进程id ->pid
  • assemblyPath:核心Hook 注入的dll 绝对路径
  • typeName:Hook 初始化方法的命名空间,一般注入一个模块dll后需要执行的入口初始化方法,这里是Hook 核心dll 中的HookService.Start 方法的命名空间(Jlion.Process.HookCore.HookService)
  • methodName : 注入后执行的方法名称
  • argument : 方法所需要的参数
  • returnValue:返回注入后运行的方法返回值
客户端UI 核心代码如下:
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} private void btnInject_Click(object sender, RoutedEventArgs e)
{
InjectService.pid = Convert.ToUInt32(txbPid.Text.Trim());
InjectService.Start();
}
}

这里核心的注入Client Demo 也写完了,我们把注入的客户端也运行起来,输入目标的进程pid(也可以程序中查找目标进程Id),运行后再来执行上面创建的第三方程序的两个按钮,结果如下:



通过编写客户端程序点击注入dll后,再点击第三方程序的两个按钮事件,结果如下:





可以看到点击后,运行的结果已经被动态注入的Jlion.Process.HookCore.dll改写了,不过上面的代码也可以改写后同时还运行原有目标的方法就是通过调用'_Original'后缀结尾的方法,方法体返回null即可。

四、总结

通过DotNetDetour 框架可以编写对目标进程的方法进行Hook 重写,使用新的方法覆盖第三方进程的方法,也可以继续执行第三方的方法。

通过FastWin32调用Win32 API 把开发的dll模块注入到第三方进程中,同时注入后执行初始化方法,可以进行原有的Hook方法进行覆盖。

到这里是不是感觉很神奇,它可以在以下场景中使用:

  • 想必大家想到的就是外挂程序,通过改写目标程序的方法进行外挂处理,写上自己的覆盖业务
  • 灰产地带比较实用
  • 破解第三方收费软件等等用途

感兴趣的朋友可以下载Demo 源代码玩一玩:

github 源代码地址:https://github.com/a312586670/processClientDemo

原创不易,对你有用请点个赞

一文解读C# 动态拦截第三方进程中的方法函数(外挂必备)的更多相关文章

  1. 进程中join方法的使用

    在进程中:join方法 是让主进程等待子进程运行完毕后再执行主进程的.(即主进程阻塞) 示例 # -*- coding: utf-8 -*- from multiprocessing import P ...

  2. [AOP拦截 ]SpringBoot+Quartz Aop拦截Job类中的方法

    ​ 最近在工作使用boot+quartz整合,开发定时调度平台,遇到需要对Quartz的Job进行异常后将异常记录到日志表的操作,第一反应就想到了使用Spring的AOP,利用AfterThrowin ...

  3. Python--day37--多进程中的方法join()

    1,多进程中的方法join()的作用: 感知一个子进程的结束,将异步的程序改为同步 #join() import time from multiprocessing import Process de ...

  4. 进程动态拦截注入API HOOK

    最近工作中遇到一个问题,需要通过程序界面进行判断程序的运行状态,刚开始认为很简单,不就是一个窗体控件获取,获取Button的状态和Text.刚好去年干过该事情,就没太在意,就把优先级排到后面了,随着项 ...

  5. 使用ptrace向已运行进程中注入.so并执行相关函数

    这个总结的很好,从前一个项目也用到这中技术 转自:http://blog.csdn.net/myarrow/article/details/9630377 1. 简介 使用ptrace向已运行进程中注 ...

  6. Linux监控重要进程的实现方法

    Linux监控重要进程的实现方法 不管后台服务程序写的多么健壮,还是可能会出现core dump等程序异常退出的情况,但是一般情况下需要在无 人为干预情况下,能够自动重新启动,保证服务进程能够服务用户 ...

  7. 使用ptrace向已运行进程中注入.so并执行相关函数(转)

    1. 简介 使用ptrace向已运行进程中注入.so并执行相关函数,其中的“注入”二字的真正含义为:此.so被link到已运行进程(以下简称为:目标进程)空间中,从而.so中的函数在目标进程空间中有对 ...

  8. Programming好文解读系列(—)——代码整洁之道

    注:初入职场,作为一个程序员,要融入项目组的编程风格,渐渐地觉得系统地研究下如何写出整洁而高效的代码还是很有必要的.与在学校时写代码的情况不同,实现某个功能是不难的,需要下功夫的地方在于如何做一些防御 ...

  9. Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP

    回到目录 .Net MVC之所以发展的如些之好,一个很重要原因就是它公开了一组AOP的过滤器,即使用这些过滤器可以方便的拦截controller里的action,并注入我们自己的代码逻辑,向全局的异常 ...

随机推荐

  1. Python中的可视化神器!你知道是啥吗?没错就是pyecharts!

    pyecharts是一款将python与echarts结合的强大的数据可视化工具,本文将为你阐述pyecharts的使用细则 前言 我们都知道python上的一款可视化工具matplotlib,而前些 ...

  2. Python数据分析入门与实践 学习

    pandas是一个Python语言的软件包,在我们使用Python语言进行机器学习编程的时候,这是一个非常常用的基础编程库.本文是对它的一个入门教程.pandas提供了快速,灵活和富有表现力的数据结构 ...

  3. Django ORM 查询表中某列字段值

    场景: 有一个表中的某一列,你需要获取到这一列的所有值,你怎么操作? 解决办法: 有一个model为:Event 方式一: 获取内容: Event.objects.values('title') 输出 ...

  4. 安装宝塔检测到系统已存在Apache,请使用纯净安装

    执行命令 停止服务 net stop Apache2.4 删除服务 sc delete apache

  5. 6.Python中内存是如何管理的?

    Python中内存是如何管理的? Python memory is managed by Python private heap space. All Python objects and data ...

  6. python笔记 函数初识

    1. 函数: 封装一个功能 def    my_len(形参):          ->  def  声明定义一个函数   my_len 函数名命名规则同变量 ······          - ...

  7. 图论--差分约束--POJ 1364 King

    Description Once, in one kingdom, there was a queen and that queen was expecting a baby. The queen p ...

  8. python json.dumps中ensure_ascii的使用,load与loads的区别

    json模块最常用的两个功能: 一:json.dumps(),用于将dict拆分成str格式,称为序列化,注意序列化后,虽然print出来仍然显示的字典的样子,但是此时已经是str类型了. 其中,有时 ...

  9. VMware15.5.0安装MacOS10.15.0系统 安装步骤(上)

    VMware15.5.0安装MacOS10.15.0系统安装步骤(上)超详细! 说明: 本文是目前最新的安装和调配教程且MacOS10.15和10.16版本搭建方法相同,我也会在一些细节地方加上小技巧 ...

  10. 算法——Java实现栈

    栈 定义: 栈是一种先进后出的数据结构,我们把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何元素的栈称为空栈 栈的java代码实现: 基于数组: import org.junit.jupite ...