用dnSpy破解某旅游系统5.2版。
某系统是网上最常见也是目前最好用的旅游站系统之一,5.1版本之前采用的maxtocode加壳后可以用de4dot反混淆后破解。5.1版本以后用de4dot无法脱壳。
本文仅限学习和讨论,请勿做侵权使用。
在这里说一种不脱壳破解的办法,我们分析早期版本的授权验证方式,以5.0为例,我们看下install的验证方法:
1 2 3 4 5 6 7 8 9 | if (!flag || step2.smethod_0( this .key, lower)) { //此处为安装代码,省略... this .Response.Redirect( "step3.aspx" ); } else { this .ClientScript.RegisterStartupScript( this .GetType(), "" , "<script language='javascript'>alert('注册码错误!');</script>" ); } |
1 2 3 4 5 | public static bool smethod_0( string string_0, string string_1) { string str = "髆@b驖b~!蘯鸛0&饕)" ; return ((string_0.Equals(Utils.MD5( string .Concat( "ωāр" , string_1, str), 32).ToLower()) || string_0.Equals(Utils.MD5( string .Concat(string_1, str), 32).ToLower()) ? true : false ) ? true : false ); } |
可以看出使用了一个Key和域名MD5以后生成序列号进行验证。所以只要找到Key就可以算出序列号。
在不脱壳的前提下,如何找到这个Key?
我们再分析TourEx.Pages.Dll 找到 BasePage
1 2 3 4 5 6 7 8 9 | private static void old_acctor_mc() { __ENCList = new List<WeakReference>(); LineOrderLock = RuntimeHelpers.GetObjectValue( new object ()); OrderLock = RuntimeHelpers.GetObjectValue( new object ()); WriteLock = RuntimeHelpers.GetObjectValue( new object ()); checkkey = "髆@b驖b~!蘯鸛0&饕)" ; includeWap = false ; } |
当然这是分析旧版本脱壳后的代码,如果没有脱壳,就通过反射调用BasePage后输出checkkey,就可以得到。
然后,我们悲催的发现5.1以后checkkey不见了,写在了方法内部,这样是没法通过反射读出来的。
到这里,我们不得不介绍下dnSpy这款神器,这款神器是de4dot的作者开发,可以动态调试.net的EXE,非常强大。
我们先分析BasePage中的验证方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // TourEx.Pages.BasePage // Token: 0x0600005B RID: 91 RVA: 0x00007684 File Offset: 0x00005884 public static bool smethod_0() { bool result; if (HttpContext.Current.Server.MapPath(HttpContext.Current.Request.Url.AbsolutePath).IndexOf( "wap" ) != -1) { if (!(result = (Operators.CompareString(BaseConfig.WebKey, TourEx.Common.Utils.MD5( "ωāр" + BaseConfig.WebDomain + BasePage.checkkey, 32).ToLower(), false ) != 0))) { BasePage.includeWap = true ; } } else if (result = (Operators.CompareString(BaseConfig.WebKey, TourEx.Common.Utils.MD5( "ωāр" + BaseConfig.WebDomain + BasePage.checkkey, 32).ToLower(), false ) != 0)) { result = (Operators.CompareString(BaseConfig.WebKey, TourEx.Common.Utils.MD5(BaseConfig.WebDomain + BasePage.checkkey, 32).ToLower(), false ) != 0); } else { BasePage.includeWap = true ; } return result; } |
这个方法返回了验证结果和includeWap,我尝试用dnSpy写了IL代码
1 | 发现保存的时候失败了。 |
1 | <br>既然我们找对了地方,那就可以想别的办法,dnSpy有个很牛X的HEX编辑功能,可以找到方法对应的十六进制代码<br><br> |
1 | 用旧的版本修改IL代码,找到相关的十六进制分复制过来保存后,发现代码成功修改了! |
1 |
1 | 测试成功打开网页,破解完成。<br>这个只是一个思路了,破解之道在于坚持不泄,找到洞洞,然后注入精华代码。。嗯,就是这么回事了~看起来是不是自然万物是不是都一样的道理?扯远了。。 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库