Winhex 21.2 分析
目录
winhex21.2
只针对21.2,其他版本不可以,因为data2解密时的AES key(PRIVATE_KEY)不同
data1 字段没有继续跟建议直接指定
21C99167CC69236A2EB9540CF881EFF6
,无法使用
专业工具
,功能不熟,keygen详见py脚本
1、check data1&Cksm
许可信息内存结构
struct LicInfo
{
char name[81];
char mailarr[61];
char homeaddr[61];
char keydata[32];
};
BSS:00718264 ; char name_718264[81]
BSS:00718264 name_718264 db 51h dup(?) ; DATA XREF: check_lic_6869AC+D0↑o
BSS:00718264 ; check_lic_6869AC+12E↑o ...
BSS:007182B5 ; _BYTE mailaddr_7182B5
BSS:007182B5 mailaddr_7182B5 db 3Dh dup(?) ; DATA XREF: check_lic_6869AC+172↑o
BSS:007182B5 ; check_lic_6869AC+5CD↑o ...
BSS:007182F2 ; _BYTE homeaddr_7182F2[61]
BSS:007182F2 homeaddr_7182F2 db 3Dh dup(?) ; DATA XREF: check_lic_6869AC+5DB↑o
BSS:007182F2 ; sub_6954BC+23B↑o
BSS:0071832F ; char keydata_71832F[32]
BSS:0071832F keydata_71832F db 20h dup(?)
check_lic_data1_6869AC
data1 校验:
1、
高3位==3;低5位 ==1; ==>0x61
(name_718264.keydata[12] ^ name_718264.keydata[8] ^ 0xB7)
2、
开始时间 距离08/05/2015 0x4705
*(_WORD *)&name_718264.keydata[2] ^ *(_WORD *)&name_718264.keydata[12] ^ 0xEA69;
3、
结束时间 距离08/05/2015 0x4705
要小于0x611Cu 07/09/2024
要大于0x58E9u 08/28/2028
*(_WORD *)&name_718264.keydata[4] ^ *(_WORD *)&name_718264.keydata[6] ^ 0x159D
4、
用户数 小于=3750u 0xea6
number_718624 = *(_WORD *)&name_718264.keydata[0xA] ^ *(_WORD *)&name_718264.keydata[2] ^ 0x69C5;
Cksm 校验:
Cksm =crc32(LicInfo+b'sector-aligned')
char __fastcall check_lic_data1_6869AC(CHAR *input, const WCHAR *a2, char a3, char a4)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v25 = 0;
v38 = a3;
lpCaption = a2;
input1 = input;
v24 = &savedregs;
v23[1] = (unsigned int)&loc_6872B2;
v23[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList;
__writefsdword(0, (unsigned int)v23);
dara1_correct_718436 = 0;
*(_BYTE *)numb_3_6FD970 = 0;
v4 = 0;
byte_6F9400[0x24] = 0;
byte_6F9400[0x23] = 0;
byte_6F9400[0x20] = 0;
byte_6F9400[0x2F] = 0;
byte_6F9400[0x2C] = 0;
byte_6F9400[0x1A] = 0;
byte_6F9400[0x22] = 0;
byte_6F9400[0x21] = 0;
wFatDate = 0;
end_date_718620 = 0;
v37 = 0;
lpMultiByteStr = input1;
if ( !*input1 )
goto END_103;
v34 = name_718264.keydata[0];
v35 = name_718264.keydata[1];
while ( 1 )
{
_408B68 = find_408B68(lpMultiByteStr, '\x93');
if ( !_408B68 )
break;
*_408B68 = '"';
}
while ( 1 )
{
v6 = find_408B68(lpMultiByteStr, '\x94');
if ( !v6 )
break;
*v6 = '"';
}
if ( !(unsigned __int8)strip_687C94((char **)&lpMultiByteStr) )
goto END_103;
FillChar(&name_718264, 0xEBu);
if ( !(unsigned __int8)getLineStartToTemp_687EC0((int)&lpMultiByteStr, 0)
// Name:
|| lstrcmpiA(&temp_getdata_7191E4, Name__6FC884)
|| !(unsigned __int8)strip_687C94((char **)&lpMultiByteStr)
|| !(unsigned __int8)get_line_data_687D80((char **)&lpMultiByteStr) )
{
goto END_103;
}
str_copy_408D20(&name_718264, &temp_getdata_7191E4);
// mailto:
_409A00 = find_409A00(lpMultiByteStr, *mailto__6FDBF4);
if ( _409A00 )
{
v8 = find_408B68(_409A00, 0xD);
if ( v8 )
*v8 = 0;
// Altered by e-mail client?
sub_694EF4(lpMultiByteStr, *off_6FC868, 3);
}
v9 = 1;
mailarr = name_718264.mailarr;
// mailaddr和homeaddr 分别61字节
do
{
if ( !(unsigned __int8)strip_687C94((char **)&lpMultiByteStr)
|| !(unsigned __int8)getLineStartToTemp_687EC0((int)&lpMultiByteStr, 0)
// Addr
|| !str_isequal_409E2C(&temp_getdata_7191E4, Addr_6FD2C0, 4, 1)
|| !(unsigned __int8)strip_687C94((char **)&lpMultiByteStr)
|| !(unsigned __int8)get_line_data_687D80((char **)&lpMultiByteStr) )
{
goto END_103;
}
str_copy_408D20(mailarr, &temp_getdata_7191E4);
++v9;
mailarr += 61;
}
while ( v9 != 3 );
key_data_flag_7183E4 = 2;
v11 = 1;
keydata = name_718264.keydata;
// 两个 Data/Key
do
{
if ( !(unsigned __int8)strip_687C94((char **)&lpMultiByteStr)
|| !(unsigned __int8)getLineStartToTemp_687EC0((int)&lpMultiByteStr, 0)
// Key
// Data
|| !str_isequal_409E2C(&temp_getdata_7191E4, Key_6FC3A8, 3, 1)
&& !str_isequal_409E2C(&temp_getdata_7191E4, Data_6FCEC4, 4, 1) )
{
goto END_103;
}
// Data
if ( v11 == 1 && str_isequal_409E2C(&temp_getdata_7191E4, Data_6FCEC4, 4, 1) )
key_data_flag_7183E4 = 0x14; // 第一个为Data时
if ( !(unsigned __int8)strip_687C94((char **)&lpMultiByteStr)
|| !(unsigned __int8)get_line_data_687D80((char **)&lpMultiByteStr)
|| hexstr2bytes_40A81C(&temp_getdata_7191E4, keydata, 0xFFFFFFFF, 0x10, 0) != 0x10 )
{
goto END_103;
}
++v11;
keydata += 0x10;
}
while ( v11 != 3 );
if ( key_data_flag_7183E4 == 2 )
// 第一个为key时
key_data_flag_7183E4 = name_718264.keydata[0xD] & 0x1F;
else
// data this one
key_data_flag_7183E4 = ((name_718264.keydata[0xC] ^ name_718264.keydata[8] ^ 0xB7) & 0x1F) + 0x14;
// b c d f 10 11 12 13 14 15
if ( (unsigned __int8)key_data_flag_7183E4 < 0xBu
|| (unsigned __int8)key_data_flag_7183E4 > 0x15u
|| key_data_flag_7183E4 == 0xE )
{
goto LABEL_101;
}
if ( (unsigned __int8)key_data_flag_7183E4 < 0xCu )// 0xb 时 错误
{
if ( (unsigned __int16)(*(_WORD *)name_718264.keydata ^ *(_WORD *)&name_718264.keydata[0xE]) < 1235u )
sub_692E04(0x3C);
else
sub_692E04(0x2B);
sub_687C2C(1);
goto END_103;
}
if ( (unsigned __int8)key_data_flag_7183E4 >= 0x14u )
// this one
wFatDate = *(_WORD *)&name_718264.keydata[4] ^ *(_WORD *)&name_718264.keydata[6] ^ 0x159D;// this way
else
wFatDate = *(_WORD *)name_718264.keydata ^ *(_WORD *)&name_718264.keydata[0xE];
if ( (unsigned __int8)key_data_flag_7183E4 >= 0x14u )
{
// this one
star_date = *(_WORD *)&name_718264.keydata[2] ^ *(_WORD *)&name_718264.keydata[12] ^ 0xEA69;
v28 = star_date < 0;
if ( (wFatDate & 0x4000) != 0 )
wFatDate &= ~0x4000u;
else
start_date1_71861E = (star_date & 0x3FFF) + 0x4705;// 天数,距离 08/05/2015
}
*(_BYTE *)evaluation_6FD0FC = (wFatDate & 0x8000u) != 0;
if ( *(_BYTE *)evaluation_6FD0FC )
wFatDate &= ~0x8000u;
if ( (unsigned __int8)key_data_flag_7183E4 >= 0x14u )
wFatDate += 0x4705; // 08/05/2015
// 得到结束日期
if ( *(_BYTE *)evaluation_6FD0FC )
end_date_718620 = wFatDate;
// 07/09/2024
v29 = wFatDate >= 0x58E9u;
// 08/28/2028
if ( wFatDate < 0x611Cu )
{
DosDateTimeToFileTime(wFatDate, 0, &FileTime);
get_date_str_41D18C(&FileTime, lic_FileTime_718A60);
if ( key_data_flag_7183E4 != 0x15 ) // !=0x15 error
{
name_718264.name[0] = 0;
*(_DWORD *)name_718264.keydata = 0;
*(_BYTE *)numb_3_6FD970 = 0;
if ( v38 )
{
sub_40C060(2, (int)&v25);
*off_6FDA08 = System::__linkproc__ ValLong(v25, v31);
}
if ( v29 )
{
LOBYTE(v4) = 1;
sub_692E04(0x2B);
}
else
{
sub_692E04(0x3C);
}
v14 = sub_4211C4(v4, 3, 0x47Bu);
sub_420A50((int)v14, (int)&history_719410, user_txt);
sub_420A50((int)&history_719410, (int)&history_719410, lic_FileTime_718A60);
if ( (_BYTE)v4 )
{
strcopy_409854((int)&history_719410, (int)" -> OK");
str_40C5BC(&history_719410);
v15 = sub_4211C4(v4, 3, 0x7Fu);
sub_409594(&history_719410, v15);
}
if ( lpCaption )
MessageBoxW(0, &history_719410, lpCaption, 0x30u);
else
sub_6949CC(&history_719410, 3);
goto END_103;
}
strip_687C94((char **)&lpMultiByteStr);
if ( !(unsigned __int8)getLineStartToTemp_687EC0((int)&lpMultiByteStr, 0) )
goto LABEL_101;
// Cksm
if ( lstrcmpiA(&temp_getdata_7191E4, Cksm_6FC6CC) )
goto LABEL_101;
strip_687C94((char **)&lpMultiByteStr);
if ( !(unsigned __int8)getLineStartToTemp_687EC0((int)&lpMultiByteStr, 0) )
goto LABEL_101;
if ( (int)hexstr2bytes_40A81C(&temp_getdata_7191E4, v33, 0xFFFFFFFF, 4, 0) < 1 )
goto LABEL_101;
remove_40BD94(&name_718264, ' ', 1);
remove_40BD94(name_718264.mailarr, 0x20, 1);
remove_40BD94(name_718264.homeaddr, 0x20, 1);
hash_init_417784(v26, 6, 0); // 6-->crc32
hash_update_417A04(v26, name_718264.name, 0xEB);
// sector-aligned
hash_update_417A04(v26, sector_aligned_6FD928, 0xE);
hash_final_417D18(v26, out);
if ( *(_DWORD *)out != *(_DWORD *)v33 )
goto LABEL_101;
// 3
*(_BYTE *)numb_3_6FD970 = (unsigned __int8)(name_718264.keydata[0xC] ^ name_718264.keydata[8] ^ 0xB7) >> 5;
if ( *(_BYTE *)numb_3_6FD970 == 6 && v28 )
*xway_ctr_6FCC58 = 1;
if ( *(_BYTE *)numb_3_6FD970 == 4 )
{
*(_BYTE *)numb_3_6FD970 = 0;
goto LABEL_101;
}
number_718624 = *(_WORD *)&name_718264.keydata[0xA] ^ *(_WORD *)&name_718264.keydata[2] ^ 0x69C5;
if ( (unsigned __int16)number_718624 > 0xEA6u )// 大于 error
{
LABEL_102:
FillChar(&name_718264, 0xEBu);
wFatDate = 0;
*(_BYTE *)numb_3_6FD970 = 0;
start_date1_71861E = 0;
goto END_103;
}
if ( *(_BYTE *)numb_3_6FD970 == 6 )
{
LABEL_101:
sub_687C2C(0);
goto LABEL_102;
}
sub_68693C();
str_copy_408D20(license_717CB4, input1);
if ( !a4 && (v34 != name_718264.keydata[0] || v35 != name_718264.keydata[1]) )
{
if ( !find_409A00(input1, *license_file_6FCB4C) )
{
str_copy_408D20(license_717CB4, "// ");
// WinHex
strcat_40953C(license_717CB4, *(_BYTE **)off_6FD834);
// license file
strcat_40953C(license_717CB4, *license_file_6FCB4C);
str_app_end_40C594(license_717CB4);
str_app_end_40C594(license_717CB4);
strcat_40953C(license_717CB4, input1);
}
sub_421728((unsigned __int8 *)user_txt, &history_719410, 0);// user.txt 历史记录 (F4)
wstr_4096E8(NewFileName, (int)&history_719410);
// .bak
strcopy_409854((int)NewFileName, (int)off_6FD1DC[0]);
if ( (unsigned __int8)sub_419ACC(&history_719410, 0) )
MoveFileW(&history_719410, NewFileName);
wstr_4096E8(NewFileName, (int)&history_719410);
v16 = strlen_408C04((int)license_717CB4);
v17 = sub_41A4F0((int)NewFileName, (int)license_717CB4, v16);
if ( !v17 )
{
v18 = sub_4211C4(0, 3, 0x31Du);
sub_68C330(v18, NewFileName);
strcopy_409854((int)&history_719410, (int)" ");
if ( !dara1_correct_718436 )
*(_DWORD *)name_718264.keydata = 0;
v22 = sub_408B18((int)&history_719410);
v19 = sub_4211C4(0, 3, 0x3Du);
sub_420A50((int)v19, v22, *(LPCSTR *)off_6FD834);
// "XXX\user.txt" 创建成功。 重新启动程序 WinHex 立即重启?
v20 = sub_694A14(&history_719410, *(LPCSTR *)off_6FD834, 0x1002, 0xFFFFFFFC);
if ( (_BYTE)v20 == 1 )
{
LOBYTE(v20) = 1;
sub_692C74(v20);
}
goto END_103;
}
sub_68A1D0(v17, (int)NewFileName, 0x53u, 0, 0);
}
dara1_correct_718436 = 0;
if ( v29 && *(_DWORD *)name_718264.keydata != 0 )
{
if ( (unsigned __int8)(*(_BYTE *)numb_3_6FD970 - 2) < 2u || *(_BYTE *)numb_3_6FD970 == 6 )
// need 1
dara1_correct_718436 = 1;
}
else
{
*(_BYTE *)numb_3_6FD970 = 0;
}
}
END_103:
__writefsdword(0, v23[0]);
v24 = (int *)&loc_6872B9;
System::__linkproc__ LStrClr(&v25);
return v37;
}
2、check data2(在特定功能时触发)
check_lic_data2_62DADC
int __fastcall check_lic_data2_62DADC(int a1)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
lpBuffer[0x28] = a1;
v1 = 0;
CursorA = LoadCursorA(0, (LPCSTR)0x7F02);
SetCursor(CursorA);
VirtualQuery((void *)lpAddress, &Buffer, 0x1Cu);
v24[0] = 0;
if ( VirtualProtect(Buffer.BaseAddress, 0x2000u, PAGE_EXECUTE_READWRITE, &flNewProtect) )
{
calc_lic_data2__key_62DD14();//计算解密key
v3 = sz_0x424_6E9404;
nSize = (unsigned __int16)sz_0x424_6E9404;
MOVE_407288(lpBuffer, (const void *)lpAddress, (unsigned __int16)sz_0x424_6E9404);
FillChar(keydata, 0x20u);
MOVE_407288(keydata, dec_lic_data2_to_privatekey_70E64C, 0x10);
LOBYTE(v5) = 1;
v6 = (__int64 *)AES_256_CTR_set_sha256key_6E0D60(0, block_xor_6E0AC4, v5, keydata, 0, 0);
AES_256_CTR_6E1130(v6, lpBuffer, nSize, 0i64, 0);
nullsub_15();
System::__linkproc__ FreeMem(v7, 0x67A);
FillChar(keydata, 0x20u);
lpBaseAddress = (int)lpAddress;
CurrentProcess = GetCurrentProcess();
if ( ((int (__stdcall *)(HANDLE, int, _DWORD *, unsigned int, int *))*ptr_WriteProcessMemory)(
CurrentProcess,
lpBaseAddress,
lpBuffer,
nSize,
&lpNumberOfBytesWritten) )
{
if ( nSize == lpNumberOfBytesWritten )
{
FillChar(lpBuffer, nSize);
VirtualProtect(Buffer.BaseAddress, 0x2000u, flNewProtect, &flOldProtect);
HIWORD(v17) = 0x2000;
LODWORD(v17) = Buffer.BaseAddress;
v9 = GetCurrentProcess();
FlushInstructionCache(v9, v17, flNewProtect);
// c2
if ( *(_BYTE *)((_DWORD)lpAddress + v3 - 1) == byte_6E9408 )
{
FillChar(dec_lic_data2_to_privatekey_70E64C, 0x10u);
LOBYTE(v1) = 1;
v10 = LoadCursorA(0, (LPCSTR)0x7F00);
SetCursor(v10);
return v1;
}
}
}
else
{
LastError_0 = (va_list *)GetLastError_0();
sub_40D910(LastError_0, v24, (WCHAR *)0x7F);
}
FillChar(dec_lic_data2_to_privatekey_70E64C, 0x10u);
}
else
{
v12 = (va_list *)GetLastError_0();
sub_40D910(v12, v24, (WCHAR *)0x7F);
}
v13 = LoadCursorA(0, (LPCSTR)0x7F00);
v14 = SetCursor(v13);
if ( v24[0] )
sub_694A14(v24, *(LPCSTR *)off_6FD5C8[0], 1, 0);
else
sub_687BC4(v14);
return v1;
}
calc_lic_data2__key_62DD14
int calc_lic_data2__key_62DD14()
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
// name,addr1,addr2
hash_init_417784(result, 9, 0); // 9--sha256
// char name[81];
// char mailarr[61];
// char homeaddr[61];
hash_update_417A04(result, ptr_lic_info_6FD5A8->name, 0xCB);
hash_final_417D18(result, (char *)user_data_SHA256);
LOBYTE(v0) = 1;
v1 = (__int64 *)AES_256_CTR_set_sha256key_6E0D60(0, block_xor_6E0AC4, v0, public_key_6E93E0, 0, 0);
AES_256_CTR_6E0F68(v1, (char *)user_data_SHA256, 0x20u, 0i64, 0);
nullsub_15();
System::__linkproc__ FreeMem(v2, 0x67A);
hash_init_417784(result, 9, 0);
hash_update_417A04(result, (char *)user_data_SHA256, 0x20);
hash_update_417A04(result, ptr_lic_info_6FD5A8->keydata, 0x10);
hash_final_417D18(result, (char *)lic_enc_data1_sha256);// data1_sha256
//
MOVE_407288(dec_lic_data2_to_privatekey_70E64C, &ptr_lic_info_6FD5A8->keydata[0x10], 0x10);
LOBYTE(v3) = 1;
v4 = (__int64 *)AES_256_CTR_set_sha256key_6E0D60(0, block_xor_6E0AC4, v3, (char *)lic_enc_data1_sha256, 0, 0);
AES_256_CTR_6E1130(v4, dec_lic_data2_to_privatekey_70E64C, 0x10u, 0i64, 0);
nullsub_15();
return System::__linkproc__ FreeMem(v5, 0x67A);
}
py
import binascii
import datetime
import hashlib
import random
#pip install pycryptodome
from Crypto.Cipher import AES
from Crypto.Util import Counter
from Crypto.Util.strxor import strxor
#winhex 21.2
PUB_KEY = bytes.fromhex('4DEFEAE49CF72587DEADB0E192EE26C2244563BD5B98461F5CDD4595932AB4FD')
#need a currect license to dec
PRIVATE_KEY=bytes.fromhex('725D5C612CCC0FF538E919E4365F3C4900000000000000000000000000000000')
CTR_INIT_VALUE = bytes.fromhex('D8DE2B1AA3036D3241607571F1E7C14D')
'''
// X-Ways license file
Name: semthex
Addr: ru-board.com
Addr: RUSSIA
Data: 21C99167CC69236A2EB9540CF881EFF6
Data: 2376D8CC4E33860CF5A9E379945DA0BE
Cksm: 3DD34CCA
'''
def str2dt(time_str, format="%Y-%m-%d"):
dt = datetime.datetime.strptime(time_str, format)
return dt
def datetime_to_dos_date(dt) -> int:
year = dt.year - 1980
month = dt.month
day = dt.day
dos_date: int = (year << 9) | (month << 5) | day
return dos_date
def dos_date_to_datetime(dos_date: int) -> str:
day = dos_date & 0x1F
month = (dos_date >> 5) & 0x0F
year = ((dos_date >> 9) & 0x7F) + 1980
# 创建 datetime 对象
dt = datetime.datetime(year, month, day)
# 返回格式化后的时间字符串
return dt.strftime('%Y-%m-%d')
def sha256(data: bytes) -> bytes:
return hashlib.sha256(data).digest()
def int_to_bytes(n: int, order='little') -> bytes:
# 获取整数的位长度
bit_length = n.bit_length()
# 计算所需的最小字节数
byte_length = (bit_length + 7) // 8
# 转换为字节序列,使用大端字节序
byte_array = n.to_bytes(byte_length, byteorder=order)
return byte_array
def zero_pad(data, block_size=16, already_pad_add=False):
# 计算需要填充的字节数
pad_len = block_size - (len(data) % block_size)
if not already_pad_add:
# 如果数据已经对齐,则 pad_len 会等于 block_size,此时无需填充
if pad_len == block_size:
return data
# 进行填充,使用 b'\0' 表示零字节填充
padded_data = data + b"\0" * pad_len
return padded_data
def aes_sha256_ctr(key: bytes, data: bytes, block: bytes = CTR_INIT_VALUE) -> bytes:
aeskey_sz=len(key)
if aeskey_sz!=32:
key=zero_pad(key,32)
aeskey = sha256(key)
print('[-]key:', key.hex())
print('[+]aeskey:', aeskey.hex())
print('[-]data:', data.hex())
initvalue=int.from_bytes(block, 'little')
counter = Counter.new(AES.block_size*8, initial_value=initvalue, little_endian=True)
# print(counter.values())
cipher = AES.new(key=aeskey, mode=AES.MODE_CTR, counter=counter)
ret = cipher.encrypt(data)
print('[+]enc/dec data:', ret.hex())
# count=len(data)//32
# end_=int_to_bytes(initvalue+count)
# print('[-]end counter:',end_.hex())
#ctr mode--> enc==dec
return ret
class LicInfo:
def __init__(self,name:bytes,mail:bytes,addr:bytes,data1_hexstr:bytes=b'',data2_hexstr:bytes=b'',cksm_hexstr:bytes=b'') -> None:
self.name=name
self.mail=mail
self.addr=addr
if data1_hexstr:
self.data1=bytes.fromhex(data1_hexstr.decode())
else:
x=LicInfo.gen_data1().hex()
self.data1=bytes.fromhex(x)
self.userinfo:bytes=LicInfo.mk_lic_userinfo(name,mail,addr)
if data2_hexstr:
self.data2=bytes.fromhex(data2_hexstr.decode())
else:
self.data2=self.calc_data2()
self.lic_allinfo=LicInfo.mk_lic(name,mail,addr,self.data1,self.data2)
# print('lic info:',self.lic_info.hex())
self.cksm=binascii.crc32(self.lic_allinfo+b'sector-aligned').to_bytes(4,'little')
if cksm_hexstr:
assert(self.cksm==bytes.fromhex(cksm_hexstr.decode()))
@staticmethod
def mk_lic_userinfo(name:bytes,mail:bytes,addr:bytes)->bytes:
lic_info=zero_pad(name,81)
lic_info+=zero_pad(mail,61)
lic_info+=zero_pad(addr,61)
return lic_info
@staticmethod
def mk_lic(name:bytes,mail:bytes,addr:bytes,data1:bytes,data2:bytes)->bytes:
'''
struct LicInfo
{
char name[81];
char mailarr[61];
char homeaddr[61];
char keydata[32];
};
'''
lic_info=LicInfo.mk_lic_userinfo(name,mail,addr)
lic_info+=zero_pad(data1,16)
lic_info+=zero_pad(data2,16)
'''
Cksm = binascii.crc32(lic_info+b'sector-aligned')
print(hex(Cksm))
'''
return lic_info
@staticmethod
def gen_data1()->bytes:
user_number=0xea6
enddate=datetime_to_dos_date(str2dt('2028-08-27'))
startdate=datetime_to_dos_date(str2dt('2024-08-10'))
data1=b''
# i_0_1= 0x1100
i_0_1=random.randint(0,0xffff)
OFFSET_DATE=0x4705
# end 要小于0x611Cu 07/09/2024 要大于0x58E9u 08/28/2028
# *(_WORD *)&name_718264.keydata[4] ^ *(_WORD *)&name_718264.keydata[6] ^ 0x159D; +0x4705
# i_4_5=0x5544
i_4_5=random.randint(0,0xffff)
i_6_7=(enddate-OFFSET_DATE)^0x159d^i_4_5
# i_9=random.randint(0,0xff)
i_9=0x99
# i_2_3=0x3322
i_2_3=random.randint(0,0xffff)
# start time
# *(_WORD *)&name_718264.keydata[2] ^ *(_WORD *)&name_718264.keydata[12] ^ 0xEA69;+0x4705
i_c_d=(startdate-OFFSET_DATE)^i_2_3^0xEA69
i_c=i_c_d&0xff
#user number <=3750u 0xea6
# *(_WORD *)&name_718264.keydata[0xA] ^ *(_WORD *)&name_718264.keydata[2] ^ 0x69C5;
i_a_b=user_number ^ i_2_3 ^ 0x69C5
# calc type
# 高3位==3;低5位 ==1; ==>0x610x61
# (name_718264.keydata[12] ^ name_718264.keydata[8] ^ 0xB7) ^0x61
i_8=i_c^0xB7 ^0x61
# i_e=random.randint(0,0xff)
i_e=0xee
data1+=i_0_1.to_bytes(2,'little')+\
i_2_3.to_bytes(2,'little')+\
i_4_5.to_bytes(2,'little')+\
i_6_7.to_bytes(2,'little')+\
i_8.to_bytes(1,'little')+\
i_9.to_bytes(1,'little')+\
i_a_b.to_bytes(2,'little')+\
i_c_d.to_bytes(2,'little')+\
i_e.to_bytes(1,'little')
'''
# WinHex_v19.8
unsigned int Random_check_sum_5C3358()
{
unsigned int result; // eax
HANDLE CurrentProcess; // eax
result = ((unsigned __int8)(lic_info_63EB5C.keydata[0xD] ^ lic_info_63EB5C.keydata[8])
* (unsigned __int8)(lic_info_63EB5C.keydata[0xB] ^ lic_info_63EB5C.keydata[0xC])
* ((unsigned __int8)lic_info_63EB5C.keydata[5] + (unsigned int)(unsigned __int8)lic_info_63EB5C.keydata[1])) >> 2;
if ( (_BYTE)result == lic_info_63EB5C.keydata[0xF] )
return result;
if ( Delphi_Random_402EA8(3) == 2 )
sub_5CC468();
CurrentProcess = GetCurrentProcess();
return TerminateProcess(CurrentProcess, 0);
}
'''
i_f= ((data1[0xD] ^ data1[8])
* (data1[0xB] ^ data1[0xC])
* (data1[5] + data1[1])
) >> 2
data1+=(i_f&0xff).to_bytes(1,'little')
return data1
def calc_data2(self)->bytes:
#name + mail + addr 81+61+61=0xcb
user_data = sha256(self.userinfo)
print('AES1:')
lic_enc = aes_sha256_ctr(PUB_KEY, user_data)
key2 = sha256(lic_enc+self.data1)
print('AES2:')
ret = aes_sha256_ctr(key2, PRIVATE_KEY)
return ret[:16]
def __repr__(self) -> str:
ret='// X-Ways license file\n\n'
ret+=f'Name: {self.name.decode()}\n'\
f'Addr: {self.mail.decode()}\n'\
f'Addr: {self.addr.decode()}\n'\
f'Data: {self.data1.hex().upper()}\n'\
f'Data: {self.data2.hex().upper()}\n'\
f'Cksm: {self.cksm.hex().upper()}\n'
return ret
# def __str__(self) -> str:
# return self.__repr__()
def read_lic(user_txt_path:str):
lines=[]
with open(user_txt_path,'rb') as f:
lines=f.readlines()
infos=[]
for x in lines:
if b':' in x:
temp=x.split(b':')[1].strip()
infos.append(temp)
return infos
def check_lic_data2(licpath=r'user.txt'):
infos=read_lic(licpath)
lic=LicInfo(*infos)
print(lic)
lic_info=lic.lic_allinfo
print('lic_info:',lic_info.hex())
lic_data1 = lic.data1
lic_data2 = lic.data2
lic_info_sha256 = sha256(lic_info[:0xcb])
print('AES1:')
lic_enc = aes_sha256_ctr(PUB_KEY, lic_info_sha256)
lic_enc_data1_sha256 = sha256(lic_enc+lic_data1)
print('AES2:')
lic_enc2 = aes_sha256_ctr(lic_enc_data1_sha256, lic_data2)
'''
need 725D5C612CCC0FF538E919E4365F3C4900000000000000000000000000000000
'''
print('data2 correct?',PRIVATE_KEY==zero_pad(lic_enc2,32))
# xordata = b''
# with open(r'code_data.bin', 'rb') as f:
# xordata = f.read()
# print('AES3:')
# print('[*]target key:',lic_enc2.hex())
# buf = aes_sha256_ctr(lic_enc2, xordata)
# with open('dec.bin', 'wb') as f:
# f.write(buf)
def check_data1(data1:bytes):#=bytes.fromhex('21C99167CC69236A2EB9540CF881EFF6')
type_15h=((data1[0xc]^data1[8]^0xb7) &0x1f) +0x14
print('\ncheck_data1:')
print('[-]type_15h:',type_15h)
numb_3=(data1[0xc]^data1[8]^0xb7)>>5
print('[-]numb_3:',numb_3)
wfatdate=strxor(strxor(data1[4:6],data1[6:8]),b'\x9d\x15')
i=int.from_bytes(wfatdate,'little')
enddate=dos_date_to_datetime(i+0x4705)
print('[-]enddate:',enddate)
date=strxor(strxor(data1[2:4],data1[12:14]),b'\x69\xea')
i=int.from_bytes(date,'little')
date=dos_date_to_datetime(i+0x4705)
print('[-]startdate:',date)
number=strxor(strxor(data1[10:12],data1[2:4]),b'\xc5\x69')#max 3750
print('[-]number:', int.from_bytes(number,'little'))
sum= ((data1[0xD] ^ data1[8])
* (data1[0xB] ^ data1[0xC])
* (data1[5] + data1[1])
) >> 2
sum&=0xff
print('[*]sum correct?',sum==data1[0xf])
def kg(name:bytes=b'test',mail:bytes=b'hello@world.com',addr:bytes=b'xxxxxxx'):
lic=LicInfo(name,mail,addr)
check_data1(lic.data1)
print('\n\nlic:\n')
print(lic)
pass
if __name__ == '__main__':
print('[*]only winhex 21.2!')
kg(b'test',b'hello@world.com',b'xxxxxxx')
# data1=LicInfo.gen_data1()
# data1=bytes.fromhex('21C99167CC69236A2EB9540CF881EFF6')
# check_data1( )
# check_lic_data2('user.txt')
pass
out:
[*]only winhex 21.2!
AES1:
[-]key: 4defeae49cf72587deadb0e192ee26c2244563bd5b98461f5cdd4595932ab4fd
[+]aeskey: 9b5c7ec628e4e879a2607be48e4c425b9d0717da2275de4d9697a99702c8862d
[-]data: 05dbd8fc480302dd8faf4259b773c7efb8d33bd1404654975ff46efb8339dbf5
[+]enc/dec data: bbf5a31c5d4d8aa52365d9cd3d385428c65daadaa5eeba6d40ccce13a37dd835
AES2:
[-]key: 05298696128c21de4bf83fab3009648b4ee9bb5e2fbb55f065e72b3f3fd9e266
[+]aeskey: 888b5a9827ff73c97c1ef18e5d8db6ede2e97b5b86189c2af553ae908e42699d
[-]data: 725d5c612ccc0ff538e919e4365f3c4900000000000000000000000000000000
[+]enc/dec data: 73d32c4abbc7218f0329be54bd337f7333bf32ef7f6d26cb76540cd7d78f2c88
check_data1:
[-]type_15h: 21
[-]numb_3: 3
[-]enddate: 2028-08-27
[-]startdate: 2024-08-10
[-]number: 3750
[*]sum correct? True
lic:
// X-Ways license file
Name: test
Addr: hello@world.com
Addr: xxxxxxx
Data: 43FF43B693B318BCF99920D12F4EEE61
Data: 73D32C4ABBC7218F0329BE54BD337F73
Cksm: 7BDDE4A7