ANTS Profiler(for .net)的分析、调试及破解(来自互联网)
【文章标题】: ANTS Profiler(for .net)的分析、调试及破解【文章作者】: 来自互联网
【作者主页】: 来自互联网
【软件名称】: ANTS Profiler
【下载地址】: 自己搜索下载
【保护方式】: 混淆+强命名+RSA
【使用工具】: Reflector,Pebrowse,snremove,UltraEdit
【操作平台】: .Net v1.1
【作者声明】: 第一次用破文生成器,8错!
--------------------------------------------------------------------------------
【详细过程】
ANTS Profiler的主要功能如下:
"Code profile .NET applications
"Profile application memory use
"Profile both .NET desktop applications and ASP.NET web applications
"Optimize your code
不废话了,直接来过程。
先运行一下,提示14天试用期,输入序列号。如果输入错误的序列号则提示Please enter a valid serial number"。用Reflector打开试试,运气好,发现软件混淆强度较弱(只有少部分使用了不可打印字符),再查发现有强命名。
目录下有两个文件很可疑,RedGate.Licensing.Client.dll和RedGate.Licensing.Helper.dll(发现这两个文件一是看目录下的文件名,二是调试时会发现有这两个模块,见下节)。同样,用Reflector载入。搜索字符串"valid serial",很容易就来到了判断序列号的地方。(晕,关键的东东不混淆,而且敏感字符串以明文出现,好久没遇到这么爽的.Net程序了。)
代码:
try { string text1 = this.?.Text.ToUpper().Trim(); if (text1 == "I NEED MORE TIME") { if (this.?.?()) { this.?((?.?) 6); return; } MessageBox.Show("Your trial could not be extended", "Trial extension failure", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } this.?.SerialNumber = this.?.Text; } catch (?) { MessageBox.Show("Please enter a valid serial number", "Invalid serial number", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } 虽然有不少不可打印字符,但并不影响分析。从代码中看出输入错误的序列号会抛出异常。下面是找序列号的计算代码。(这里还有个字符串"I NEED MORE TIME",这是延长试用期的,结合注册表可以不破解直接无限使用,已经发过帖子了。)
找序列号的比较代码有两种方法,一种是在PeBrowse中下断,动态调试找到地方,当时我用的这个方法,这里只简单的说一下。用PeBrowse载入(对于含有不可打印字符的程序,ildasm后的源代码往往不能用ilasm再编译,用WinDbg不方便,还是直接调试方便),在相应的dll处对所有的方法下断(因为暂时不知道是哪个方法计算序列号),见下图,红色圈中的就是前文提到的可疑dll。不再多说了,大家自已试,因为这个程序静态完全可以跟出来。
第二是Reflector中直接分析。注意这句:
this.?.SerialNumber = this.?.Text;
点击"SericalNumber",来到它的定义处
代码:
public string SerialNumber { get { return this.?; } set { value = value.Trim(); if (!Licence.?(value, this.?)) { throw new ?(); } this.? = value; } } 这里明显调用的是set。代码的意义非常明显,如果License判断序列号是错的,就throw一个异常,这正好被刚才的catch捕捉到,显示invalid serial的窗口。那我们点击Licence.XX(某不可见字符,呵呵),终于,找到了:
代码:
private static bool ?(string text5, int num1) { text5 = text5.ToUpper().Trim(); Regex regex1 = new Regex(@"{2}-{1}-{1}-/d{5}-{4}"); Regex regex2 = new Regex(@"/d{3}-/d{3}-/d{6}-{4}"); if (regex1.IsMatch(text5)) { string text1 = text5.Substring(0, 12); string text2 = string.Format("{0:X4}", Licence.?(text1)); if (!text5.EndsWith(text2)) { return false; } } else { if (!regex2.IsMatch(text5)) { return false; } string text3 = text5.Substring(0, 14); string text4 = string.Format("{0:X4}", Licence.?(text3)); if (!text5.EndsWith(text4)) { return false; } if (Convert.ToInt32(text5.Substring(0, 3)) != num1) { return false; } } return true; } 还是正则表达式。这里不多说了,不明白的可以看编程文档。分析一下就知道序列号的格式,{2}-{1}-{1}-/d{5}-{4},而且前14位计算的值等于末尾4位。这里给出一个,以便我们继续分析:AA-0-0-12345-5C3B。
输入序列号后,可以继续了,发现原来还要激活,不然还是试用14天。选择用Email激活(网络激活不好搞),然后会让你输入激活的代码。随便输入一些,提示"The activation response is not in the correct format"。就以这为关键词搜,来到这里。
代码:
private bool ?(XmlDocument document1, ref Licence.? ?Ref1) { XmlNodeList list1 = document1.GetElementsByTagName("data"); XmlNodeList list2 = document1.GetElementsByTagName("signature"); if ((list1.Count != 1) || (list2.Count != 1)) { ?Ref1.? = "The activation response is not in the correct format"; return false; } string text1 = list1.OuterXml; string text2 = list2.InnerXml; if (text2.Length != 0) { ?Ref1.? = "The activation response does not contain a digital signature"; return false; } RSACryptoServiceProvider provider1 = new RSACryptoServiceProvider(); string text3 = "<RSAKeyValue><Modulus>zLizNmLUd4VlIWee1GXgn/KxEwcghPASQ+NUzZhbY2fTGzpW64T6yEOdHlIbhX1DX6yAz2gMZKfnpQL2aFqxh5ACFV9dONSTzuQzkqeXwFEARsMxGP3eTQSWMpwVhEcraSn1zOqMb3CRDeQpgasq0lv4HRFhbwalOifKarjEL/8=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"; provider1.FromXmlString(text3); byte[] buffer1 = Convert.FromBase64String(text2); byte[] buffer2 = Encoding.UTF8.GetBytes(text1); if (provider1.VerifyData(buffer2, new SHA1Managed(), buffer1)) { ?Ref1.? = "The activation response contains an incorrect digital signature"; return false; } ?Ref1.? = false; 晕,有RSA,我功力不行,只能爆破了。不过这里爆破范围和爆破点的选择还是很有技巧的,详见下文。大概分析一下代码,看来激活信息是XML格式,大至如下:
<activationresponse>
<data>
XXXX
</data>
<signature>
YYYY
</signature>
</activationresponse>
而且YYYY必须的字符数必须是4的倍数,为啥?因为Convert.FromBase64String(text2),不信你可以试试。我们就按上面的样式输入,又有新提示:The activation response does not match the registration properties。看来这里还不是最终验证的地方,还得找。
这里有个使用Reflector的小技巧,操作见图:先分析这个方法被哪些别的方法使用了,又使用了哪些别的方法。
这里我们找被使用的关系,然后点Go To Member,来到下面的代码处。这里才是关键呵。
代码:
private bool ?(XmlDocument document1) { Licence.? ?1 = new Licence.?(); if (!this.?(document1, ref ?1)) { throw new ?(?1.?); } if (((?1.? != this.?) || (?1.? != this.?)) || (?1.? != this.?)) { throw new ?("The activation response does not match the registration properties"); } if (!?1.?) { if (?1.? != this.?) { throw new ?("The activation response does not match the registration properties"); } if (Licence.?(?1.?, this.?)) { this.? = true; return true; } throw new ?("The activation response is for a different machine"); } if (?1.? != this.?) { throw new ?("The activation response is for a different session"); } this.?(true); return false; } 我们要在这里进行爆破,但怎么个爆破法呢?注意,该段代码中只有一个正确的返回点,就是
this.? = true;
return true;
我们的方法是让第一句Licence.? ?1 = new Licence.?();执行完后,不进行任何判断,直接执行上面的两句代码。对了,前面还有一处,就是RSA判断处的provider1.VerifyData也要改掉,这样才能进行到下面。
修改方法,在结合ILDASM的反汇编代码,在UltraEdit中定位。
第一处:
IL_00a4:/* 2D | 0E */ brtrue.s IL_00b4
将2D改为2C(brfalse.s)。物理偏移在0x3118h处。
第二处:
IL_0000:/* 73 | (06)00003B */ newobj instance void RedGate.Licensing.Client.Licence/*02000008*//'?'/*02000009*/::.ctor() /* 0600003B */
IL_0005:/* 0A | */ stloc.0
在物理偏移的0x2cb4处。紧接着这两句修改。原文件为
00002cbah: 02 03 12 00 28 29 00 00 ; ....()..
改为
00002cbah: 02 17 7D 38 00 00 04 17 ; ..}8....
即MSIL代码
ldarg.0
ldc.i4.1
stfld bool RedGate.Licensing.Client.Licence::'?'
ret
保存修改,运行。按格式输入注册码和激活信息,显示激活成功,不再提示有使用时间了。序列号生成器偶就不写了,很简单的算法。不知道什么时候才能搞定RSA。
仅供参考!
谢谢分享 支持楼主
页:
[1]