某Excel插件 MagicalVBA 激活码逆向分析
前情提要
某日 某 3xx3 佬 给咱传了个 链接,说他搞不定这个。。。
咱问他是干啥的,他说 他也不清楚 就是看了名字觉得想弄一下。。。
啊这... 不过咱也好奇 到底是个啥,就折腾看看...
PS.
这个好像是个VBA学习工具,里面生产力的功能到是不多,但是不少图文教程。
知乎软文链接
淘宝里面有点贵好像。。。
就用来当 5.1 礼物吧... (当然想嫖还是要点技术的
准备工作
下载安装包
安装完了
注册表也有了
功能也出来了
但是 插件的 dll 呢?文件没了?!这不科学。。。
看样子是安装完就自动删除了。。。
得想办法 文件提取出来。。。
由于对这块儿不熟,所以直接笨办法,那杀毒软件 给屏蔽了删除操作
最后提取出了 具体的安装文件和 vsto
这个会和原始安装包一起放出来 方便大伙分析。
原始安装包和提取内容下载地址
开始分析
打开 产品注册窗口
中文软件的好处 就是可以直接搜名字 比如 激活,产品注册界面
然后 既然是个 Form 那里面的按钮肯定是 Button,简单看一眼
试着先去个混淆
private void uiButton1_Click_1(object sender, EventArgs e)
{
try
{
string text = this.tb_ComputerFingerPrint.Text; //机器码文本框的值 基本就是 编码后的机器码
string text2 = this.tb_ActivateCode.Text; //激活码文本框 就是 传入的激活码 了
if (!string.IsNullOrWhiteSpace(text2))
{
//RSA解密
string[] array = new RSA(this._clientPublicKey).DencryptWithPublicKey(text2).Split(new char[] { '隔' });
//解析后 用 隔 分割,长度为3
if (array.Length != 3)
{
UIMessageBox.ShowError("激活码错误", true, false);
}
else
{
string text3 = array[0];
string text4 = array[1];
string text5 = array[2];
if (text == text3) //array[0] 要和 编码后的机器码一致
{
DateTime dateTime;
if (DateTime.TryParse(text5, out dateTime)) //array[2] 是日期
{
if (DateTime.Today.Subtract(dateTime).Days <= 0) //array[2] 要比当前日期大
{
Settings.Default.ZhuCeMa = text2;
Settings.Default.App_RegistryDate = text4;
Settings.Default.App_RegistryCodeEndValidDate = text5;
Settings.Default.Save(); //配置保存
string activatingCodeSavePath = Settings.Default.ActivatingCodeSavePath;
if (!File.Exists(activatingCodeSavePath))
{
if (!Directory.Exists(Path.GetDirectoryName(activatingCodeSavePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(activatingCodeSavePath));
}
new FileStream(activatingCodeSavePath, FileMode.Create, FileAccess.ReadWrite).Close();
}
File.ReadAllLines(activatingCodeSavePath, Encoding.Default);
FileStream fileStream = new FileStream(activatingCodeSavePath, FileMode.OpenOrCreate);
StreamWriter streamWriter = new StreamWriter(fileStream);
streamWriter.WriteLine(text2);
streamWriter.Close();
fileStream.Close();
Microsoft.Office.Tools.Ribbon.RibbonTab magic_VBA_RibbonTab = Globals.Ribbons.GetRibbon<Ribbon1>().Magic_VBA_RibbonTab;
foreach (RibbonGroup ribbonGroup in magic_VBA_RibbonTab.Groups)
{
//....................
}
magic_VBA_RibbonTab.ResumeLayout(true);
magic_VBA_RibbonTab.PerformLayout();
base.Dispose();
}
else
{
UIMessageBox.ShowError("当前激活码授予的使用权已过期!请购买新的激活码", true, false);
}
}
else
{
UIMessageBox.ShowError("激活码错误", true, false);
}
}
else
{
UIMessageBox.ShowError("激活码错误", true, false);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
再来看看 密钥 在哪儿
密钥在这儿了
既然上了 RSA那肯定要替换密钥,
怎么换 可以参考 其他帖子,这里不详述。
值得一提的是,里面有一个明显字样
private string warnintext = "产品结构被非法篡改,当前用户已标记";
咱们瞧瞧都用在哪儿了
霍儿~ 用了强命名检查呢~
数据是这儿的
基本如果要改就是修改上面这两处位置了。
替换一个RSA密钥,然后 替换一下强签名验证的密钥,当然也可以直接强制改为判断成功。
咱这边就没动太多 改了两处文本。
编码逻辑
改完文本就要来实现激活码了。
之前已经分析出来 激活码的 格式很简单
[编码后的机器码,激活开始日期,激活结束日期]
然后 用字符 隔 拼接
然后 RSA 加密 具体看看怎么加密的
可以看到 有个 加密函数在
但是 入参是 两个 BigInteger
我们可以逆推一下
//公钥解密是下面这样
RSAHelper.ResolveKey(key, out array, out array2);
BigInteger bigInteger = new BigInteger(array);
BigInteger bigInteger2 = new BigInteger(array2);
text = RSAHelper.DecryptString(encryptString, bigInteger, bigInteger2);
key = RSAHelper.ComponentKey(publicKeyParameters.Exponent, publicKeyParameters.Modulus);
那么 私钥加密 也应该是 类似这样
然后 看到 上面有个
public static RSAHelper.RSAKey GetRASKey()
{
RSACryptoServiceProvider.UseMachineKeyStore = true;
RSAParameters rsaparameters = new RSACryptoServiceProvider(1024).ExportParameters(true);
return new RSAHelper.RSAKey
{
PublicKey = RSAHelper.ComponentKey(rsaparameters.Exponent, rsaparameters.Modulus),
PrivateKey = RSAHelper.ComponentKey(rsaparameters.D, rsaparameters.Modulus)
};
}
那么很明显了 私钥大概 用的就是 rsaparameters.D 和 rsaparameters.Modulus
key = RSAHelper.ComponentKey(rsaparameters.D, rsaparameters.Modulus);
RSAHelper.ResolveKey(key, out array, out array2);
BigInteger bigInteger = new BigInteger(array);
BigInteger bigInteger2 = new BigInteger(array2);
text = RSAHelper.EncryptString(encryptString, bigInteger, bigInteger2);
可以直接省略为
BigInteger bigInteger = new BigInteger(rsaparameters.D);
BigInteger bigInteger2 = new BigInteger(rsaparameters.Modulus);
text = RSAHelper.EncryptString(encryptString, bigInteger, bigInteger2);
开工
开始码代码实现了,老样子 偷懒用反射