开始用reflecotr,收费后一直用dnspy, 利用业余时间跟踪了下refloctor的注册流程。 从网上搜了个注册机,辅助跟踪分析。
准备:
从reggate官网下载一个新版, 9.0版本,14天试用,安装好后,用dnspy载入后,发现好多名称都是不可见字符,利用de4dot处理下,比不可见字符好看多了,如果发现不能处理,尝试在管理员权限下运行de4dot。我是在win7 64位下调试的。
1.序列号的处理:
搜索字符串 “Serial Number”,来到ns25.EnterSerialNumberPage.InitializeComponent处,此处为注册窗口
this.label2.Text = "Serial number";
this.m_txtSerialNumber.Location = new Point(3, 18);
this.m_txtSerialNumber.MaxLength = 40;
this.m_txtSerialNumber.Name = "m_txtSerialNumber";
this.m_txtSerialNumber.Size = new Size(161, 20);
this.m_txtSerialNumber.TabIndex = 2;
this.m_txtSerialNumber.TextChanged += new EventHandler(this.m_txtSerialNumber_TextChanged);
单步跟踪,序列号格式检查的一个地方
public bool vmethod_1()
{
bool result;
if (string.IsNullOrEmpty(this.string_0))
{
result = false;
}
else
{
string text = string.Format("[{0}]", new string(Class789.char_0));
string pattern = string.Concat(new string[]
{
"^A3",
text,
"{2}(-(",
text,
"{4})){5}$"
});
result = new Regex(pattern).IsMatch(this.string_0);
}
return result;
}
序列号的模式匹配
pattern "^A3[2346789ABCDEFGHJKMNPRTWXYZ]{2}(-([2346789ABCDEFGHJKMNPRTWXYZ]{4})){5}$"
2.激活码的初步验证:
点击注册时把网断掉,点击注册按钮处理函数:
private void m_AcceptButton_Click(object sender, EventArgs e)
{
this.method_6(sender, e);
}
生成请求码的处理函数
public virtual string vmethod_4(string string_3)
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < this.method_12().Length; i++)
{
stringBuilder.Append(string.Concat(new object[]
{
"<activationrequest>\r\n<version>",
Class801.int_1,
"</version>\r\n<machinehash>",
this.method_12()[i].method_33(),
"</machinehash>\r\n<productcode>",
this.method_12()[i].method_4(),
"</productcode>\r\n<majorversion>",
this.method_12()[i].method_12(),
"</majorversion>\r\n<minorversion>",
this.method_12()[i].method_14(),
"</minorversion>\r\n<serialnumber>",
string_3,
"</serialnumber>\r\n<session>",
base.method_6(),
"</session>\r\n<locale>",
Thread.CurrentThread.CurrentUICulture.Name,
"</locale>\r\n",
this.vmethod_5(this.method_14()),
"</activationrequest>\r\n"
}));
}
return stringBuilder.ToString();
输入正确的激活码后,对激活码格式验证的函数
private static bool smethod_0(string strTxt, out string strVerified)
{
strVerified = null;
string text = strTxt.Trim();
int num;
bool result;
int num2;
if ((num = text.IndexOf("<activationresponse>")) == -1)
{
result = false;
}
else if ((num2 = text.IndexOf("</activationresponse>")) == -1)
{
result = false;
}
else
{
string text2 = text.Substring(num, num2 - num + "</activationresponse>".Length);
XmlDocument xmlDocument = new XmlDocument();
bool flag;
try
{
xmlDocument.LoadXml(text2);
strVerified = text2;
flag = true;
}
catch (XmlException)
{
flag = false;
}
result = flag;
}
return result;
}
3.对激活码签名验证的地方
private static XmlNode smethod_14(XmlNode xmlNode_0, string string_0, string string_1, out string string_2)
{
XmlNode xmlNode = xmlNode_0.SelectSingleNode(string_0 + "/data");
XmlNode xmlNode2 = xmlNode_0.SelectSingleNode(string_0 + "/signature");
if (xmlNode == null || xmlNode2 == null)
{
throw new ActivationException(Class790.string_10);
}
string text = xmlNode2.InnerText.Trim();
if (text.Length == 0)
{
throw new ActivationException(Class790.string_9);
}
StringBuilder stringBuilder = new StringBuilder();
xmlNode_0.WriteTo(new XmlTextWriter(new StringWriter(stringBuilder))
{
Indentation = 0,
Formatting = Formatting.Indented
});
string_2 = stringBuilder.ToString();
RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider(new CspParameters
{
Flags = CspProviderFlags.UseMachineKeyStore
});
rSACryptoServiceProvider.FromXmlString(string_1);
try
{
byte[] byte_;
try
{
byte_ = Convert.FromBase64String(text); //签名
}
catch (FormatException)
{
throw new ActivationException(Class790.string_9);
}
byte[] bytes = Encoding.UTF8.GetBytes(string_2.Substring(string_2.IndexOf("<data>"), string_2.IndexOf("</data>") - string_2.IndexOf("<data>") + 7));
if (!Class791.smethod_0(rSACryptoServiceProvider, bytes, new SHA1CryptoServiceProvider(), byte_))
{
throw new ActivationException(Class790.string_13);
}
}
finally
{
rSACryptoServiceProvider.Clear();
}
return xmlNode;
}
private static bool smethod_1(RSACryptoServiceProvider rsacryptoServiceProvider_0, byte[] byte_0, HashAlgorithm hashAlgorithm_0, byte[] byte_1)
{
string text = hashAlgorithm_0.GetType().ToString();
if (CryptoConfig.MapNameToOID(text) == null)
{
throw new CryptographicException("Uh-hoh, I couldn't find the oid for {0}", text);
}
byte[] rgbHash = hashAlgorithm_0.ComputeHash(byte_0);
return rsacryptoServiceProvider_0.VerifyHash(rgbHash, text, byte_1);
}
}
reflector客户端中的公钥:
"<RSAKeyValue><Modulus>zLizNmLUd4VlIWee1GXgn/KxEwcghPASQ+NUzZhbY2fTGzpW64T6yEOdHlIbhX1DX6yAz2gMZKfnpQL2aFqxh5ACFV9dONSTzuQzkqeXwFEARsMxGP3eTQSWMpwVhEcraSn1zOqMb3CRDeQpgasq0lv4HRFhbwalOifKarjEL/8=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"
注册机中的私钥是能搞出来确实挺NB,正常点的破解方法是替换公钥了。
激活码的生成方法:用私钥对请求码签名,对签名后的数据做base64编码。
验证过程:讲签名数据从base64编码转换成二进制子串,用rsa校验。
附上用de4dot处理后的注册机。