|
|
@ -47,9 +47,19 @@ def create_auth_chain_b(method): |
|
|
|
return auth_chain_b(method) |
|
|
|
|
|
|
|
|
|
|
|
def create_auth_chain_c(method): |
|
|
|
return auth_chain_c(method) |
|
|
|
|
|
|
|
|
|
|
|
def create_auth_chain_d(method): |
|
|
|
return auth_chain_d(method) |
|
|
|
|
|
|
|
|
|
|
|
obfs_map = { |
|
|
|
'auth_chain_a': (create_auth_chain_a,), |
|
|
|
'auth_chain_b': (create_auth_chain_b,), |
|
|
|
'auth_chain_c': (create_auth_chain_c,), |
|
|
|
'auth_chain_d': (create_auth_chain_d,), |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -724,3 +734,105 @@ class auth_chain_b(auth_chain_a): |
|
|
|
if buf_size > 400: |
|
|
|
return random.next() % 521 |
|
|
|
return random.next() % 1021 |
|
|
|
|
|
|
|
|
|
|
|
class auth_chain_c(auth_chain_b): |
|
|
|
def __init__(self, method): |
|
|
|
super(auth_chain_c, self).__init__(method) |
|
|
|
self.salt = b"auth_chain_c" |
|
|
|
self.no_compatible_method = 'auth_chain_c' |
|
|
|
self.data_size_list0 = [] |
|
|
|
|
|
|
|
def init_data_size(self, key): |
|
|
|
if self.data_size_list0: |
|
|
|
self.data_size_list0 = [] |
|
|
|
random = xorshift128plus() |
|
|
|
random.init_from_bin(key) |
|
|
|
# 补全数组长为12~24-1 |
|
|
|
list_len = random.next() % (8 + 16) + (4 + 8) |
|
|
|
for i in range(0, list_len): |
|
|
|
self.data_size_list0.append((int)(random.next() % 2340 % 2040 % 1440)) |
|
|
|
self.data_size_list0.sort() |
|
|
|
|
|
|
|
def set_server_info(self, server_info): |
|
|
|
self.server_info = server_info |
|
|
|
try: |
|
|
|
max_client = int(server_info.protocol_param.split('#')[0]) |
|
|
|
except: |
|
|
|
max_client = 64 |
|
|
|
self.server_info.data.set_max_client(max_client) |
|
|
|
self.init_data_size(self.server_info.key) |
|
|
|
|
|
|
|
def rnd_data_len(self, buf_size, last_hash, random): |
|
|
|
other_data_size = buf_size + self.server_info.overhead |
|
|
|
# final_pos 总是分布在pos~(data_size_list0.len-1)之间 |
|
|
|
# 除非data_size_list0中的任何值均过小使其全部都无法容纳buf |
|
|
|
if other_data_size >= self.data_size_list0[-1]: |
|
|
|
if other_data_size >= 1440: |
|
|
|
return 0 |
|
|
|
if other_data_size > 1300: |
|
|
|
return random.next() % 31 |
|
|
|
if other_data_size > 900: |
|
|
|
return random.next() % 127 |
|
|
|
if other_data_size > 400: |
|
|
|
return random.next() % 521 |
|
|
|
return random.next() % 1021 |
|
|
|
|
|
|
|
random.init_from_bin_len(last_hash, buf_size) |
|
|
|
pos = bisect.bisect_left(self.data_size_list0, other_data_size) |
|
|
|
# random select a size in the leftover data_size_list0 |
|
|
|
final_pos = pos + random.next() % (len(self.data_size_list0) - pos) |
|
|
|
return self.data_size_list0[final_pos] - other_data_size |
|
|
|
|
|
|
|
|
|
|
|
class auth_chain_d(auth_chain_b): |
|
|
|
def __init__(self, method): |
|
|
|
super(auth_chain_d, self).__init__(method) |
|
|
|
self.salt = b"auth_chain_d" |
|
|
|
self.no_compatible_method = 'auth_chain_d' |
|
|
|
self.data_size_list0 = [] |
|
|
|
|
|
|
|
def check_and_patch_data_size(self, random): |
|
|
|
# append new item |
|
|
|
# when the biggest item(first time) or the last item(other time) are not big enough. |
|
|
|
# but set a limit size (64) to avoid stack over follow. |
|
|
|
if self.data_size_list0[-1] < 1000 and len(self.data_size_list0) < 64: |
|
|
|
self.data_size_list0.append((int)(random.next() % 2340 % 2040 % 1440)) |
|
|
|
self.check_and_patch_data_size(random) |
|
|
|
|
|
|
|
def init_data_size(self, key): |
|
|
|
if self.data_size_list0: |
|
|
|
self.data_size_list0 = [] |
|
|
|
random = xorshift128plus() |
|
|
|
random.init_from_bin(key) |
|
|
|
# 补全数组长为12~24-1 |
|
|
|
list_len = random.next() % (8 + 16) + (4 + 8) |
|
|
|
for i in range(0, list_len): |
|
|
|
self.data_size_list0.append((int)(random.next() % 2340 % 2040 % 1440)) |
|
|
|
self.data_size_list0.sort() |
|
|
|
old_len = len(self.data_size_list0) |
|
|
|
self.check_and_patch_data_size(random) |
|
|
|
# if check_and_patch_data_size are work, re-sort again. |
|
|
|
if old_len != len(self.data_size_list0): |
|
|
|
self.data_size_list0.sort() |
|
|
|
|
|
|
|
def set_server_info(self, server_info): |
|
|
|
self.server_info = server_info |
|
|
|
try: |
|
|
|
max_client = int(server_info.protocol_param.split('#')[0]) |
|
|
|
except: |
|
|
|
max_client = 64 |
|
|
|
self.server_info.data.set_max_client(max_client) |
|
|
|
self.init_data_size(self.server_info.key) |
|
|
|
|
|
|
|
def rnd_data_len(self, buf_size, last_hash, random): |
|
|
|
other_data_size = buf_size + self.server_info.overhead |
|
|
|
# if other_data_size > the bigest item in data_size_list0, not padding any data |
|
|
|
if other_data_size >= self.data_size_list0[-1]: |
|
|
|
return 0 |
|
|
|
|
|
|
|
random.init_from_bin_len(last_hash, buf_size) |
|
|
|
pos = bisect.bisect_left(self.data_size_list0, other_data_size) |
|
|
|
# random select a size in the leftover data_size_list0 |
|
|
|
final_pos = pos + random.next() % (len(self.data_size_list0) - pos) |
|
|
|
return self.data_size_list0[final_pos] - other_data_size |
|
|
|