def str2hex(s): """ 把一个字符串转成其ASCII码的16进制表示 :param s: 要转换的字符串 :return: ASCII码的16进制表示字符串 """ return force_text(binascii.b2a_hex(force_bytes(s)))
def to_base64(data): """ 把字符串转换成BASE64编码 :param data: 字符串 :return: BASE64字符串 """ return base64.b64encode(force_bytes(data))
def decode(data, length=None, print_output=True): new_data = [] for t in data: i = cipher_letters.index(t) new_data.append(i) data_list = [] while len(new_data) > 0: t = new_data[:4] if len(t) < 4: t.extend([0 for i in range(4 - len(t))]) new_data = new_data[4:] data_list.append(t) new_data_list = [] for group in data_list: tmp_group = ['%06d' % int(bin(t)[2:]) for t in group] tmp_group = ''.join(tmp_group) new_data_list.append(tmp_group) result_bin_data = ''.join(new_data_list) decode_str = hex(int(result_bin_data, 2))[2:].rstrip('L') # print(decode_str) if length is not None: # print(len(decode_str)) decode_str = decode_str[:length * 2] decode_str = force_bytes(decode_str).decode('hex') if print_output: print(decode_str) return decode_str
def to_base16(data): """ 把字符串转换成BASE16编码 :param data: 字符串 :return: BASE16字符串 """ return base64.b16encode(force_bytes(data))
def to_base32(data): """ 把字符串转换成BASE32编码,5个ASCII字符一组,生成8个Base字符 :param data: 字符串 :return: BASE32字符串 """ return base64.b32encode(force_bytes(data))
def to_uu(data): """ uu编码 :param data: 字符串 :return: 编码后的字符串 """ r = binascii.b2a_uu(force_bytes(data)) return force_text(r)
def partial_decode(decode_method, data, base_padding_length=4): """ 对前面可以解码的数据一直解到无法解码 :param base_padding_length: :param decode_method: :param data: :return: """ data = force_bytes(data) result = [] while len(data) > 0: tmp = base_padding(data[:base_padding_length], base_padding_length) data = data[base_padding_length:] try: r = decode_method(tmp) result.append(r) except: break return b''.join(result)
def bytes_2_printable_strings(data): data = force_bytes(data) result = ['', ''] for c in data: if PY2: c = ord(c) if 32 <= c <= 126 or c in (9, 10, 13): if c == 9: c = 32 elif c == 13: c = 10 # 去掉连续的空格 if c == 32 and result[-1] == ' ': continue # 去掉连续的换行 elif c == 10 and result[-1] == '\n': continue result.append(chr(c)) return ''.join(result)
def to_base91(data): return force_text(b91encode(force_bytes(data)))
def to_base85(data): return force_text(base64.b85encode(force_bytes(data)))
def from_base85(data): return force_text(base64.b85decode(force_bytes(data)))
def url_safe_b64decode(data): return force_text(urlsafe_b64decode(force_bytes(data)))
def b642hex(s): s = base_padding(s, 4) s = b64decode(force_bytes(s)) return str2hex(s)
def base_padding(data, length=4): data = force_bytes(data) if len(data) % length != 0: data = data + b'=' * (length - len(data) % length) return data
def to_base58(data): return b58encode(force_bytes(data))
def from_base58(data): return b58decode(force_bytes(data))
def parse(self): encode_str = self.data_str encode_str = encode_str.strip() should_try_list = [] # 先进行第一层解密 for m in encode_methods: success, decode_str = self.parse_str(encode_str, m, []) if success: should_try_list.append({'data': decode_str, 'm_list': [m]}) result_method_dict = {} while len(should_try_list) > 0: new_should_try_list = [] for item in should_try_list: m_list = item['m_list'] data = item['data'] has_print = False for i, m in enumerate(encode_methods): tmp_m_list = deepcopy(m_list) self.last_result_printable = True success, decode_str = self.parse_str(data, m, tmp_m_list) if success: tmp_m_list.append(m) if tmp_m_list not in new_should_try_list: new_should_try_list.append({ 'data': decode_str, 'm_list': tmp_m_list }) else: if len(tmp_m_list) > 0 and not has_print: has_print = True md5 = hashlib.md5(force_bytes(decode_str)).hexdigest() if md5 in result_method_dict: item = result_method_dict[md5] # 为了避免数据很繁杂,只保留最短路径 if len(item['m_list']) > len(tmp_m_list): item['m_list'] = tmp_m_list item['methods'] = '->'.join(tmp_m_list) else: if self.calc_printable_percent(decode_str) >= self.printable_percent: result_method_dict[md5] = { 'data': '%s' % decode_str, 'm_list': tmp_m_list, 'methods': '->'.join(tmp_m_list) } should_try_list = new_should_try_list def cmp_method_list(x, y): # 按照解码后的数据长度排序,最小的排在前面 len_x = len(x['data']) len_y = len(y['data']) if len_x == len_y: for index, t in enumerate(x['m_list']): if x['m_list'][index] > y['m_list'][index]: return 1 elif x['m_list'][index] == y['m_list'][index]: pass else: return -1 return 0 elif len_x > len_y: return -1 else: return 1 # 按使用方法列表的长度排序,最大的排在前面 # len_x = len(x['m_list']) # len_y = len(y['m_list']) # if len_x == len_y: # for index, t in enumerate(x['m_list']): # if x['m_list'][index] > y['m_list'][index]: # return 1 # elif x['m_list'][index] == y['m_list'][index]: # pass # else: # return -1 # return 0 # elif len_x > len_y: # return 1 # else: # return -1 result_method_list = sorted(result_method_dict.values(), key=cmp_to_key(lambda x, y: cmp_method_list(x, y)), reverse=True) return result_method_list
def parse_str(self, encode_str, decode_method, m_list): if len(m_list) > self.max_depth: return False, encode_str # encode_str = deepcopy(encode_str) encode_str = force_bytes(encode_str) if decode_method in ['zlib']: encode_str = force_bytes(encode_str) else: encode_str = force_text(encode_str) raw_encode_str = deepcopy(encode_str) if len(encode_str) <= 0: return False, raw_encode_str try: if decode_method == 'base16': # 避免无限递归 # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.upper() rex = re.compile('^[0-9A-F]+[=]*$', re.MULTILINE) if self.regex_match(rex, encode_str): decode_str = partial_base16_decode(encode_str) else: return False, raw_encode_str elif decode_method == 'base32': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') # 避免无限递归 # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.upper() rex = re.compile('^[A-Z2-7=]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = base64.b32decode(base_padding(encode_str, 8)) else: return False, raw_encode_str elif decode_method == 'base64': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') # 避免无限递归 # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9+/=]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = base64.b64decode(base_padding(encode_str, 4)) else: return False, raw_encode_str elif decode_method == 'urlsafe_b64': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') # base_list = ('base16', 'base32', 'base64', 'urlsafe_b64') # base_list = () if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9-_=]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = urlsafe_b64decode(base_padding(encode_str, 4)) else: return False, raw_encode_str elif decode_method == 'base58': encode_str = encode_str.strip().replace(' ', '').replace('\n', '') if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$', re.MULTILINE) # 自动纠正填充 if self.regex_match(rex, encode_str): decode_str = from_base58(encode_str) else: return False, raw_encode_str elif decode_method == 'ascii_85': if len(encode_str) < 7: return False, raw_encode_str if PY2: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9!#$%&()*+\-;<=>?@^_`{|}~]+$', re.MULTILINE) if self.regex_match(rex, encode_str): decode_str = a85decode(force_bytes(encode_str)) else: return False, encode_str elif decode_method == 'base85': if len(encode_str) < 7: return False, raw_encode_str if PY2: return False, raw_encode_str rex = re.compile('^[A-Za-z0-9!#$%&()*+\-;<=>?@^_`{|}~]+$', re.MULTILINE) if self.regex_match(rex, encode_str): decode_str = b85decode(force_bytes(encode_str)) else: return False, encode_str elif decode_method == 'rot13': # 如果这里不做限制,会无限递归下去 if 'rot13' in m_list: return False, raw_encode_str decode_str = decode_rot13(encode_str) elif decode_method == 'pawn_shop': try: encode_str = encode_str.decode('gb2312') except: pass encode_str = force_text(encode_str) encode_str = encode_str.replace(' ', '').strip() code_base = '口由中人工大王夫井羊' decode_str = [] for t in encode_str: if t in code_base: i = code_base.index(t) decode_str.append(str(i)) else: return False, raw_encode_str decode_str = ''.join(decode_str) if len(decode_str) < 0: return False, raw_encode_str elif decode_method == 'decimal': if len(encode_str) < 4: return False, raw_encode_str rex = re.compile('^[0-9]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str # 解码后是 0xab1234,需要去掉前面的 0x decode_str = hex(int(encode_str))[2:].rstrip('L') elif decode_method == 'binary': rex = re.compile('^[0-1]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str # 不足8个的,在后面填充0 padding_length = (8 - len(encode_str) % 8) % 8 encode_str = '%s%s' % (encode_str, '0' * padding_length) # 解码后是 0xab1234,需要去掉前面的 0x decode_str = hex(int(encode_str, 2))[2:].rstrip('L') elif decode_method in ['octal', 'octal_ascii', 'octal_binary']: # 8进制转成16进制的数据 rex = re.compile('^[0-7]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str rex = re.compile('^[0-1]+$', re.MULTILINE) if self.regex_match(rex, encode_str): return False, raw_encode_str if len(encode_str) < 4: return False, raw_encode_str if decode_method == 'octal': # 解码后是 0xab1234,需要去掉前面的 0x decode_str = hex(int(encode_str, 8))[2:].rstrip('L') elif decode_method == 'octal_ascii': encode_str = encode_str.replace(' ', '').strip() # 8 进制的 177 转成十进制后是 128 tmp_list = list(encode_str) ascii_list = [] while len(tmp_list) > 0: tmp_str = ''.join(tmp_list[:3]) if int(tmp_str, 8) > 127: tmp_str = ''.join(tmp_list[:2]) tmp_list = tmp_list[2:] else: tmp_list = tmp_list[3:] ascii_list.append(chr(int(tmp_str, 8))) decode_str = ''.join(ascii_list) elif decode_method == 'octal_binary': # 因为这里有补0的操作,要避免无限递归 if len(m_list) > 0 and \ (m_list[-1] in ('octal_binary', 'octal', 'binary') or len(encode_str) < 8): return False, raw_encode_str # 将8进制直接转成16进制,也就是3个8进制数字转成2个16进制字符 # 先将每个8进制数字转成二进制,不足3个的前面补0 encode_str = encode_str.replace(' ', '').strip() tmp_bin_list = ['%03d' % int(bin(int(t))[2:]) for t in list(encode_str)] tmp_bin_list = [t for t in tmp_bin_list] # logger.info(tmp_bin_list) decode_str = ''.join(tmp_bin_list) else: return False, raw_encode_str elif decode_method == 'decimal_ascii': if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.replace(' ', '').strip() rex = re.compile('^[0-9]+$', re.MULTILINE) if not self.regex_match(rex, encode_str): return False, raw_encode_str # ascii 字符串,10进制最大127 tmp_list = list(encode_str) ascii_list = [] while len(tmp_list) > 0: tmp_str = ''.join(tmp_list[:3]) if int(tmp_str) > 127: tmp_str = ''.join(tmp_list[:2]) tmp_list = tmp_list[2:] else: tmp_list = tmp_list[3:] ascii_list.append(chr(int(tmp_str))) decode_str = ''.join(ascii_list) elif decode_method in ['swap_case', 'reverse_alphabet', 'reverse']: # 如果这里不做限制,会无限递归下去 if len(m_list) > 0: for t in ['swap_case', 'reverse_alphabet', 'reverse']: if t in m_list: return False, raw_encode_str # 一定要包含 ascii 字符 tmp_data = [t for t in encode_str if t in string.ascii_letters] if len(tmp_data) <= 0: return False, raw_encode_str # rex = re.compile('^[A-Za-z0-9+/=]$', re.MULTILINE) # if not self.regex_match(rex, encode_str): # return False, raw_encode_str if decode_method == 'swap_case': new_data = [] for t in encode_str: if t in string.ascii_lowercase: t = t.upper() elif t in string.ascii_uppercase: t = t.lower() new_data.append(t) decode_str = ''.join(new_data) elif decode_method == 'reverse_alphabet': # 字母逆序,a->z, z->a new_data = [] for t in encode_str: if t in string.ascii_letters: if t in string.ascii_lowercase: t = ord(t) + (25 - (ord(t) - ord('a')) * 2) t = chr(t) else: t = ord(t) + (25 - (ord(t) - ord('A')) * 2) t = chr(t) new_data.append(t) decode_str = ''.join(new_data) elif decode_method == 'reverse': # 逆序 decode_str = encode_str[::-1] else: return False, raw_encode_str elif decode_method == 'urlencode': if len(encode_str) < 4: return False, raw_encode_str decode_str = unquote_plus(encode_str) elif decode_method == 'hex': if len(encode_str) < 4: return False, raw_encode_str encode_str = encode_str.lower() rex = re.compile('^[a-f0-9]+$', re.MULTILINE) if self.regex_match(rex, encode_str.lower()): # 修正基数位数的16进制数据 if len(encode_str) % 2 != 0: encode_str += '0' decode_str = force_text(hex2str(encode_str)) else: return False, raw_encode_str elif decode_method == 'zlib': if len(encode_str) < 4: return False, raw_encode_str try: decode_str = zlib.decompress(force_bytes(encode_str)) if self.calc_printable_percent(decode_str) < self.printable_percent: return False, raw_encode_str except: return False, raw_encode_str else: decode_str = encode_str.decode(decode_method) if len(decode_str) <= 0: return False, raw_encode_str elif force_bytes(encode_str) == force_bytes(decode_str): return False, raw_encode_str else: # 解码的内容只有可打印字符,才认为合法 if self.only_printable: printable_percent = 1.0 else: printable_percent = self.printable_percent is_printable = True # 如果可打印字符低于一定的百分比,就认为解码失败 if self.calc_printable_percent(decode_str) < printable_percent: is_printable = False if is_printable is False: if self.last_result_printable is False: return False, raw_encode_str self.last_result_printable = is_printable return True, decode_str except Exception as e: if self.verbose: logger.exception(e) return False, raw_encode_str