客户的一个紧急bug,我用了两种方式进行 C# 反编译修改源码

一:背景

1. 讲故事

周五下午运营反馈了一个紧急bug,说客户那边一个信息列表打不开,急需解决,附带的日志文件也发过来了,看了下日志大概是这样的:


日期:2020-11-13 12:25:45,923 线程ID:[3924] 日志级别:INFO  错误类:xxx property:[(null)] - 错误描述:应用程序出现了未捕获的异常,Message:该字符串未被识别为有效的 DateTime。;StackTrace:   在 System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles)在 System.Data.ConstNode..ctor(DataTable table, ValueType type, Object constant, Boolean fParseQuotes)在 System.Data.ExpressionParser.Parse()在 System.Data.DataExpression..ctor(DataTable table, String expression, Type type)在 System.Data.Select..ctor(DataTable table, String filterExpression, String sort, DataViewRowState recordStates)在 System.Data.DataTable.Select(String filterExpression)

从异常信息可以看到,大概就是 DataTable.Select 的时候抛出了异常,通过调用堆栈追查了下代码大概是这样的。

public Task<DataTable> QueryDataTable(){var dt = new DataTable();dt.Columns.Add(new DataColumn("SendTime"));dt.Rows.Add(dt.NewRow()["SendTime"] = "2020/11/14");var where = $" SendTime < #{DateTime.Now.ToString()}#";var query = dt.Select(where).CopyToDataTable();}

大坑就在这里,绝大多数时候过滤 DataTable 可以采用这样的写法 : SendTime < #2020/11/5#,但是客户在新加坡,全英文操作系统,而且时间格式也不知道设置成啥样了,我估计时间格式包含了类似的 #,正好又遇到了前后缀 # ,拆分上就出错了,导致了经典的 该字符串未被识别为有效的 DateTime 异常被抛出。

这个 bug 改起来还是很简单的,将 # 换成 ' 即可,也就是:  SendTime < '2020/11/5',如果一切顺利的话,文章就应该到此为止了,可恰恰上天捉弄,因为是紧急bug,研发老大 & 项目实施 都请假了,我一个人还真搞不定,也不知道给了客户哪一个 release 版,不想节外生枝,为了先解决这个问题,我想到了一个好办法,反编译修改,这是代价最小的,也能最快的搞定。

二:使用 dnspy 反编译修改代码

1. 使用 dnspy 的 编辑方法 模式

为了更好的理解通过 dnspy 修改,先来聊一聊 dnspy 最便捷的修改 dll 的方式:编辑方法,这种方式非常方便,无需理解 IL 代码,为了演示,我举一个简单的加法运算。

static void Main(string[] args){var i = 10;var j = 20;Console.WriteLine($"{i}+{j}={i + j}");Console.ReadLine();}

接下来将 var i= 10 改成  var i=100 的步骤为:

  • 右键 编辑方法

  • 弹框修改 var i=10 -> var i=100

  • 点击右下角 编译

  • Ctrl + Shift + S 全部保存

  • 弹出框中 选择 确定

截图大概如下:

最后 bin 目录下的 exe 就被成功修改了,双击之后就能看到你的成果啦!

????????,果然搞定了,是不是太简单了?感觉做这种反编译一点门槛都没有, 哈哈,真的没有门槛吗?

不信的话,我举一个异步方法的例子:

class Program{static void Main(string[] args){var query = QueryDataTable().Result;Console.WriteLine(JsonConvert.SerializeObject(query));Console.ReadLine();}static async Task<DataTable> QueryDataTable(){var dt = new DataTable();dt.Columns.Add(new DataColumn("SendTime"));dt.Rows.Add(dt.NewRow()["SendTime"] = "2020/11/14");var where = $" SendTime < #{DateTime.Now.ToString()}#";Console.Write(where + "\t");var task = await Task.Run(() => { return dt.Select(where).CopyToDataTable(); });return task;}}

接下来反编译一下:

我去,麻烦了,从图中可以看出两点信息:

  • 异步方法会生成状态机,用 C# 模式看反编译的代码,那些自动生成的状态机类看都看不到,谈何修改???比如你能找到:var where = $" SendTime < #{DateTime.Now.ToString()}#"; 吗?

  • <QueryDataTable>d__1 类的命名格式:<QueryDataTable>d__ 来看,你点击 编译 按钮肯定是过不了编译器的。

而恰恰我遇到的就是这种情况,太坑爹了。。。所以说,不碰 IL 在实际反编译中是不可能的。

2. 使用 dnspy 的 编辑IL指令 模式

dnspy 中除了编辑方法外,还可以使用 编辑IL指令,这功能就强大了,接下来看看怎么处理呢?操作步骤如下:

  • 在 dnspy 中将 C# 切换到 IL 视图

  • 找到需要修改的类的 IL 代码处,右键选择 编辑IL指令

  • 编辑完成之后,点击 确定

大概截图如下:

然后双击执行 exe ,可以看到已经修改成功了。

不过这里有一个吐糟的地方就是,这次bug我需要修改的地方有多处,而 编辑IL指令 的窗口中并没有 搜索功能,这就尴尬了,处理起来非常麻烦!

三:使用 ildasm & ilasm  反编译修改代码

1. 介绍

这一对还是蛮有意思的,ildasm 用于查看 dll 中的 il 代码, ilasm 用于将 il 编译成 dll,所以两者配合使用挺好的。

  • ildasm 路径:C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\ildasm.exe

  • ilasm  路径:C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ilasm.exe

2. 使用 ildasm 导出 il文件

打开 ildasm, 点击 '文件' -> '转储' 生成 il 文件,这里我指定名称为 my.il,接下来就可以在 my.il 中将 # 改成 ' ,如下图:

3. 使用 ilasm 编译 il 文件

使用 ilasm 将 my.il 重新生成 ConsoleApp2.exe 即可。


E:\net5\ConsoleApp2\ConsoleApp2\bin\Debug>ilasm my.il my.res /output=ConsoleApp2.exe /exeMicrosoft (R) .NET Framework IL Assembler.  Version 4.8.3752.0
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembling 'my.il'  to EXE --> 'ConsoleApp2.exe'
Source file is UTF-8Assembled method ConsoleApp2.Program?<>c__DisplayClass1_0::.ctor
Assembled method ConsoleApp2.Program?<>c__DisplayClass1_0::<QueryDataTable>b__0
Assembled method ConsoleApp2.Program?<QueryDataTable>d__1::.ctor
Assembled method ConsoleApp2.Program?<QueryDataTable>d__1::MoveNext
Assembled method ConsoleApp2.Program?<QueryDataTable>d__1::SetStateMachine
Assembled method ConsoleApp2.Program::Main
Assembled method ConsoleApp2.Program::QueryDataTable
Assembled method ConsoleApp2.Program::.ctorAssembling 'my.res'  to EXE --> 'ConsoleApp2.exe'
Source file is UNICODECreating PE fileEmitting classes:
Class 1:        ConsoleApp2.Program
Class 2:        ConsoleApp2.Program?>c__DisplayClass1_0
Class 3:        ConsoleApp2.Program?QueryDataTable>d__1Emitting fields and methods:
Global
Class 1 Methods: 3;
Class 2 Fields: 2;      Methods: 2;
Class 3 Fields: 6;      Methods: 3;
Resolving local member refs: 44 -> 44 defs, 0 refs, 0 unresolvedEmitting events and properties:
Global
Class 1
Class 2
Class 3
Method Implementations (total): 2
Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved
Writing PE file
Operation completed successfullyE:\net5\ConsoleApp2\ConsoleApp2\bin\Debug>ilasm my.il my.res /output=ConsoleApp2.exe /exeMicrosoft (R) .NET Framework IL Assembler.  Version 4.8.3752.0
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembling 'my.il'  to EXE --> 'ConsoleApp2.exe'
Source file is UTF-8Assembled method ConsoleApp2.Program?<>c__DisplayClass1_0::.ctor
Assembled method ConsoleApp2.Program?<>c__DisplayClass1_0::<QueryDataTable>b__0
Assembled method ConsoleApp2.Program?<QueryDataTable>d__1::.ctor
Assembled method ConsoleApp2.Program?<QueryDataTable>d__1::MoveNext
Assembled method ConsoleApp2.Program?<QueryDataTable>d__1::SetStateMachine
Assembled method ConsoleApp2.Program::Main
Assembled method ConsoleApp2.Program::QueryDataTable
Assembled method ConsoleApp2.Program::.ctorAssembling 'my.res'  to EXE --> 'ConsoleApp2.exe'
Source file is UNICODECreating PE fileEmitting classes:
Class 1:        ConsoleApp2.Program
Class 2:        ConsoleApp2.Program?>c__DisplayClass1_0
Class 3:        ConsoleApp2.Program?QueryDataTable>d__1Emitting fields and methods:
Global
Class 1 Methods: 3;
Class 2 Fields: 2;      Methods: 2;
Class 3 Fields: 6;      Methods: 3;
Resolving local member refs: 44 -> 44 defs, 0 refs, 0 unresolvedEmitting events and properties:
Global
Class 1
Class 2
Class 3
Method Implementations (total): 2
Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved
Writing PE file
Operation completed successfully

可以看到,最后编译成 exe 成功,双击 ConsoleApp2.exe 可以看到最新的成果。

四:总结

本篇介绍了两种修改 dll 的方式,其实实操起来我感觉 ildasm & ilasm 的方式更灵活一点,如果大家有更好的反编译修改的方式,欢迎留言讨论哈!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

离线语音识别软件_从音乐识别软件起家,这家公司如何备战车载AI语音市场GGAI对话...

加入高工智能汽车专业行业群(自动驾驶5群&#xff0c;车联网智能座舱3群&#xff0c;智能网联商用车2群)&#xff0c;加微信&#xff1a;17157613659&#xff0c;出示名片&#xff0c;仅限智能网联汽车软硬件供应商及OEM厂商。早在2016年&#xff0c;亚马逊推出的语音助手Alexa…

int函数在Oracle,vb中int是什么意思 ?

VB语言中int函数的意思是取整数。即&#xff1a;int(x)函数是取不大于x的最大整数。例如&#xff1a;1、int(4.88)4int(4.88)即是取一个不大于4.88且最接近4.88的整数&#xff0c;所以int(4.88)4。2、int(8.1)8int(8.1)即是取一个不大于8.1且最接近8的整数&#xff0c;所以int(…

windows如何添加本机dns记录_运维必看!超清晰的 DNS 原理入门指南

来源&#xff1a;阮一峰的网络日志作者&#xff1a;阮一峰链接&#xff1a;http://www.ruanyifeng.com/blog/2016/06/dns.htmlDNS 是互联网核心协议之一。不管是上网浏览&#xff0c;还是编程开发&#xff0c;都需要了解一点它的知识。本文详细介绍DNS的原理&#xff0c;以及如…

天际数见数据质量巡检架构优化

源宝导读&#xff1a;天际数见平台是一个数据可视化的BI平台&#xff0c;定位于为高层决策提供数据可视化赋能。数据准确性是生命线&#xff0c;如何提前发现数据问题&#xff0c;快速定位和修复问题&#xff0c;成为我们必须攻克的难点。本文将介绍数见平台通过架构优化&#…

db2 删除存储过程_蚂蚁金服OceanBase挑战TPCC | TPCC基准测试之存储优化

蚂蚁金服自研数据库 OceanBase 登顶 TPC-C 引起业内广泛关注&#xff0c;为了更清楚的展示其中的技术细节&#xff0c;我们特意邀请 OceanBase 核心研发人员对本次测试进行技术解读&#xff0c;共包括五篇&#xff1a;1)TPC-C基准测试介绍2)OceanBase如何做TPC-C测试3)TPC-C基准…

Github Actions 中 Service Container 的使用

Github Actions 中 Service Container 的使用Intro之前写过一个 StackExchange.Redis 的一个扩展&#xff0c;测试项目依赖 redis&#xff0c;所以之前测试一直只是在本地跑一下&#xff0c;最近通过 Github Action 中的 Service Container 来通过 CI 来跑测试&#xff0c;分享…

深度探秘.NET 5.0

2020 中国.NET 开发者峰会正式启动 &#xff0c;欢迎大家提交演讲主题或者购买超级早鸟票。今年11月10号 .NET 5.0 如约而至。这是.NET All in one后的第一个版本&#xff0c;虽然不是LTS(Long term support)版本&#xff0c;但是是生产环境可用的。微软从.NET 5 Preview 1就开…

vuex保存用户信息_Vuex状态管理

一个组件可以分为数据和视图&#xff0c;数据更新时&#xff0c;视图也会自动更新。在视图中又可以绑定一些事件&#xff0c;它们触发methods里面指定的方法&#xff0c;从而又可以改变数据、更新视图&#xff0c;这就是一个组件基本的运行模式。但实际的业务中&#xff0c;经常…

使用 docker 构建分布式调用链跟踪框架skywalking

一旦你的程序docker化之后,你会遇到各种问题&#xff0c;比如原来采用的本地记日志的方式就不再方便了&#xff0c;虽然你可以挂载到宿主机&#xff0c;但你使用 --scale 的话&#xff0c;会导致记录日志异常&#xff0c;所以最好的方式还是要做日志中心化&#xff0c;另一个问…

excel同一单元格怎么换行_excel表格内怎么换行 方法有两种 一看就会 新手教程...

很多人在用excel表格的时候都需要用到换行&#xff0c;但是有一些小伙伴还不知道如何去换行。今天就介绍两种单元格内换行的方法&#xff0c;这两种换行方式的效果不一样&#xff0c;大家可以根据自己的需求来选择使用哪种换行方式。方法一&#xff1a;单元格内自动换行操作&am…

持续交付一:从开发到上线的环境

团队开发中&#xff0c;开发&#xff0c;测试&#xff0c;预发布&#xff0c;生产&#xff0c;不同的角色工作在不同的环境中&#xff0c;不同的环境有不同的作用(有些公司的环境更多&#xff0c;按照自己的交付流程设计)&#xff0c;当然不同的环境&#xff0c;配置也不能相同…

win10控制面板快捷键_你没玩过的全新版本 Win10这些操作你知多少

不知不觉&#xff0c;Win10与我们相伴已经整整四个年头了&#xff0c;从最开始的组团抗拒到现在的默默接受&#xff0c;个中滋味相信谁心里都有个数。近日微软开始推送“Win10更新五月版”&#xff0c;那么Win10中到底都有哪些“骚”操作&#xff1f;一起来看看吧。1、夜间模式…

C# 中的数字分隔符 _

编写 C# 代码时&#xff0c;我们时常会用到很大的数字&#xff0c;例如下面定义的变量&#xff1a;const long loops 50000000000;您能快速读出这是多少吗&#xff1f;是不是还是会有很多人把光标定位到最后一位&#xff0c;然后按键盘上的向左键一个一个往上数&#xff1a;个…

数字调制系统工作原理_空间光调制器工作原理是什么 空间光调制器工作原理...

空间光调制器(SLM), 空间光调制器(SLM)工作原理是什么?实时空间光调制器使得相干处理系统能输入非相干光图像和随时间变化的图像的器件。相干光处理系统的最大优点是二维平行处理、信息容量大&#xff0c;运算速度快。但是目前的输入图像和空间滤波都用银盐胶片作记录媒质&…

使用 .NET 5 体验大数据和机器学习

2020 中国.NET 开发者峰会正式启动 &#xff0c;欢迎大家提交演讲主题或者购买超级早鸟票。翻译&#xff1a;精致码农-王亮原文&#xff1a;http://dwz.win/XnM.NET 5 旨在提供统一的运行时和框架&#xff0c;使其在各平台都有统一的运行时行为和开发体验。微软发布了与 .NET 协…

linux监控目录容量,利用ZABBIX监控某个目录大小

近期&#xff0c;因为JMS的消息堆积导致ApacheMQ频率故障(消息没有被消费掉&#xff0c;导致其数据库达到1.2G&#xff0c;JMS此时直接挂掉)&#xff0c;很是郁闷&#xff01;刚好自己在研究zabbix.既然zabbix如此强大&#xff0c;那么它可以监控我的这个目录大小吗&#xff1f…

三菱plc选型手册_模拟量是什么?PLC和模拟量是如何转换的?

模拟量在PLC系统中有着非常广泛的应用&#xff0c;特别是在过程控制系统中。模拟量是一种连续变化的量&#xff0c;因此&#xff0c;它的使用对象也是各种连续变化的量&#xff0c;比如温度&#xff0c;压力&#xff0c;湿度&#xff0c;流量&#xff0c;转速&#xff0c;电流&…

windows和linux命令行一样吗,微软改进Windows命令行 目的是和Linux命令行相抗衡

微软官方人员承认微软正在对Windows命令行环境或是Windows终端进行全方位的改进&#xff0c;目的是能和Linux命令行相竞争。随着Linux云服务器的大量被采用&#xff0c;很多Linux云服务器都没有安装图形界面&#xff0c;只使用终端能够大幅度提高运行速度&#xff0c;微软想通过…

vue 离开页面事件_【必看】58 道 Vue 常见面试题集锦,涵盖入门到精通,自测 Vue 掌握程度...

△ 是新朋友吗&#xff1f;记得先点web前端学习圈关注我哦&#xff5e;1.vue优点&#xff1f;答&#xff1a;轻量级框架&#xff1a;只关注视图层&#xff0c;是一个构建数据的视图集合&#xff0c;大小只有几十 kb &#xff1b;简单易学&#xff1a;国人开发&#xff0c;中文文…

购票啦 | 2020中国.NET开发者峰会启动

.NET Conf China 2020去年2019年在上海举行了第一届的中国.NET开发者峰会&#xff0c;今年2020年即将在苏州举行第二届&#xff0c;有兴趣的童鞋们&#xff0c;不要忘记购票参加哈。 1大会背景介绍2014年微软组织并成立.NET基金会&#xff0c;微软在成为主要的开源参与者的道路…