不知不觉,接触破解逆向已经三个月了,从当初的门外汉到现在的小白,这个过程只有经历过才知道其中的苦与乐:

有无知、困惑、痛苦、惊喜、彻悟、欣慰……

有无助的软件脱壳,茫然的代码分析,有无趣的反复测试,

有人说破解不应该程序员干的事,我回复我不是程序员;

有人说.NET程序太没难度了,去破安卓,后来我真开始研究起安卓来;

有人说能不能把支付宝破了,我没回答。

虽然很忙,时间少,但每天晚上都要抽些时间来关注52论坛,关注破解;虽然并没有从破解中获取物质利益,但我愿意将自己的心得或作品分享给大家。不管怎样,它将作为我的一门兴趣爱好继续发展下去。

本文为详细分析,新手们也可以尝试着做一下。

一、对象描述

作为GIS及相关专业,想必都接触过地图下载吧,市面上地图、影像下载工具都非常多,效果好的、差的,免费的、收费的……各有优劣。我曾经分析过一篇文章《那些年,我们用过的地图下载器》,需要的朋友可以去看看,今天我们的目标就是一个地图下载器——太乐地图下载器。

其官方网址是:http://www.arctiler.com/ ,最新版本是:太乐地图下载器 V4.9

还是那句老话:严格意义上来说,地图下载器已经触犯了地图服务商的权益(只不过别人没有来找你),有关方面不要给我留言或发邮件,如果这样,相当于干着侵权的事的人来指责其他侵犯自己的权益。

《计算机保护条例》中说了,单方面的免费声明是无效的,我还是要像地图下载器开发者一样做一个免责声明:本教程仅供研究学习,请在24小时之内删除相关软件、忘记相关内容

二、环境说明

操作系统:Win7 64位原版(由于笔记本配置太差,虚拟机都没装)

使用工具:de4dot 3.1(脱壳).NET Reflector8.5(主要分析工具)、Reflexil1.9(修改,它是.NET Reflector插件)、ILSpy2.1(调试)、VS(辅助分析、写注册机)。这些工具网上都能找到,这里就不用提供了吧。

三、详细流程

还是以前的原则,破解程序的大致流程是:试用脱壳-寻找关键-分析修改-调试发布。

01.安装试用

去官网下载安装,在帮助文档的说明中,分别说明了共了免费版、标准版、专业版和企业版,其功能与价格成正比。

试用,它是试用版,有功能限制,比如下载的等级、数据量大小等,这是一般的商业软件模式。在试用过程中,发现其限制的地方,为后面的寻找关键作好准备。

02.软件脱壳

脱壳是实际上一个有难度的活,由于我现在还是工具党,还用的脱.NET壳神器de4dot,(大家还有没有好的脱壳神器或手动脱壳的教程,分享一下呗)它的成功率应该有60%-70%左右。如果把它放在.NET Reflector8.5中出现"索引超出了数组界限"

它的脱壳结果有三种:一是脱壳后代码没有了混淆,程序可以运行,这是最好的结果;二是脱壳后代码还是有部分混淆,程序可以运行,这个结果也勉强能接受;三是脱壳后代码没有混淆,程序不可以运行,这也是最痛苦的(这多半要手动来脱壳)。

本程序遇到了两个关键文件AZMap.exe属于第一种, AZMap.Core.dll属于第三种,也就是说我不能对AZMap.Core.dl修改,只能修改AZMap.exe。

03.寻找关键

将脱壳后的AZMap.exe加到.NET Reflector,使用go to entry point和search是两种常用的入手方法,前者可以到达程序的main函数,然后可一步一步往下分析,后者找出与限制相关的地方,然后可一 一分析。

Main函数中,没有什么异样,直接进入即可。想一下,下一步,程序主界面出现后就知道你是试用版还是其他版本,这说明在主界面出现的过程中必定有函数或方面来检测版本问题,而MainForm里只有两个函数存在这样的效果:构造函数和Load函数(其他程序破解也有类似规律)

果然,MainForm的构造函数中调用了InitLicense方法,赶快标记起来,可能有用。

分析InitLicense方法中的代码,其中RegisterProduct枚举有Control,Desktop,Server三个。

//根据经验,这个字符串是经过加密函数加密后的
//最后有个=号,你可能见过这样的,猜测这是“Desktop”的含义
SN.RegisterProductCode = "wfg783X8Joo=";
//检查权限类型,这个整个分析的关键
LicenseType lic = SN.Registered(1);
//刷新窗体显示的权限版本
this.RefreshFormTitle(lic);
//启动加密狗监听
this.StartDogListener();

  OK,我们显然要进入SN.Registered看看它具体是什么。等一下,想一下,以我以前的脾气,我会直接让这个方法返回想要的类型值,直接暴破,但这里SN类是AZMap.Core.dll中,我们不能修改,所以本程序破解的方式是分析它的算法,SN类的Registered是我们要分析的关键。(这句话说起来简单,这也是我尝试过好几次得到的结论和方面,平时处理过程中,新手应该不会这么快就得出这样的结果,可能也找了很久才找到关键,而且还不一定是真正的关键,所以要有耐心!)

04.代码分析

新手入门都是暴破,这样来得快,我这次也是迫不得已(不会脱壳,高手勿喷)才来分析它的算法的。下面这个过程可能有点让人痛苦:

SN.Registered函数是读取许可文件的,其关键还在于调用的另外一个函数Register

//返回的LicenseType(枚举值,有Enterprise, Professional, Standerd, Trial, Free, Given),我们想要的当然是枚举值=0的企业版。
//输入参数是lic许可文件路径和要注册的类型(1代表Desktop,这个我们可以不管,在这个程序注册的都是它)
public static LicenseType Register(string licPath, RegisterProduct regType = 1)
{LicenseType type2;//初始化为Free版,我就是就想让free的值赋成EnterpriseLicenseType free = LicenseType.Free;if (!File.Exists(licPath)) return free;//读取许可文件中的许可码string sn = ReadSN(licPath);//如果是Desktop,许可文件路径为C:\Users\Administrator\AppData\Local\AZMapstring path = GetLocalAZMapPath(RegisterProduct.Desktop) + "azmap_4";// 如果是Server,许可文件路径为X:\Program Files (x86)\ArcTiler\Desktop\4.9\AZMapstring str3 = GetLocalAZMapPath(RegisterProduct.Server) + "azmap_4";try{string r = "";bool flag = false;//规律一:SN长度为175-250个// IsSNLegality函数检查SN是否非法,其具体要求是SN长度为175-250个if (IsSNLegality(sn)){//规律二:SN的72位到104位与机器码加密后的字符串必须相等//我们想要flag的值返回为ture,就需要看SetSN函数返回值。获取机器码加密后的值是否与r相等。根据它提供的计算函数,我在VS把它生成出来了//如果SN从72位开始截取32位(即r值)与MCToR()函数返回值(获取机器码加密后的值)相当,则flag为真。r = sn.Substring(72, 32);flag = R.Instance.SetSN(r);}if (!flag) goto Label_02B4;//规律三:SN中至少有两个#号//将SN用#进行分割,从下文看,使用了strArray[1],strArray[2],说明至少有两个#号string[]strArray = sn.Split(new char[] { '#' });int result = 0;//规律四:#号分割后的SN,strArray[1]为版本类型代码加密后的值// 用Decode函数将strArray[1]解密后转为int类型,out给result(是LicenseType的代码),我们的目的是想将Enterprise(当Version =0,1,2时,其代码-1,-11,-21),根据调试,本程序当Version =0,所以,我们是想把-1out给result//如果Decode解密后的值不是数字,则TryParse转换失败,将返回为False值,那就完蛋了。if (!int.TryParse(EncAndDec.Decode(strArray[1], EncAndDec.ToMD5("KEY_64"), EncAndDec.ToMD5("IV_64")), out result)){free = LicenseType.Trial;return LicenseType.Trial;}//经测试,其他Version为0,所以,Version=1,2的代码忽略掉了if (ApplicationConfig.Version == 0){//在VS测试,能够得到 result=-1,达到了free的值赋成Enterprise的目的switch (result){case -1:free = LicenseType.Enterprise;// 转换到Label_0170,这应该是脱壳没干净的原因,不然不会有跳转goto Label_0170;case -3:free = LicenseType.Professional;goto Label_0170;case -5:free = LicenseType.Standerd;goto Label_0170;case -7:free = LicenseType.Free;goto Label_0170;case -9:free = LicenseType.Given;goto Label_0170;}//如果没有跳转,那又完蛋了if (result <= 0){free = LicenseType.Free;return LicenseType.Free;}free = LicenseType.Trial;}else if (ApplicationConfig.Version == 1){……}else if (ApplicationConfig.Version == 2){……}//假设大家都成功跳转过来了,在这里见到大家表示很高兴,如果没有来到这里,在VS里面多调试一下代码。Label_0170:// 这个程序不是Server,所以不管if (regType == RegisterProduct.Server) path = str3;//因为我们是LicenseType.Enterprise,所以要执行下面的语句if (free != LicenseType.Trial){//设置许可类型为free,此时free已为LicenseType.EnterpriseR.Instance.SetLicenseType(free);//将这个有效的SN写入到注册文件,以便下次检测File.WriteAllText(path, sn);//已经return了,后面不管了return free;}……}catch{type2 = LicenseType.Free;}finally{……}return type2;
}

  05.修改调试

下面是在VS中生成示例注册码用到的函数,给大家参考一下:

//获取加密后的机器码
internal string MCToR()
{string s = string.Format("{0}{1}{2}{3}", new object[] { "a71z", this.GetCpuId(), "a91z", this.GetHDid() });using (MD5 md = new MD5CryptoServiceProvider()){byte[] buffer = md.ComputeHash(Encoding.UTF8.GetBytes(s));StringBuilder builder = new StringBuilder(0x20);for (int i = 0; i < buffer.Length; i++){builder.Append(buffer[i].ToString("x").PadLeft(2, '0'));}return builder.ToString();}
}//获取CUP序列号
internal string GetCpuId()
{try{string str = string.Empty;using (ManagementClass class2 = new ManagementClass("Win32_Processor")){foreach (ManagementObject obj2 in class2.GetInstances()){if (obj2.Properties["ProcessorId"] != null){str = obj2.Properties["ProcessorId"].Value.ToString();}obj2.Dispose();}}return str;}catch{return this.GetSystemName();}
}//获取系统名字
internal string GetSystemName()
{try{string str = string.Empty;using (ManagementClass class2 = new ManagementClass("Win32_Processor")){foreach (ManagementObject obj2 in class2.GetInstances()){if (obj2.Properties["SystemName"] != null){str = obj2.Properties["SystemName"].Value.ToString();}obj2.Dispose();}}return str;}catch (Exception){return "SystemName";}
}//获取硬盘序列号
internal string GetHDid()
{string str = string.Empty;using (ManagementClass class2 = new ManagementClass("Win32_DiskDrive")){using (ManagementObjectCollection.ManagementObjectEnumerator enumerator = class2.GetInstances().GetEnumerator()){if (enumerator.MoveNext()){ManagementObject current = (ManagementObject)enumerator.Current;if (current.Properties["Model"] != null){str = (string)current.Properties["Model"].Value;}current.Dispose();}}}if (str != null){str.ToString();}return str;
}//将字符串转为整型
public static bool TryParse(string s, out int result)
{return Int32.TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
}//转MD5
public static string ToMD5(string KEY)
{byte[] bytes = Encoding.Default.GetBytes(KEY);MD5 md = new MD5CryptoServiceProvider();return BitConverter.ToString(md.ComputeHash(bytes)).Replace("-", "").Substring(0, 8);
}//加密函数
public  string Encode(string data, string KEY_64, string IV_64)
{KEY_64 =ToMD5(KEY_64);IV_64 = ToMD5(IV_64);byte[] bytes = System.Text.Encoding.ASCII.GetBytes(KEY_64);byte[] bytes2 = System.Text.Encoding.ASCII.GetBytes(IV_64);string result;using (System.Security.Cryptography.DESCryptoServiceProvider dESCryptoServiceProvider = new System.Security.Cryptography.DESCryptoServiceProvider()){int arg_34_0 = dESCryptoServiceProvider.KeySize;using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream()){using (System.Security.Cryptography.CryptoStream cryptoStream = new System.Security.Cryptography.CryptoStream(memoryStream, dESCryptoServiceProvider.CreateEncryptor(bytes, bytes2), System.Security.Cryptography.CryptoStreamMode.Write)){System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(cryptoStream);streamWriter.Write(data);streamWriter.Flush();cryptoStream.FlushFinalBlock();streamWriter.Flush();result = System.Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);}}}return result;
}//解密函数
public static string Decode(string data, string KEY_64, string IV_64)
{byte[] buffer3;string str;KEY_64 = ToMD5(KEY_64);IV_64 = ToMD5(IV_64);byte[] bytes = Encoding.ASCII.GetBytes(KEY_64);byte[] rgbIV = Encoding.ASCII.GetBytes(IV_64);try{buffer3 = Convert.FromBase64String(data);}catch{return null;}using (DESCryptoServiceProvider provider = new DESCryptoServiceProvider()){using (MemoryStream stream = new MemoryStream(buffer3)){using (CryptoStream stream2 = new CryptoStream(stream, provider.CreateDecryptor(bytes, rgbIV), CryptoStreamMode.Read)){str = new StreamReader(stream2).ReadToEnd();}}}return str;
}

  

用VS生成了一个注册码,进行注册后,终于显示成功,有点小激动!

06.测试程序

猜中了开头,没有猜中故事的结局,重启后出现这个警告,并且企业版又变回了试用版,点击确定后,程序关闭。

搜索"非法授权"关键字,找到了SN.OnlineCheck()函数(在不能修改的AZMap.Core.dll文件中),认识英文的都知道,它是联网查询数据库检查是否存在 这个SN,接下来怎么办?黑数据库?……

return MySQLHelper.CheckMCExisted(R.smethod_0());

开个玩笑,我们接下来分析一下,它出现的位置。

柳暗花明又一村,这是在AZMap.exe中调用的,这就好办了,修改判断啊,来个狠一点,这个timer的Tick事件一直会检测SN是否合法,检查加密狗是否插入、拔出、合法,直接全删除!

终于写完了,效果图!

四、注意事项

01.本教程不提供最终成品,已分析了详细过程,不要因此而留言;

02.在分析和调试时AZMap.Core.dll应使用脱壳后的,在检查SN是否有效则使用原版AZMap.Core.dll;

.NET破解之太乐地图下载器【非暴破】相关推荐

  1. 太乐地图下载器 V5.0.5 破解版

    博主今天给大家带来太乐地图下载器 V5.0.5 破解版 需要的小伙伴下载使用哦:http://download.csdn.net/download/shujujiegougou/9514304?utm ...

  2. 太乐地图下载器5.0.5(破解版)

    简介 太乐地图下载器是一款地图.高程下载类GIS软件,支持将下载的地图.高程等数据进行多种专业格式转换,或发布为地图服务,旨在辅助用户提高工作效率,轻松构建自己的地图应用.可应用于学术科研.工程.规划 ...

  3. 使用太乐地图下载器下载cesium适用瓦片

    使用太乐地图下载器下载cesium适用瓦片

  4. 那些年,我们用过的地图下载器

    作为地信.遥感.地质.测绘等专业的同学,下载电子地图.遥感影像应该都接触过,现在XX地图下载器广告满天飞,虽然各位同学唯唯诺诺,还是被群主踢出了.现在把自己那些年珍藏的地图下载器分享给大家.对各种下载 ...

  5. 加载调用本地百度地图资源,附地图下载器及黑龙江省1-16级瓦片地图,加载显示marker

    业务适用场景说明 适用范围,需要局域网或者本地环境加载显示百度地图及展示marker的业务场景,可以根据业务使用场景下载不同地区等级的地图瓦片.由于瓦片文件过大,建议放在本地服务器上. 已有1-16级 ...

  6. 谷歌卫星地图下载器有哪些那款好用

    众所周知,谷歌卫星地图以其"影像清晰.更新迅速.时间近.精度高"的特点受到了广大地图爱好者的喜爱,为了能够将其下载 ,谷歌卫星地图下载器也随之应运而生,目前市面上有很多款谷歌卫星地 ...

  7. 0622_ArcMap添加地图地图(矢量底图与影像地图)_太乐地图插件ArcTailer.tlb

    AIM: 在Arcmap中添加遥感影像底图,并进行矢量面的绘制: 添加方法 · 使用太乐地图ArcGIS插件 下载地址:太乐地图ArcGIS插件 安装使用与卸载教程:安装使用卸载教程(有垃圾软件顺带, ...

  8. Cesium - 地图下载器(python)

    开发 需要卫星地图作为底图.百度.高德.谷歌.arcgis都提供在线服务,但在不能访问在线服务的地方就不适用了. 网上有不少地图下载器,BigeMap.水经注.太乐.91卫图.Google Maps ...

  9. 地图下载器工具-Java

    地图下载器工具-Java 瓦片下载 要点1 使用瓦片的访问地址直接下载瓦片 主要用到的是HttpURLConnection去访问,为了避免被封杀ip,设置了两个请求参数referer,User-Age ...

最新文章

  1. 取java.sql.date日期_JAVA 处理时间 - java.sql.Date、java.util.Date与数据库中的Date字段的转换方法[转]...
  2. 【计算理论】计算复杂性 ( 时间复杂度时间单位 : 步数 | 算法分析 | 算法复杂性分析 )
  3. Html5-Canvas实现简易的抽奖转盘
  4. 利用sshpass实现ansible功能
  5. QT QML 在qml中自定义信号
  6. LeetCode 663. 均匀树划分(树形DP)
  7. iframe 去除边框 背景透明等设置 待修改
  8. STL之stack容器
  9. java把含小数点的数字字符串转换为int类型
  10. 软件测试中不需要测试的八件事
  11. 创建一个可以复制百度文库的Chrome插件
  12. Vue实现简单汇率转换器
  13. 计算机英语背诵发音,英语26个字母的标准发音 26个字母背诵顺口溜
  14. CSDN 博客专家申请入口
  15. ubuntu18.04(Jetson)以及火狐浏览器设置终端代理和清除代理命令
  16. 全方面讲解OpenWrt的DNS配置与DHCP,并介绍dnsmasq DNS缓存工具、nslookup/dig DNS测试工具
  17. 自建企业邮箱如何选择服务器
  18. 软件测试实战(微软技术专家经验总结)--第四章(测试建模)读书笔记
  19. 周鸿祎的“花房上市”执念
  20. 零基础学SQL(二、MYSQL数据类型)

热门文章

  1. SQL Server Check检查约束用法
  2. python随机函数random、画、星轨_如何使用 NVIDIA StyleGAN 生成自己的动漫(老婆)头像...
  3. 树莓派Linux-raspberrypi域名解析失败:Temporary failure in name resolution
  4. 展锐UDX710:5G LAN数据流通图
  5. MATLAB读视频报错 Unable to initialize the video obtain properties (videoreader in Matlab)
  6. 嵌入式Linux:安装Ubuntu系统环境
  7. Caché 变量大全
  8. PS设计网页下载使用960栅格系统设计简洁网页
  9. 群晖 Drive 的团队文件夹显示 “无法取得“
  10. Uni-app开发微信小程序使用本地图片做背景图