寻找关键函数
直接IDA载入,发现静态编译了MFC,无壳,无混淆,没有反调试。 试运行下,一个窗体程序,有两个文本框、checkbox、和按钮。文本框分别输入 UserName 和 Regcode 。 通过 GetDlgItem api找到按键的响应函数,位置 4026F0 ,很明显是主流程。
主流程
函数路径简单明显,通过 SendMessage ,先取 UserName 、 Regcode 和 checkbox 。伪代码如下:
v13 = (CWnd *)this;
v1 = GetDlgItem(this[8], 1000); memset(name, 0, 0x400u); SendMessageA(v1, 0xDu, 0x400u(LPARAM)name);
v2 = GetDlgItem(*((HWND *)v13 + 8), 1001); memset(code, 0, 0x400u); SendMessageA(v2, 0xDu, 0x400u, (LPARAM)code);
v3 = v13; v4 = CWnd::GetDlgItem(v13, 1004);
flag = SendMessageW(*((HWND *)v4 + 8), 0xF0u, 0, 0) == 1; v13 = (CWnd *)&p_code; p_code.field_14 = 15;
p_code.length = 0;
LOBYTE(p_code.field_0) = 0;
if ( code[0] )
length1 = strlen(code);
else
length1 = 0;
string_402A70(&p_code, code, length1);
v26 = 0;
v10 = 15;
v9 = 0;
LOBYTE(p_name.field_0) = 0;
if ( name[0] )
length2 = strlen(name);
else
length2 = 0;
string_402A70(&p_name, name, length2); v26 = -1;
if ( check_routing_405510(
p_name.field_0,
p_name.field_4,
p_name.field_8,
p_name.field_C,
v9,
v10,
p_code.field_0,
p_code.field_4,
p_code.field_8,
p_code.field_C,
p_code.length,
p_code.field_14, flag) )
{
*(_DWORD *)v16 = 'eR';
v17 = 0;
v7 = (const wchar_t *)v16;
*(_DWORD *)&v16[4] = 'ig';
*(_DWORD *)&v16[8] = 'ts';
*(_DWORD *)&v16[12] = 're';
*(_DWORD *)&v16[16] = 'S ';
*(_DWORD *)&v16[20] = 'cu';
*(_DWORD *)&v16[24] = 'ec';
*(_DWORD *)&v16[28] = 'ss';
*(_DWORD *)&v16[32] = 'C,';
*(_DWORD *)&v16[36] = 'no';
*(_DWORD *)&v16[40] = 'rg';
*(_DWORD *)&v16[44] = 'ta';
*(_DWORD *)&v16[48] = 'lu';
*(_DWORD *)&v16[52] = 'ta';
*(_DWORD *)&v16[56] = 'oi';
*(_DWORD *)&v16[60] = '!n';
// RegisterSuccess,Congratulation!
}
else {
*(_DWORD *)v18 = 'eR';
v7 = v18; v19 = 'ig';
v20 = 'ts';
v21 = 're';
v22 = 'F ';
v23 = 'ia';
v24 = 'el';
v25 = 'd';
// RegisterFailed
}
CWnd::SetDlgItemTextW(v3, 1003, v7);
地址为 405510 的函数为主检验函数。
主校验流程
校验的主流程大致过程为:
检查name的有效性。
计算name,得到5个64bit的整数。
code先进行base64解码,再进行AES解密,得到32字节数据,前24字节作为3个64bit整数,最后4字节为 00000000 ,剩 下的4字节为 8102 。
对得到的8个64bit整数进行算术校验(中间过程有溢出)。
主流程的主要伪代码如下:
if ( checkname_404F00((struc_1 *)&name) )
{
compute_name_405040((int)&name, &v26, &v27, &v28, (int *)&v29, &v30);// name
v31 = 0i64;
v32 = 0;
LOBYTE(v34) = 2;
v14 = (const char *) a7;
if ( (unsigned int)a12 >= 0x10
v14 = (const char *)a7;
if ( decode_base64_406080(v14, (int *)&v31)
&& ((v16 = HIDWORD(v31), v17 = (__m128i *)v31, flag)
|| (v33 = val_AES_KEY_5AC470, AES_403010(HIDWORD(v31) - v31, v31, (char *)&v33, v15, v31)))
&& v16 - (_DWORD)v17 == 32
&& v17[1].m128i_i32[2] == '2018'
&& !v17[1].m128i_i32[3] )
{
v18 = *v17;
*((_QWORD *)&v33 + 1) = v17[1].m128i_i64[0];
v13 = equation_402F20(v26, v27, v28, v29, v30, __PAIR__(_mm_cvtsi128_si32(_mm_srli_si128(v18, 4)), _mm_cvtsi128_si32(v18)), __PAIR__(_mm_cvtsi128_si32(_mm_srli_si128(v18, 12)), _mm_cvtsi128_si32(_mm_srli_si128(v18, 8))), *((__int64 *)&v33 + 1));
}
else
{
v13 = 0;
}
sub_405740(&v31);
}
校验规则与算法
name的检查与计算
输入值name的检查规则为:
长度为39。
中间以 # 分隔,通过堆偏移及后续计算,可以得出name分为8个部分,每部分4字节。
除 # 分隔符外,name由hex字符组成,大小写不敏感,计算前全部转成大写
记name的8个部分分别为a0,a1...a7,记结果的输出为b0,b1...b4,name转换成5个大整数的计算公式整理如下:
b0 = (a[0][0]*a[1][0] <<16) + (a[0][1]^a[2][1]) + (a[0][2]%(a[3][2]+1)+1) + a[0][3]/(a[3][3]+1)
b1 = ((a[1][0]^a[5][0]) <<16) + a[1][1]%(a[6][1]+3) + (a[1][2]/(a[7][2]+1)+5) + a[1][3]+a[0][3]
b2 = ((a[2][0]/(a[1][0]+3) <<16) ^ (a[2][1]%a[3][1])) + (a[2][2]+a[5][2]+12) + a[2][3]+a[7][3] b3 = (((((a[0][1]^a[2][3]) *(a[3][1]+a[1][3])) &(a[5][2]&a[4][2]))*a[7][3] +b1)*a[6][0]*b0)
b3 = b3-((b3-b1) %(2*b0))
b4 = ((a[4][0]^a[3][0]) <<16) *(a[3][1]%(a[4][1]+2)) + (a[3][2]%(a[4][2]+5)+7) + a[3][3]*a[4][3]
base64解码算法
输入的code先进行base64解码,此处的base64解码算法与标准版有两点改动:
编解码表改了
进行查表索引时,加了异或操作
现用的编码表为:
ZO6Kq79L&CPWvNopzQfghDRSG@di*kAB8rsFewxlm+/u5a^2YtTJUVEn0$HI34y#
AES解密算法
输入的code经过base64解码后进行AES解密。
AES解密算法也是魔改过的,主要改动如下:
sbox改动。
密钥扩展时,取key的顺序改动。
取轮密钥时的顺序改动,与扩展密钥的改动对应。应该可以归结为key的变更。
行变换时的改动,及解密时第一轮字节代换与行变换更改了顺序。
AES解密后,检验解密结果为32字节,前24字节为3个整数,后8字节以上文中提到的的规则检查。
方程验证算法
将name及code计算得到的8个整数分别记为b0,b1,b2,b3,b4,c0,c1,c2。
最后的检验计算公式如下(64bit计算,溢出部分不计):
b2 + (b1 + b0 * c0) * c0 == c1
(b1 - b3) * (b1 - b3) == 4 * (b3 * c0 - (b1 + b0 * c0) * c0) * b0
b2 + (b1 + b0 * b4 - b3) * b4 == c2
以上公式可写成为:
b2 + (b1 + b0 * c0) * c0 == c1
b0*c0*c0 + (b1 - b3)*c0 +(b1 - b3) * (b1 - b3)/(4*b0) == 0
b2 + (b1 + b0 * b4 - b3) * b4 == c2
第二个式子就是一个二元一次方程,通过求根公式,可以得到c0的解为 (b3-b1)/(2*b0) 。这个式子明显能得到整数解,在上 面的 b3 的计算公式就能看出:
b3 = b3-((b3-b1) %(2*b0))
其它的计算不在话下,最后整理的python计算公式如下:
c[2] = (b[2] + (b[1] + (b[0] * b[4]) - b[3]) * b[4])&0xffffffffffffffff
c[0] = ((b[3] - b[1]) / ( 2 * b[0]))&0xffffffffffffffff
c[1] = (b[2] + (b[1] + (b[0] * c[0])) * c[0])&0xffffffffffffffff
感觉多解还是有的,标准版只是少了AES环节。
测试数据
UserName:1234#5678#90ab#cdef#1234#5678#90ab#cdef Regcode:HxvIC@h4Udf3Y9ti36wmrGVZCG@Q@64ABSv@5ou7BS+=
UserName:1111#1111#1111#1111#1111#1111#1111#1111 Regcode:la9K+2h4UdQH5Pku2Z/PglB/aVrDfe87BSv@5ou7BS+=
注册机说明
注册机使用的是python语言,版本2.7。未使用任何第三方库。
自动化测试脚本
# -*- coding:utf-8 -*-
#Anthor: poyoten @ Chamd5
#Mail: poyoten@hotmail.com
import re
InvSbox = (
0x9C, 0x6C, 0xF4, 0x32, 0xAE, 0x75, 0x9F, 0x3A, 0x4F, 0x0F, 0xD9, 0x09, 0x5A, 0xC2, 0xCB, 0x61,
0x7B, 0x04, 0xE2, 0x25, 0x9D, 0x2E, 0x23, 0x1E, 0xDB, 0x83, 0x5C, 0x6A, 0xB7, 0x5E, 0xC4, 0x26,
0xBE, 0xE3, 0x15, 0x6F, 0x56, 0x31, 0xFE, 0x0E, 0xBA, 0x00, 0x6D, 0xE0, 0x9E, 0xAF, 0xD0, 0x0A,
0x73, 0x7A, 0x78, 0x8E, 0x99, 0x71, 0xE8, 0xA6, 0x63, 0x6E, 0x86, 0x14, 0x0D, 0x97, 0x96, 0x80,
0xAD, 0xBD, 0x48, 0x12, 0xB0, 0xEB, 0xCA, 0x6B, 0x52, 0xB4, 0x35, 0xB3, 0x5D, 0x2C, 0x2A, 0xF6,
0x9B, 0xE6, 0xA2, 0xD8, 0x89, 0xCE, 0xDD, 0x2B, 0x44, 0x59, 0xF0, 0xF2, 0xA9, 0x22, 0x7F, 0xEC,
0x40, 0x8D, 0xA4, 0x5B, 0x8F, 0x0C, 0xB1, 0xAC, 0x46, 0x3F, 0xA3, 0x01, 0xAA, 0x57, 0x1C, 0xF8,
0xF1, 0xFF, 0x81, 0x10, 0xBB, 0xDF, 0x60, 0x41, 0xC3, 0xF5, 0xD1, 0x38, 0xD7, 0x47, 0x1F, 0xCC,
0xC1, 0x27, 0x82, 0xCD, 0xEE, 0x90, 0x4D, 0x98, 0xD3, 0xBF, 0xE5, 0x19, 0x70, 0x49, 0xB6, 0xE4,
0xB9, 0x93, 0x1D, 0x24, 0x8A, 0x88, 0x91, 0xD2, 0x76, 0x17, 0x69, 0x58, 0x68, 0x66, 0x16, 0xB8,
0x7E, 0x29, 0x05, 0xC9, 0x3C, 0x21, 0x92, 0x1B, 0xA1, 0xA7, 0xFD, 0x1A, 0xE7, 0x30, 0x33, 0x9A,
0x54, 0xFB, 0x08, 0xAB, 0x87, 0xCF, 0xA5, 0x4C, 0x5F, 0xF3, 0xF9, 0x2F, 0x03, 0x39, 0xFC, 0x28,
0x8B, 0xC5, 0x42, 0x4A, 0x37, 0x4E, 0x94, 0x95, 0xD4, 0xBC, 0x3E, 0x72, 0xED, 0xEA, 0x74, 0x77,
0x3B, 0x45, 0x34, 0x20, 0xC0, 0xC7, 0x8C, 0x0B, 0x67, 0xDC, 0x62, 0xEF, 0x2D, 0x50, 0x13, 0x84,
0xE1, 0x07, 0x4B, 0x3D, 0x06, 0x7D, 0xD6, 0x11, 0x64, 0xD5, 0xA0, 0x43, 0xB2, 0xE9, 0x02, 0x65,
0xB5, 0x36, 0x18, 0xA8, 0xDE, 0x7C, 0xFA, 0xDA, 0x51, 0xC6, 0x85, 0xF7, 0x53, 0x79, 0xC8, 0x55,
)
Sbox = (
0x29, 0x6B, 0xEE, 0xBC, 0x11, 0xA2, 0xE4, 0xE1, 0xB2, 0x0B, 0x2F, 0xD7, 0x65, 0x3C, 0x27, 0x09,
0x73, 0xE7, 0x43, 0xDE, 0x3B, 0x22, 0x9E, 0x99, 0xF2, 0x8B, 0xAB, 0xA7, 0x6E, 0x92, 0x17, 0x7E,
0xD3, 0xA5, 0x5D, 0x16, 0x93, 0x13, 0x1F, 0x81, 0xBF, 0xA1, 0x4E, 0x57, 0x4D, 0xDC, 0x15, 0xBB,
0xAD, 0x25, 0x03, 0xAE, 0xD2, 0x4A, 0xF1, 0xC4, 0x7B, 0xBD, 0x07, 0xD0, 0xA4, 0xE3, 0xCA, 0x69,
0x60, 0x77, 0xC2, 0xEB, 0x58, 0xD1, 0x68, 0x7D, 0x42, 0x8D, 0xC3, 0xE2, 0xB7, 0x86, 0xC5, 0x08,
0xDD, 0xF8, 0x48, 0xFC, 0xB0, 0xFF, 0x24, 0x6D, 0x9B, 0x59, 0x0C, 0x63, 0x1A, 0x4C, 0x1D, 0xB8,
0x76, 0x0F, 0xDA, 0x38, 0xE8, 0xEF, 0x9D, 0xD8, 0x9C, 0x9A, 0x1B, 0x47, 0x01, 0x2A, 0x39, 0x23,
0x8C, 0x35, 0xCB, 0x30, 0xCE, 0x05, 0x98, 0xCF, 0x32, 0xFD, 0x31, 0x10, 0xF5, 0xE5, 0xA0, 0x5E,
0x3F, 0x72, 0x82, 0x19, 0xDF, 0xFA, 0x3A, 0xB4, 0x95, 0x54, 0x94, 0xC0, 0xD6, 0x61, 0x33, 0x64,
0x85, 0x96, 0xA6, 0x91, 0xC6, 0xC7, 0x3E, 0x3D, 0x87, 0x34, 0xAF, 0x50, 0x00, 0x14, 0x2C, 0x06,
0xEA, 0xA8, 0x52, 0x6A, 0x62, 0xB6, 0x37, 0xA9, 0xF3, 0x5C, 0x6C, 0xB3, 0x67, 0x40, 0x04, 0x2D,
0x44, 0x66, 0xEC, 0x4B, 0x49, 0xF0, 0x8E, 0x1C, 0x9F, 0x90, 0x28, 0x74, 0xC9, 0x41, 0x20, 0x89,
0xD4, 0x80, 0x0D, 0x78, 0x1E, 0xC1, 0xF9, 0xD5, 0xFE, 0xA3, 0x46, 0x0E, 0x7F, 0x83, 0x55, 0xB5,
0x2E, 0x7A, 0x97, 0x88, 0xC8, 0xE9, 0xE6, 0x7C, 0x53, 0x0A, 0xF7, 0x18, 0xD9, 0x56, 0xF4, 0x75,
0x2B, 0xE0, 0x12, 0x21, 0x8F, 0x8A, 0x51, 0xAC, 0x36, 0xED, 0xCD, 0x45, 0x5F, 0xCC, 0x84, 0xDB,
0x5A, 0x70, 0x5B, 0xB9, 0x02, 0x79, 0x4F, 0xFB, 0x6F, 0xBA, 0xF6, 0xB1, 0xBE, 0xAA, 0x26, 0x71,
)
# learnt from http://cs.ucsb.edu/~koc/cs178/projects/JT/aes.c
xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)
Rcon = (
0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39,
)
key_exp = [
[0x77, 0x65, 0x6c, 0x63], [0x6f, 0x6d, 0x65, 0x67], [0x73, 0x6c, 0x61, 0x62], [0x32, 0x30, 0x31, 0x38],
[0x34, 0x72, 0x5b, 0xe3], [0x5b, 0x1f, 0x3e, 0x84], [0x28, 0x73, 0x5f, 0xe6], [0x1a, 0x43, 0x6e, 0xde],
[0x1e, 0x26, 0xec, 0x4e], [0x45, 0x39, 0xd2, 0xca], [0x6d, 0x4a, 0x8d, 0x2c], [0x77, 0x09, 0xe3, 0xf2],
[0xb7, 0xe7, 0x4a, 0x49], [0xf2, 0xde, 0x98, 0x83], [0x9f, 0x94, 0x15, 0xaf], [0xe8, 0x9d, 0xf6, 0x5d],
[0xa6, 0x41, 0x9a, 0xc3], [0x54, 0x9f, 0x02, 0x40], [0xcb, 0x0b, 0x17, 0xef], [0x23, 0x96, 0xe1, 0xb2],
[0xf8, 0x41, 0xa1, 0x14], [0xac, 0xde, 0xa3, 0x54], [0x67, 0xd5, 0xb4, 0xbb], [0x44, 0x43, 0x55, 0x09],
[0xfb, 0x14, 0xbf, 0xb9], [0x57, 0xca, 0x1c, 0xed], [0x30, 0x1f, 0xa8, 0x56], [0x74, 0x5c, 0xfd, 0x5f],
[0x1c, 0x42, 0x1b, 0xf8], [0x4b, 0x88, 0x07, 0x15], [0x7b, 0x97, 0xaf, 0x43], [0x0f, 0xcb, 0x52, 0x1c],
[0x6e, 0x59, 0x1f, 0x22], [0x25, 0xd1, 0x18, 0x37], [0x5e, 0x46, 0xb7, 0x74], [0x51, 0x8d, 0xe5, 0x68],
[0x9a, 0x37, 0xb4, 0xcb], [0xbf, 0xe6, 0xac, 0xfc], [0xe1, 0xa0, 0x1b, 0x88], [0xb0, 0x2d, 0xfe, 0xe0],
[0x51, 0xee, 0x42, 0x39], [0xee, 0x08, 0xee, 0xc5], [0x0f, 0xa8, 0xf5, 0x4d], [0xbf, 0x85, 0x0b, 0xad]
]
def text2matrix(text):
matrix = []
for i in range(16):
byte = (text >> (8 * (15 - i))) & 0xFF
if i % 4 == 0:
matrix.append([byte])
else:
matrix[i / 4].append(byte)
return matrix
def matrix2text(matrix):
text = 0
for i in range(4):
for j in range(4):
text |= (matrix[i][j] << (120 - 8 * (4 * i + j)))
return text
class AES:
def __init__(self, master_key):
self.change_key(master_key)
def change_key(self, master_key):
self.round_keys = text2matrix(master_key)
for i in range(4, 4 * 11):
self.round_keys.append([])
if i % 4 == 0:
byte0 = self.round_keys[i - 1][3] ^ Sbox[self.round_keys[i - 1][3]] ^ self.round_keys[i-4][0] #^ Rcon[i / 4]
byte1 = self.round_keys[i - 1][2] ^ (Sbox[self.round_keys[i - 1][2]] +1) ^ self.round_keys[i-4][1]
byte2 = self.round_keys[i - 1][0] ^ (Sbox[self.round_keys[i - 1][0]] +2) ^ self.round_keys[i-4][2]
byte3 = self.round_keys[i - 1][1] ^ (Sbox[self.round_keys[i - 1][1]] +3) ^ self.round_keys[i-4][3]
bytes = (byte0<<24 | byte1<<16 | byte2<<8 | byte3)^(byte1&(Rcon[i/4]<<18))
self.round_keys[i].append((bytes>>24)&0xff)
self.round_keys[i].append((bytes>>16)&0xff)
self.round_keys[i].append((bytes>>8)&0xff)
self.round_keys[i].append(bytes&0xff)
else:
for j in range(4):
byte = self.round_keys[i - 4][j]^ self.round_keys[i - 1][j]
self.round_keys[i].append(byte)
def encrypt(self, plaintext):
self.plain_state = text2matrix(plaintext)
self.__add_round_key(self.plain_state, self.round_keys[:4])
for i in range(1, 10):
self.__round_encrypt(self.plain_state, self.round_keys[4 * i : 4 * (i + 1)])
self.__shift_rows(self.plain_state)
self.__sub_bytes(self.plain_state)
self.__add_round_key(self.plain_state, self.round_keys[40:])
return matrix2text(self.plain_state)
def decrypt(self, ciphertext):
self.cipher_state = text2matrix(ciphertext)
tmp = list(self.cipher_state)
self.__add_round_key(self.cipher_state, self.round_keys[40:])
self.__inv_sub_bytes(self.cipher_state)
self.__inv_shift_rows(self.cipher_state)
for i in range(9, 0, -1):
self.__round_decrypt(self.cipher_state, self.round_keys[4 * i : 4 * (i + 1)])
self.__add_round_key(self.cipher_state, self.round_keys[:4])
return matrix2text(self.cipher_state)
def __add_round_key(self, s, k):
for i in range(4):
s[i][3] ^= k[i][1]
s[i][2] ^= k[i][0]
s[i][1] ^= k[i][2]
s[i][0] ^= k[i][3]
def __round_encrypt(self, state_matrix, key_matrix):
self.__sub_bytes(state_matrix)
self.__shift_rows(state_matrix)
self.__mix_columns(state_matrix)
self.__add_round_key(state_matrix, key_matrix)
def __round_decrypt(self, state_matrix, key_matrix):
self.__add_round_key(state_matrix, key_matrix)
self.__inv_mix_columns(state_matrix)
self.__inv_shift_rows(state_matrix)
self.__inv_sub_bytes(state_matrix)
def __sub_bytes(self, s):
for i in range(4):
for j in range(4):
s[i][j] = Sbox[s[i][j]]
def __inv_sub_bytes(self, s):
for i in range(4):
for j in range(4):
s[i][j] = InvSbox[s[i][j]]
def __shift_rows(self, s):
s[1][0], s[1][1], s[1][2], s[1][3] = s[1][1], s[1][2],s[1][3],s[1][0]
s[2][0], s[2][1], s[2][2], s[2][3] = s[2][2],s[2][3],s[2][0], s[2][1]
s[3][0], s[3][1], s[3][2], s[3][3] = s[3][3], s[3][0],s[3][1],s[3][2]
def __inv_shift_rows(self, s):
s[1][0], s[1][1], s[1][2], s[1][3] = s[1][3], s[1][0], s[1][1], s[1][2]
s[2][0], s[2][1], s[2][2], s[2][3] = s[2][2], s[2][3], s[2][0], s[2][1]
s[3][0], s[3][1], s[3][2], s[3][3] = s[3][1], s[3][2], s[3][3], s[3][0]
def __mix_single_column(self, a):
# please see Sec 4.1.2 in The Design of Rijndael
t = a[0] ^ a[1] ^ a[2] ^ a[3]
u = a[0]
a[0] ^= t ^ xtime(a[0] ^ a[1])
a[1] ^= t ^ xtime(a[1] ^ a[2])
a[2] ^= t ^ xtime(a[2] ^ a[3])
a[3] ^= t ^ xtime(a[3] ^ u)
def __mix_columns(self, s):
for i in range(4):
self.__mix_single_column(s[i])
def __inv_mix_columns(self, s):
# see Sec 4.1.3 in The Design of Rijndael
for i in range(4):
u = xtime(xtime(s[i][0] ^ s[i][2]))
v = xtime(xtime(s[i][1] ^ s[i][3]))
s[i][0] ^= u
s[i][1] ^= v
s[i][2] ^= u
s[i][3] ^= v
self.__mix_columns(s)
def tips():
tip = '''
##########################################n
# 2018游戏安全技术竞赛 ROUND 1 #n
# keymake #n
# name format: x#x#x#x#x#x#x#x #n
# x is 4-digits hex #n
##########################################n
'''
print tip.decode('utf-8')
def nameinput():
name = raw_input('Input name:')
return name
def namecheck(name):
print '[*]Checking name...'
if len(name) != 39:
print '[*]Name length is wrong'
return False
lname = name.split('#')
pat = '[dA-Fa-f]{4}'
for i in lname:
if re.match(pat,i) == None:
print '[*]Name format is wrong'
return False
return True
def namecompute(name):
print '[*]Computing name...'
lname = name.split('#')
lname = [list(i.upper()) for i in lname]
a = [[ord(i) for i in j] for j in lname ]
b0 = (a[0][0]*a[1][0] <<16) + (a[0][1]^a[2][1]) + (a[0][2]%(a[3][2]+1)+1) + a[0][3]/(a[3][3]+1)
b1 = ((a[1][0]^a[5][0]) <<16) + a[1][1]%(a[6][1]+3) + (a[1][2]/(a[7][2]+1)+5) + a[1][3]+a[0][3]
b2 = ((a[2][0]/(a[1][0]+3) <<16) ^ (a[2][1]%a[3][1])) + (a[2][2]+a[5][2]+12) + a[2][3]+a[7][3]
b3 = (((((a[0][1]^a[2][3]) *(a[3][1]+a[1][3])) &(a[5][2]&a[4][2]))*a[7][3] +b1)*a[6][0]*b0)
b3 = b3-((b3-b1) %(2*b0))
b4 = ((a[4][0]^a[3][0]) <<16) *(a[3][1]%(a[4][1]+2)) + (a[3][2]%(a[4][2]+5)+7) + a[3][3]*a[4][3]
b = [b0,b1,b2,b3,b4]
if (b[3] - b[1]) % ( 2 * b[0]) != 0:
print '[*]This name can't generate regcode!!!'
exit(0)
return b
def compcode(b):
print '[*]Computing regcode...'
c = [0,0,0]
c[2] = (b[2] + (b[1] + (b[0] * b[4]) - b[3]) * b[4])&0xffffffffffffffff
c[0] = ((b[3] - b[1]) / ( 2 * b[0]))&0xffffffffffffffff
c[1] = (b[2] + (b[1] + (b[0] * c[0])) * c[0])&0xffffffffffffffff
return c
def genformat(c):
s = ''
for i in c:
tmp = hex(i)[2:].replace('L','').rjust(16,'0').decode('hex')[::-1]
s += tmp
s += '8102'+'x00'*4
return s
def base(code):
nell = list(r'ZO6Kq79L&CPWvNopzQfghDRSG@di*kAB8rsFewxlm+/u5a^2YtTJUVEn0$HI34y#')
msg = list(code)
bs = ''
for i in msg:
bs+="0"*(8-len(bin(ord(i))[2:]))+bin(ord(i))[2:]
length_b = len(bs)
times = length_b/6
c=""
for i in range(0,times*6,6):
num = int(bs[i:i+6],2)
num = num^(num>>3)
c += nell[num]
ll = len(bs)%6
if ll == 2:
num = (int(bs[-2:],2)<<4) #+ (ord('=')&0xf)
num = num^(num>>3)
c += nell[num]
c += '=='
if ll == 4:
num = (int(bs[-4:],2)<<2)# + (ord('=')&0x3)
num = num^(num>>3)
c += nell[num]
c += '='
return c
if __name__ == '__main__':
tips()
key = 'welcomegslab2018'
name = nameinput()
if namecheck(name):
namenum = namecompute(name)
code = compcode(namenum)
code = genformat(code)
print '[*]Generating final Regcode...'
cipher = AES(int(key.encode('hex'),16))
c1 = cipher.encrypt(int(code.encode('hex')[:32],16))
c2 = cipher.encrypt(int(code.encode('hex')[32:],16))
fcode = base((hex(c1)[2:].replace('L','').rjust(32,'0')+hex(c2)[2:].replace('L','').rjust(32,'0')).decode('hex'))
print '[*]final regcode info is:n'+'UserName:'+name+'nRegcode:'+fcode
本文作者:ChaMd5安全团队
本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/71366.html