如何破解.net软件
.net sdk中有不少很强大的工具,可以轻易完成对.net程序的破解,只要你懂得一点IL语言就行。现在以一个 M 软件为例,介绍整个破解过程。
第零步:用反编译工具分析软件的可执行文件,制订破解逻辑。
我以"M"来称呼这个软件。首先,要搞明白M的注册原理。M是通过输入注册码来完成注册的,为了破解它,要先搞明白它注册的原理,这就必须用反译工具来分析它。
我用的反编译工具是.net reflactor,可以用它打开.net的可执行文件,看到C#源代码。打开之后,经过一番寻找,发现的注册窗口的事件处理过程所在,然后一直找到了它的注册校验程序。如下:
MarkdownPad2.Licensing.LicenseEngine.VerifyLicense(String, String) : Boolean
public bool VerifyLicense(string licenseKey, string email)
{
if (string.IsNullOrEmpty(licenseKey) || string.IsNullOrEmpty(email))
{
return false;
}
try
{
this.License = this.Decrypt(licenseKey);
this.LicenseProcessed = true;
}
catch (Exception exception3)
{
...
return false;
}
if (((this.License == null) || (this.License.Email == null)) || (this.License.Product == null))
{
return false;
}
bool flag = this.License.Email.Equals(email, StringComparison.OrdinalIgnoreCase);
bool flag2 = this.License.Product == "MarkdownPad2";
return (flag && flag2);
}
在窗口中输入的email和key都被送到这里,其中Key通过Decrypt方法进行解密,直接生成了一个License对象,这个对象的定义如下:
namespace MarkdownPad2.Licensing
{
using System;
using System.Runtime.CompilerServices;
public class License
{
public DateTime CreationDate { get; set; }
public string Email { get; set; }
public int LicenseTypeId { get; set; }
public string Name { get; set; }
public string Product { get; set; }
}
}
看来就是注册信息的内存对象了。那么,再看看生成这个对象的那个Decrypt方法:
private License Decrypt(string payload)
{
RSA rSA = CryptoKey.FromPublicKey(
"-----BEGIN PUBLIC KEY-----\nMIIB...pQIDAQAB\n-----END PUBLIC KEY-----",
"2QJmLPD5ktxIrFkr")
.GetRSA();
byte[] msg = Convert.FromBase64String(payload);
byte[] bytes = rSA.PublicDecrypt(msg, RSA.Padding.PKCS1);
string str = Encoding.Default.GetString(bytes);
IRestResponse response = new RestResponse {
Content = str
};
License license = new JsonDeserializer().Deserialize<License>(response);
rSA.Dispose();
return license;
}
研究一下就能明白,这个程序就是通过一个指定公钥的rsa解密器,对传入的Base64字符进行解密,解密之后的内容是一个Json格式的文本符串,这个文本串直接反序列化就是License对象了。
破解的办法有下列几个:
- 把 VerifyLicense 改掉,直接返回一个true。
- 这个方法我其实用过了,但是发现了一个问题,就是软件一启动总是会出现一个nullException,原因应该是在启动时软件检查是否注册,然后改过的方法给它返回了个true,但它兴致勃勃地去检查注册的信息时,没料到是个空的。
- 解决办法就是去修改c:\users<用户名>\AppData\Local<产品名><文件名><版本号>\user.config文件,把注册信息写进去,但是注册信息还是要符合解密要求才行。所以我不采用这个方式。
- 写一个注册码生成器,用对应的私钥生成符合程序要求的注册码,这样不用改程序。
- 问题在于,我们没有这个公钥对应的私钥,没办法做注册信息之后再加密。
- 解决办法自己生成一个新的RSA密码对,然后把程序的公钥替换了,用对应的私钥写注册机。那么还是要改程序了?意义不大,算了不用这个办法。
- 改掉Decrypt方法,把解密的过程跳过,让它支持明文注册信息,然后就随我的意输入了。就用这个办法了!
方案确定,现在开始修改程序。
第一步:用ildasm来反编译EXE或是DLL文件到IL源代码。
ildasm是.net自带的反编译IL的工具。我用ildasm打开M.exe文件,看到里面的命名空间、类名什么的了,然后选择菜单里的“转储”,选择一个空的目录——注意,会生成一堆文件的,所以要用空的目录——,确认,IL文件与资源文件就保存到那里了。
由于我们只要动一点点代码,其他的都不要动的,所以,只需要注意m.il文件就行了。
第二步:修改il文件。
用你喜欢的文本编辑器打开m.il文件,找到我们打算要修改的Decrypt方法,哇,这个在C#里只有几行方法,在IL里好长呀!
再回来看看这个方法的c#版:
private License Decrypt(string payload)
{
RSA rSA = CryptoKey.FromPublicKey(
"-----BEGIN PUBLIC KEY-----\nMIIB...pQIDAQAB\n-----END PUBLIC KEY-----",
"2QJmLPD5ktxIrFkr")
.GetRSA();
byte[] msg = Convert.FromBase64String(payload);
byte[] bytes = rSA.PublicDecrypt(msg, RSA.Padding.PKCS1);
string str = Encoding.Default.GetString(bytes);
IRestResponse response = new RestResponse {
Content = str
};
License license = new JsonDeserializer().Deserialize<License>(response);
rSA.Dispose();
return license;
}
我们要把它改为这样:
private License Decrypt(string payload)
{
IRestResponse response = new RestResponse {
Content = payload
};
JsonDeserializer deserializer = new JsonDeserializer();
return deserializer.Deserialize<License>(response);
}
现在,硬起头皮,看看IL代码,发现并不太难,比如说起头这段:
.locals init (
class [ManagedOpenSsl]OpenSSL.Crypto.CryptoKey V_0,
class [ManagedOpenSsl]OpenSSL.Crypto.RSA V_1,
uint8[] V_2,
uint8[] V_3,
string V_4,
class [RestSharp]RestSharp.IRestResponse V_5,
class [RestSharp]RestSharp.Deserializers.JsonDeserializer V_6,
class MarkdownPad2.Licensing.License V_7)
这就是局部变量的定义啦,它们按位置编号,从0开始。
然后对着c#看,就是几个ldXXX指令(ldstr:压栈字串常量;ldloc:压栈局部变量,ldarg:压栈本方法参数)准备参数,一个call调用方法,如有返回值,就用stloc保存到第N号变量里。
IL_0000: ldstr "-----BEGIN PUBLIC KEY-----\nMI...QAB\n-----END PUBLIC KEY-----"
IL_0005: ldstr "2QJmLPD5ktxIrFkr"
IL_000a: call class [ManagedOpenSsl]OpenSSL.Crypto.CryptoKey [ManagedOpenSsl]OpenSSL.Crypto.CryptoKey::FromPublicKey(string, string)
IL_000f: stloc.0
看懂了吧?后面的也都一样。我们一直找到new RestResponse的地方,
IL_0034: newobj instance void [RestSharp]RestSharp.RestResponse::.ctor()
IL_0039: stloc.s V_5 //new 的返回值赋值给V_5局部变量。
IL_003b: ldloc.s V_5 //第0个参数是this指针。
IL_003d: ldloc.s V_4 //set方法的参数,现在取的是V_4,也就是str局部变量
IL_003f: callvirt instance void [RestSharp]RestSharp.IRestResponse::set_Content(string)
我们只需要把 IL_003d: ldloc.s V_4 改为 IL_003d: ldarg.1 ,就把payload参数直接给了response.Content了。
IL_0034: newobj instance void [RestSharp]RestSharp.RestResponse::.ctor()
IL_0039: stloc.s V_5
IL_003b: ldloc.s V_5
IL_003d: ldarg.1
IL_003f: callvirt instance void [RestSharp]RestSharp.IRestResponse::set_Content(string)
前面的RSA解密代码如果不删除,它们会对将放进来的明文进行解密,会引起异常,我们就把它们都注释了吧!也就是初始化局部变量之后到IL_0034之前的代码都全部删除。而最后还有一个RSA.dispose(),它对应的IL代码如下,也一并删除:
IL_0056: ldloc.1
IL_0057: callvirt instance void [ManagedOpenSsl]OpenSSL.Core.Base::Dispose()
还有,由于有4个局部变量没有被使用,所以也要在init里把它们删除,不然会造成程序运行时的堆栈出错。
最后检查程序里的变量引用序号是不是需要调整。最后的程序是这样:
.method private hidebysig instance class MarkdownPad2.Licensing.License
Decrypt(string payload) cil managed
{
// 代码大小 95 (0x5f)
.maxstack 3
.locals init (
class [RestSharp]RestSharp.IRestResponse V_5,
class [RestSharp]RestSharp.Deserializers.JsonDeserializer V_6,
class MarkdownPad2.Licensing.License V_7)
IL_0034: newobj instance void [RestSharp]RestSharp.RestResponse::.ctor()
IL_0039: stloc.s V_5
IL_003b: ldloc.s V_5
IL_003d: ldarg.1
IL_003f: callvirt instance void [RestSharp]RestSharp.IRestResponse::set_Content(string)
IL_0044: newobj instance void [RestSharp]RestSharp.Deserializers.JsonDeserializer::.ctor()
IL_0049: stloc.s V_6
IL_004b: ldloc.s V_6
IL_004d: ldloc.s V_5
IL_004f: callvirt instance !!0 [RestSharp]RestSharp.Deserializers.JsonDeserializer::Deserialize<class MarkdownPad2.Licensing.License>(class [RestSharp]RestSharp.IRestResponse)
IL_0054: stloc.s V_7
IL_005c: ldloc.s V_7
IL_005e: ret
} // end of method LicenseEngine::Decrypt
第三步:用ilasm来重新编译exe文件。
ilasm是一个.net sdk里的命令行工具,用来编译il文件。在命令行里执行下面的命令,M.exe就被重新生成了:
ilasm /exe /resource=M.res /output=M.exe M.il
注意,M.exe里的程序还有很多图片之类的资源,在反编译时,这些资源文件也会被抽出来放到这里,所有的资源都会在m.res文件里描述。在重新编译时,只需要如上面例子里的那样/resource=M.res就行了。
好,把破解过的M.exe放回到原来的目录里,替换原版的程序,然后执行之。
选择注册,在注册码框里输入json格式的明文:
{"CreationDate":"2014-12-11T06:06:54.0068849Z",
"Email":"***@qq.com",
"LicenseTypeId":1,"Name":"myname",
"Product":"Msoftware"}
这个JSON数据是根据License对象的成员而编写的。现在我们知道这个字串会被直接反序列化为一个妥妥的License对象。
一按OK……
成功!您现在的所有使用限制已被解除。
如何破解.net软件的更多相关文章
- 在Windows10中破解一些软件
在Windows10中破解一些软件 一.前言 以前的windows是很好破解的,这里说的windows包含了windows的一些产品,比如说office,visio等等,可是自从到了新版的wind ...
- 使用Dede破解Delphi软件实战
昨日练习了一把如何破解Delphi软件.下面和大家分享一下破解的过程,对初学者,希望有授之以渔的作用. 首先分析我们的目标软件,不要问我破解的是什么软件.保护知识产权,要从娃娃抓取. 目标软件是一个销 ...
- 深入理解.NET程序的原理 谈一谈破解.NET软件的工具和方法
最近一段时间不忙,闲下来的空闲时间,重读了一下CLR的原理,回味一下有关程序集的的知识,顺便练了一下手,学习致用,破解了若干个.NET平台的软件.以此来反观.NET程序开发中,需要注意的一些问题. 基 ...
- 2018.4.8 Mac/Win 破解StartUml软件
Mac破解 在桌面选择前往----前往文件夹-----输入"/应用程序/StarUML.app/Contents/www/license/node/LicenseManagerDomain. ...
- PowerBuilder 这么古老的语言(破解一软件)
PowerBuilder 这么古老的语言,编辑器用的6.5的好古老的气息,好吧破解木有兴趣了, 不过嘛可以说一下破解思路,这个系统使用的是圣天狗,联网版的. 复制狗(暴力,没技术味道) 模拟狗(也是 ...
- 【krpano】krpano xml资源解密(破解)软件说明与下载(v1.4)
欢迎加入qq群551278936讨论krpano技术以及获取最新软件. 该软件已经不再维护,现在已经被KRPano资源分析工具取代,详情参见 http://www.cnblogs.com/reac ...
- 【krpano】krpano xml资源解密(破解)软件说明与下载(v1.3)
欢迎加入qq群551278936讨论krpano技术以及获取最新软件. 该软件已经不再维护,现在已经被KRPano资源分析工具取代,详情参见 http://www.cnblogs.com/reac ...
- 【krpano】krpano xml资源解密(破解)软件说明与下载(v1.2)
欢迎加入qq群551278936讨论krpano技术以及获取最新软件. 该软件已经不再维护,现在已经被KRPano资源分析工具取代,详情参见 http://www.cnblogs.com/reac ...
- 【krpano】krpano xml资源解密(破解)软件说明与下载
欢迎加入qq群551278936讨论krpano技术以及获取最新软件. 最新版本软件下载:http://www.cnblogs.com/reachteam/p/5455675.html 该软件已经 ...
随机推荐
- Ionic + Cordova 跨平台移动开发环境配置
1.下载安装JDK(根据各自系统选择32位或64位下载),安装完成之后需要做以下环境变量配置 在“系统变量”中,设置3象属性,JAVA_HOME,PATH,CLASSPATH(大小写无所谓),如果已经 ...
- JavaScript基本语法(五)
BOM 浏览器对象模型 BOM (浏览器对象模型),它提供了与浏览器窗口进行交互的对象. 一.window对象 Window对象表示整个浏览器窗口. 所有浏览器都支持 window 对象.它表示浏览器 ...
- iOS 苹果开发证书失效的解决方案(Failed to locate or generate matching signing assets)
从2月14日开始,上传程序的同学可能会遇到提示上传失败的提示. 并且打开自己的钥匙串,发现所有的证书全部都显示此证书签发者无效. 出现以下情况: Failed to locate or generat ...
- centos虚拟机复制移动后网络配置无效
移植Centos虚拟机后无法联网解决1.迁移以后,会存在其中一个网卡无法启动(eth0 or eth1) [root@ ~]# ifup eth0 WARNING: Deprecated config ...
- SharePoint 2013 网站搜索规则的使用示例
前言 SharePoint 2013搜索中,有一个非常好用的细化搜索结果的功能,就是“查询规则”.可以通过对于某些特定查询时,起到细化显示结果的作用.下面,我们简单的介绍一下该功能的使用和效果. 1. ...
- sqlite 管理软件
★SQLite的官方网站 http://www.sqlite.org/ ★SQLite的官方网址提供数据库查看软件:http://www.sqlite.org/cvstrac/wiki?p=Manag ...
- OC #import和@class的用法和区别
OC #import和@class的用法和区别 import会包含这个类的所有信息,包括实体变量和方法,而@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑, ...
- IOS开发之Bug--使用KVC的易错情况
1.其实某些角度而言KVC是一个破坏封装又暴力的做法,而我已经两次因为KVC而导致应用程序出现闪退的情况. 场景:1.使用KVC修改某一个UIView的属性,比如width. 2.在viewWi ...
- php关键词替换的类(避免重复替换,保留与还原原始链接)
转载:http://www.169it.com/blog_article/601549531.html 本节主要内容:一个关键词替换的类 主要可以用于关键词过滤,或关键词查找替换方面. 实现过程分析: ...
- cms真实问题的来源以及模拟解决方案
先来描述一下cms问题的来源: 初始需求: 在开发的过程中有这样的一个处理时间显示的需求: 如果时间小于1分钟显示秒, 如果时间小于1小时显示分钟, 如果时间小于1天显示小时, 如果大于1天显示日期. ...