本帖最后由 Marketing 于 2018-8-4 13:29 编辑
第一次发布这么长的教程,可能有点啰嗦,希望大家理解. 技术含量不怎么高,适合新手入门.后面我会继续发布安卓逆向算法的相关算法分析,希望在论坛和各位大神相互学习.软件本身对大都数人价值不大.相关的敏感信息已经全部打码,发帖目的在于分享方法和思路.
1. 首先运行软件,提示需要注册才能继续使用,否则无法使用功能界面.
2. 关闭软件, 直接使用dnSpy载入,发现程序反编译都是乱码,因为加了壳
3. 运行CMD命令使用de4dot脱壳,脱壳后的程序如下,类名,方法名都已经清晰可以看见.
4. 接下来就是定位关键代码, 因为我之前分析过,所以上面的截图就是验证关键代码, 其实一开始拿到软件,关键代码的定位是非常重要并且费时间的一步. 很多时候定位都可以通过搜索字符串实现, 但是还有很多情况是需要结合其他方式和个人逆向经验的.
4.1首先在dnSpy中运行调试程序. 输入假码,程序提示注册码长度无效,没关系,因为是随便输入的.
4.2不要关闭它的错误提示, 返回dnSpy,在调试工具条按下暂停按钮.
4.3 简单单步跟踪几步,注意观察软件界面下方局部变量窗口的值变化.在某一个位置出现了,我们输入的假码信息, 停下来, 仔细分析上下代码和其他局部变量值,看看能否找出对我们有价值的信息.
展开this对象的变量值,往下查找可以发现我们输入的用户名,密码,假码,包括机器码都存在在这里, 所以可以判断这里一定有我们想要的一些信息. 查看上图, this对象是属于 FmAddUser类.接下来我们就去找 FmAddUser这个类进行分析.
4.4 在dnSpy右侧的资源管理器,查找到FmAddUser类, 查看它的方法列表,很明显的可以看见它有几个按钮事件, 在逆向分析的时候按钮事件是需要我们特别关注了, 因为它是我们在执行操作时最先执行的代码. 一个一个查看,在btn_ok_Click方法可以明显看到有”注册码错误”字符串(但是我通过dnSpy的搜索”注册”一个结果都没有,不知道是什么原因), 前面的代码进行的操作是普通注册软件的套路,首先读取用户输入信息,然后调用验证函数验证, 最后将验证结果进行对比,如果正确就返回OK,错误提示信息框错误.
4.5 一开始呢,也想直接在这里把他给爆破掉,但是程序有自校验, 修改任何地方都会导致奔溃. 第二次方式是想打个补丁,但是.NET程序打补丁还没尝试过,使用也不方便. 最后想着反编译的结果都这么清晰了,直接找出他的注册算法不是更好?
5. 点击进入Verity()方法内, 开始分析软件注册算法
进去之后发现调用了DESDecrypt ()方法, 原来是个常用的DES加密算法,这下分析就轻松多了,直接找出加密的Key,IV和Mode. 直接在DESDecrypt()方法前下一个断点,运行程序进行动态调试.
在局部变量窗口可以看见DESDecrypt传入的参数分别是 RegCode(输入的注册码), “adecefgd”.继续跟进DESDecrypt方法, 发现DES加密的key,IV,Model分别是:
[C#] 纯文本查看 复制代码 key = "abecefgd";
iv = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; //程序截图的是10进制, 这里是调试时的16进制字节数组
Mode="DES/CBC/PKCS7Padding"
//输出格式是Base64编码.
到这里程序的加密算法已经特别清晰了, 接下来我们要分析进行加密前的原字符串和格式.
6. 返回Verity()方法进行分析:
[C#] 纯文本查看 复制代码 public string Verity()[/size][size=4] {
string text = SDKSecurity.DESDecrypt(this.RegCode, this.\u000E); //调用DES解密函数, 传入参数: RegCode(输入的注册码),DES加解密key(“adecefgd”)
//text= 解密后的结果
int num;
if (int.TryParse(text.Substring(0, 8), out num)) //截取解密结果的前8位字符, 通过调试可以知道这个是到期时间, 格式: 20180101
{
new DecryptFile().SetEndDate(text.Substring(0, 8));//保存到期时间到本地文件
}
if (string.IsNullOrEmpty(this.RegCode) || this.Machine != this.CountMachineCode() || text.Substring(8) != this.Machine)
//判断注册码是否为空, 机器码是否等于电脑机器码, 解密后的结果8位以后字符串是否等于机器码 . 如果为真,则提示错误
//这上面两个可以判断,解密后的结果是8位的到期时间+机器码
{
return global::\u0003.\u0002(122172263);
}
if (!DecryptFile.CanOpenPage())//检测注册文件是否保存成功,如果保存失败,返回提示用户重新注册
{
new DecryptFile().SetEndDate(global::\u0003.\u0002(122172246));
return global::\u0003.\u0002(122172231);
}
DecryptFile.AddDate();
return SDKSecurity.DESDecrypt(this.RegCode, this.\u000E).Substring(0, 8);//返回注册码的到期时间
}
7. 接下来编写一个java代码进行验证,写入一个到期时间+自己的机器码,调试输出计算出的注册码
8. 最后一步进行注册授权,看看是否计算正确
点击确定,弹出注册成功,功能使用也都没有任何问题,说明程序算法分析已经完成啦!
|