关于静态修改.NET的DLL对某些函数进行HOOK的方法

以 Hook httpclient,打印它的request和response为例

1. 使用ildasm将目标DLL转成IL

cs 复制代码
ildasm target.dll /out=target.il

2.修改target.il

原始:

复制代码
    IL_007b:  newobj     instance void [netstandard]System.Net.Http.HttpClientHandler::.ctor()
    IL_0080:  dup
    IL_0081:  ldc.i4.3
    IL_0082:  callvirt   instance void [netstandard]System.Net.Http.HttpClientHandler::set_AutomaticDecompression(valuetype [netstandard]System.Net.DecompressionMethods)
    IL_0087:  stloc.0
    IL_0088:  ldarg.0
    IL_0089:  ldloc.0
    IL_008a:  newobj     instance void [netstandard]System.Net.Http.HttpClient::.ctor(class [netstandard]System.Net.Http.HttpMessageHandler)

修改调用自己的handler, 直接[netstandard]System.Net.Http.HttpClientHandler 改成 [InterceptorLib]InterceptorLib.LoggingHandler:

diff 复制代码
    IL_007b:  newobj     instance void [InterceptorLib]InterceptorLib.LoggingHandler::.ctor()
    IL_0080:  dup
    IL_0081:  ldc.i4.3
    IL_0082:  callvirt   instance void [InterceptorLib]InterceptorLib.LoggingHandler::set_AutomaticDecompression(valuetype [netstandard]System.Net.DecompressionMethods)
    IL_0087:  stloc.0
    IL_0088:  ldarg.0

然后il文件开头添加InterceptorLib引用

diff 复制代码
.assembly extern InterceptorLib
{
  .ver 0:0:0:0
}

3. 生成一个InterceptorLib.dll 和 LoggingHandler这个类。

cs 复制代码
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.IO;

namespace InterceptorLib
{
    public class LoggingHandler : DelegatingHandler
    {
        
        public LoggingHandler()
            : base(new HttpClientHandler())
        {

        }
        //[netstandard] System.Net.Http.HttpClientHandler::set_AutomaticDecompression(valuetype[netstandard] System.Net.DecompressionMethods)
        public System.Net.DecompressionMethods  AutomaticDecompression
        {
            get { return ((HttpClientHandler)this.InnerHandler).AutomaticDecompression; }
            set { ((HttpClientHandler)this.InnerHandler).AutomaticDecompression = value; }
        }


        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {

            StreamWriter sw = File.AppendText("api.log");
            try
            {
                sw.WriteLine(DateTime.Now +  " Request:");
                sw.WriteLine(request.ToString());
                if (request.Content != null)
                {
                    sw.WriteLine(await request.Content.ReadAsStringAsync());
                }
                sw.WriteLine();
                sw.WriteLine();

                HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

                sw.WriteLine(DateTime.Now + " Response:");
                sw.WriteLine(response.ToString());
                if (response.Content != null)
                {
                    sw.WriteLine(await response.Content.ReadAsStringAsync());
                }
                sw.WriteLine();
                return response;
            }
            catch (Exception ex)
            {
                // Handle potential errors during logging (e.g., file access issues)
                Console.WriteLine($"Error writing to log file: {ex.Message}");
            }

            return null;
        }



    }
}

4. 使用ilasm 将target.il 转成 dll

cs 复制代码
ilasm  target.il /dll

5. 将InterceptorLib.dll和生成后的target.dll 复制到目标目录

cs 复制代码
cp *.dll target_dir
相关推荐
缺点内向3 小时前
C#: 告别繁琐!轻松移除Word文档中的文本与图片水印
c#·自动化·word·.net
2501_930707784 小时前
使用 C# .NET 从 PowerPoint 演示文稿中提取背景图片
c#·powerpoint·.net
向上的车轮9 小时前
为什么.NET(C#)转 Java 开发时常常在“吐槽”Java:checked exception
java·c#·.net
波波00710 小时前
每日一题:.NET 的 GC是如何分代工作的?
算法·.net·gc
波波0071 天前
每日一题:中间件是如何工作的?
中间件·.net·面试题
无风听海1 天前
.NET 10之可空引用类型
数据结构·.net
码云数智-园园1 天前
基于 JSON 配置的 .NET 桌面应用自动更新实现指南
.net
无风听海1 天前
.NET 10 之dotnet run的功能
.net
岩屿1 天前
Ubuntu下安装Docker并部署.NET API(二)
运维·docker·容器·.net
码云数智-大飞1 天前
.NET 中高效实现 List 集合去重的多种方法详解
.net