抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

群晖罪大恶极,百姓怨声载道(

本文并不包含如何破解Surveillance Station的方法,也不提供可用的序列号,想要破解的可以关掉页面了(

本文分析的Surveillance Station版本为8.2.10-7310,但更新的⑨版本似乎并没有修改授权密钥的算法。

群晖并没有删除Surveillance Station的库的各种符号表,可以说是非常方便逆向了。

流水账

SYNO.SurveillanceStation.License.so

添加授权时API call直接指向这个文件,拖ida发现DoVerifyKey函数

upload successful

其使用输入的密钥先直接构造请求向群晖服务器(synosurveillance.synology.com)发送激活授权的请求,但这里这个请求他留了一个后门可以绕过:

upload successful

即执行以下命令即可

1
2
touch /var/packages/SurveillanceStation/target/off.conf
chown SurveillanceStation:SurveillanceStation /var/packages/SurveillanceStation/target/off.conf

服务器校验通过或者被绕过之后,执行到VerifyLicenseKey函数。

libssutils.so

VerifyLicenseKey函数,将传入的char *类型的License字符串转成了C++的string类,并检查了该序列号是否已经安装在本机,检查通过之后传入了VerifyKey函数。

upload successful

libssshm.so

校验序列号是否合法的核心函数就在这里了,大概内容就输入内容先用表一阵解码,然后取出其中的疑似BuildTimeCameraCount的值并通过SHA1校验其是否合法。

upload successful

对着IDA F5结果将其校验过程重写成py,如下,将ENTERYOURKEYHERE替换成一个合法的序列号,运行即可看到校验的结果和解码内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#coding=utf-8
from binascii import unhexlify
from hashlib import sha1

xstr = "BCDFGHJKMPQRTVWXY2346789"
LicenseKey_String = "ENTERYOURKEYHERE"

def long_to_bytes (val, endianness='big'):
width = val.bit_length()
width += 8 - ((width % 8) or 8)
fmt = '%%0%dx' % (width // 4)
s = unhexlify(fmt % val)
if endianness == 'little':
s = s[::-1]
return s

def BN_mask_bits(a, n):
n = int("1"*n, 2)
return a & n

def BN_num_bits(a):
return len(bin(a)[2:])

def BN_bn2bin(a):
return long_to_bytes(a, 'big')

def sub_2E1130(BN1):
BN2 = BN_mask_bits(BN1, 46)
KeyBuildTIme = BN_mask_bits(BN2 >> 15, 31)
Lic_Cam_Cnt = BN_mask_bits(BN2 >> 11, 4)
return KeyBuildTIme, Lic_Cam_Cnt, BN2, BN1 >> 46

def sub_2E46F0(BN2):
a = BN_bn2bin(BN2)
if len(a) < 6:
a = ("\x00" * (6 - len(a))) + a
return BN_mask_bits(int(sha1(a).digest()[-6:].encode('hex'), 16), 45)

LicNumber = 0
for licenseKeyStr in LicenseKey_String:
LicNumber *= 24
bRoundFound = False
for xStrIndex in range(0, len(xstr)):
if licenseKeyStr == xstr[xStrIndex]:
LicNumber += xStrIndex
bRoundFound = True
break
if not bRoundFound:
LicNumber -= 1

print("LicNumber", LicNumber)
KeyBuildTIme, Lic_Cam_Cnt, BN2, BN3 = sub_2E1130(LicNumber)
print("KeyBuildTIme", KeyBuildTIme, "Lic_Cam_Cnt", Lic_Cam_Cnt, "BN2", BN2, "BN3", BN3)
BN4 = sub_2E46F0(BN2)
print("BN4", BN4)
print("SHA1 Chk", BN3 == BN4)

upload successful

评论