关于静态修改.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
相关推荐
用户2986985301411 小时前
程序员效率工具:Spire.Doc如何助你一键搞定Word表格排版
后端·c#·.net
牧马人win12 小时前
SmartDapper.Repository
.net
mudtools2 天前
搭建一套.net下能落地的飞书考勤系统
后端·c#·.net
玩泥巴的2 天前
搭建一套.net下能落地的飞书考勤系统
c#·.net·二次开发·飞书
快乐非自愿2 天前
C# 中的 Span 和内存:.NET 中的高性能内存处理
java·c#·.net
Traced back2 天前
【.NET7 WinForm 实战】三层架构+EF Core+多数据库+完整功能(源码+教程+脚本)
数据库·架构·.net
波波0073 天前
每日一题:IEnumerable和IQueryable区别?
.net·面试题
light blue bird3 天前
产线多并发客户端指令操作场景组件
jvm·oracle·.net·winform
小先生8123 天前
.NET Core后台任务队列
.net·.netcore