本文作者Sp4ce,转自https://0x20h.com/p/a73d.html

Apache Log Viewer 5.X 注册机

抽空研究了下ALV的注册机制,写了个注册机

分析

ALV的注册方法是unlockCodeToolStripMenuItem_Click方法,当点击Unlock按钮时会触发注册事件并调用Class2类中的smethod_1smethod_02个方法进行校验,详细流程见如下代码

unlockCodeToolStripMenuItem_Click方法

private void unlockCodeToolStripMenuItem_Click(object sender, EventArgs e)
{
string text = this.prefs_0.Key;
if (!InputForm.smethod_3("Apache Logs Viewer | " + Class96.smethod_264(), Class96.smethod_143(), ref text))
{
return;
}
if (text != null)
{
text = text.Trim();
}
if (string.IsNullOrEmpty(text))
{
this.prefs_0.Key = string.Empty;
this.bool_0 = false;
Prefs.Save(Prefs.Filename, this.prefs_0);
this.method_2(this.bool_0);
return;
}
try
{
this.Cursor = Cursors.WaitCursor;
if (text.Length < 22)//检查key长度是否大于22
{
throw new ApplicationException("Failed");
}
if (Class2.smethod_1(Class2.smethod_0(text)))//重点位置
{
this.prefs_0.Key = text;
this.method_23();
Prefs.Save(Prefs.Filename, this.prefs_0);
this.Cursor = Cursors.Default;
this.lbStatusStripNotify.Text = Class96.smethod_253() + " Apache Logs Viewer.";
MessageBox.Show(this, Class96.smethod_253() + " Apache Logs Viewer.", "Apache Logs Viewer", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
this.bool_0 = true;
}
else
{
MessageBox.Show(this, Class96.smethod_117(), "Apache Logs Viewer | " + Class96.smethod_264(), MessageBoxButtons.OK, MessageBoxIcon.Hand);
this.bool_0 = false;
}
}
catch (Exception)
{
this.Cursor = Cursors.Default;
MessageBox.Show(this, Class96.smethod_90(), "Apache Logs Viewer | " + Class96.smethod_264(), MessageBoxButtons.OK, MessageBoxIcon.Hand);
this.bool_0 = false;
}
finally
{
this.Cursor = Cursors.Default;
}
this.method_2(this.bool_0);
}

Class2.smethod_0方法,

public static string smethod_0(string string_0)
{
if (string_0.IndexOf('-') < 0)//检查注册代码中是否有-
{
return string_0;
}
string str = "DBV";
string_0 = string_0.Replace("-", string.Empty);//将字符-转为空
string_0 = string_0.Replace('Q', '4');//Q转为4
string_0 = string_0.Replace('G', '4');//G转为4
string_0 = string_0.Replace('V', '0');//V转为0
string_0 = string_0.Replace('N', '3');//N转为3
str + string_0;//无用语句
byte[] array = new byte[string_0.Length / 2];//新建个数组,长度是去掉-后的注册码长度的一半
for (int i = 0; i < string_0.Length; i += 2)
{
byte b;
byte.TryParse(new string(new char[]
{
string_0[i],
string_0[i + 1]
}), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out b);//每两位进行拼接并转回字符串形式并依次存入b
array[i / 2] = b;
}
string text = Encoding.ASCII.GetString(array);//将注册码转为字符串形式,传入的注册码为hex后的ascii值
text = text.Insert(1, ":");//第2位插入:
text = text.Insert(5, ":");//第6位插入:
text = text.Insert(9, ":");//第10位插入:
if (text.Length > 13)
{
text = text.Insert(13, ":");//如果注册码长度大于13则在第13位插入:
}
return text;
}

Class2.smethod_1方法,

public static bool smethod_1(string string_0)
{
bool flag = true;
string a = string_0.Substring(4, 5);//取经过smethod_0处理后的字符串中的第4到8位
//如果a为IALV或注册码第一位不为F或第3位转为int型大于16或a不为I:ALV或注册码第4位转为int型大于16则抛出注册码错误
if (a == "IALV")
{
flag = false;
}
if (string_0[0] != 'F')
{
flag = false;
}
int num = int.Parse(string_0[2].ToString(), NumberStyles.HexNumber);
if (num > 16)
{
flag = false;
}
if (a != "I:ALV")
{
flag = false;
}

num = int.Parse(string_0[3].ToString(), NumberStyles.HexNumber);
if (num > 16)
{
flag = false;
}
if (!int.TryParse(string_0.Substring(10, 3), out num))
{
flag = false;
}
//处理后的注册码如果长度小于14则抛错
if (string_0.Length <= 14)
{
throw new ApplicationException("Invalid Unlock Code");
}
//命名num2变量,值为注册码的第15位,并判断num2是否为2或3,不是就抛错
int num2 = int.Parse(string_0.Substring(15, 1));
if (num2 != 2 && num2 != 3)
{
throw new ApplicationException("Incorrect Code for Version");
}
string s = string_0.Substring(0, 16);//s为1~17位
string b = string_0.Substring(16);//b为17位后的校验位
int num3 = 0;
byte[] bytes = Encoding.ASCII.GetBytes(s);//将s转为字节码并存入数组
for (int i = 0; i < bytes.Length; i++)
{
if (bytes[i] % 2 == 0)//每一位进行模2运算,为0则num3+1
{
num3++;
}
}
return !(num3.ToString("00") != b) && flag;//num3向上取整后与校验位作比较,比较成功则返回真
}

Keygen

有了注册机制就可以写注册机了,这里用python写了一个

'''
@Author : Sp4ce
@Date : 2020-02-19 19:17:59
@LastEditors : Sp4ce
@LastEditTime : 2020-02-19 23:27:40
@Description : Challenge Everything.
'''

import random
import binascii

def banner():
print(r"""
_ __ __ _ __ _____
/\ | |\ \ / / | |/ / / ____|
/ \ | | \ \ / / | ' / ___ _ _| | __ ___ _ __
/ /\ \ | | \ \/ / | < / _ \ | | | | |_ |/ _ \ '_ \
/ ____ \| |___\ / | . \ __/ |_| | |__| | __/ | | |
/_/ \_\______\/ |_|\_\___|\__, |\_____|\___|_| |_|
__/ |
|___/

Apache Log Viewer 5.X KeyGen
By:Sp4ce
""")

def genLicenseCode(data):
try:
hexdata = data.replace('-', ':')
data = "".join(data.split('-'))
num = 0
for i in hexdata:
a = binascii.b2a_hex(i.encode('utf-8')).decode('utf-8')
if int(a, 16) % 2 == 0:
num = num+1
hexData = binascii.b2a_hex((data+str(num)).encode('utf-8')) .decode('utf-8')
hexData = list(hexData)
hexData.insert(2, '-')
hexData.insert(9, '-')
hexData.insert(16, '-')
hexData.insert(23, '-')
licenseCode = ''.join(hexData)
print("[+] License Code Generate Success!\nYour License Code: ->["+licenseCode.upper()+"]<-")
except:
print("[-] License Code Generate Failed!")



def main():
banner()
data = []
data.append('F') # 第一位必须:F
data.append('-') # 第一个-
data.append(random.randint(1, 9)) # 第3位转为int后必须小于16
data.append(random.randint(1, 9)) # 第4位转为int后必须小于16
data.append('I') # I
data.append('-') # 第二个-
data.append('ALV') # ALV
data.append('-') # 第三个-
data.append(random.randint(100, 999)) # 第11~13位必须为int型
data.append('-') # 第四个-
data.append(random.randint(1, 9)) # 第14位随机
data.append(random.randint(2, 3)) # 第15位必须为2或3
data = "".join('%s' % i for i in data).upper()
genLicenseCode(data)

if __name__ == "__main__":
main()

运行后

          _ __      __  _  __           _____
/\ | |\ \ / / | |/ / / ____|
/ \ | | \ \ / / | ' / ___ _ _| | __ ___ _ __
/ /\ \ | | \ \/ / | < / _ \ | | | | |_ |/ _ \ '_ \
/ ____ \| |___\ / | . \ __/ |_| | |__| | __/ | | |
/_/ \_\______\/ |_|\_\___|\__, |\_____|\___|_| |_|
__/ |
|___/

Apache Log Viwer 5.X KeyGen
By:Sp4ce

[+] License Code Generate Success!
Your License Code: ->[46-313449-414C56-353934-33323130]<-

后话

该软件注册机制还有第二种方案,抽空再写