def str2hex(s): """ 把一个字符串转成其ASCII码的16进制表示 :param s: 要转换的字符串 :return: ASCII码的16进制表示字符串 """ return force_text(binascii.b2a_hex(force_bytes(s)))
def hex2str(s): """ 把十六进制字符串转换成其ASCII表示字符串 :param s: 十六进制字符串 :return: 字符串 """ return force_text(binascii.a2b_hex(s))
def dec2str(n): """ decimal number to string. """ s = hex(int(n))[2:].rstrip('L') if len(s) % 2 != 0: s = '0' + s return force_text(hex2str(s))
def from_uu(data): """ 解uu编码 :param data: uu编码的字符串 :return: 字符串 """ r = binascii.a2b_uu(data) return force_text(r)
def to_uu(data): """ uu编码 :param data: 字符串 :return: 编码后的字符串 """ r = binascii.b2a_uu(force_bytes(data)) return force_text(r)
def load_dict(self, file_name): dict_list = [] with open(file_name, 'rb') as f: for line in f: line = force_text(line).strip() if line != '' and not line.startswith('#'): ext, des, hex_start, hex_end = line.split('::') hex_start = hex_start.lower().replace(' ', '') hex_end = hex_end.lower().replace(' ', '') ext = ext.strip().lower() if ext.lower() in self.exclude: continue item = [ext, des, hex_start, hex_end] item = tuple([force_text(t.strip()) for t in item]) dict_list.append(item) return dict_list
def byte2hex(s): """ 字节类型的数据转成16进制字符串 :param s: :return: """ result = binascii.b2a_hex(s) return force_text(result)
def load_file(self): file_name = self.file_name size = os.path.getsize(file_name) print(''' [+] File: %s [+] Size: %s [Kb] ''' % (file_name, str(size / 1024))) with open(file_name, 'rb') as f: data = f.read() hex_data = force_text(binascii.hexlify(data)) self.hex_data = hex_data return hex_data
def to_base91(data): return force_text(b91encode(force_bytes(data)))
def from_base92(data): return force_text(b92decode(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 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
def regex_match(cls, regex, encode_str): try: return regex.match(force_text(encode_str)) except: print(encode_str) return False
def get_flag_from_file(file_path, strict_mode=False, result_dict=None): if not os.path.exists(file_path): if result_dict is not None: result = '\n'.join(result_dict.keys()) else: result = '' return result with open(file_path, 'rb') as f: data = f.read() data = force_text(data) if isinstance(data, bytes): data = bytes_2_printable_strings(data) data = data.replace('\n', '') data = data.replace('\r', '') data = data.replace('\t', '') data = data.replace(' ', '') # 这里用 ?: 表示不对该分组编号,也不匹配捕获的文本 # 这样使用 findall 得到的结果就不会只有()里面的东西 # [\x20-\x7E] 是可见字符 re_list = [ # (r'(?:key|flag|ctf)\{[^\{\}]{3,35}\}', re.I), # (r'(?:key|KEY|flag|FLAG|ctf|CTF)+[\x20-\x7E]{3,50}', re.I), (r'(?:key|flag|ctf|synt|galf)[\x20-\x7E]{5,41}', re.I), # (r'(?:key|flag|ctf|synt|galf)[\x20-\x7E]{0,3}(?::|=|\{|is)[\x20-\x7E]{,40}', re.I), (r'k.{0,2}e.{0,2}y[\x20-\x7E]{0,2}(?::|=|\{|is)[\x20-\x7E]{3,40}', re.I), (r'f.{0,2}l.{0,2}a.{0,2}g[\x20-\x7E]{0,2}(?::|=|\{|is)[\x20-\x7E]{3,40}', re.I), (r'c.{0,2}t.{0,2}f.{0,2}[\x20-\x7E]{0,2}(?::|=|\{|is)[\x20-\x7E]{3,40}', re.I), (r's.{0,2}y.{0,2}n.{0,2}t[\x20-\x7E]{0,2}(?::|=|\{|is)[\x20-\x7E]{3,40}', re.I), (r'g.{0,2}a.{0,2}l.{0,2}f[\x20-\x7E]{0,2}(?::|=|\{|is)[\x20-\x7E]{3,40}', re.I), ] if not strict_mode: re_list.extend([ (r'[a-z0-9]{0,8}[\x20-\x7E]{0,3}\{[\x20-\x7E]{4,40}\}', re.I), (r'[\x20-\x7E]{0,8}[a-zA-Z0-9_]{16}[\x20-\x7E]{0,5}', re.I), (r'[\x20-\x7E]{0,8}[a-zA-Z0-9_]{32}[\x20-\x7E]{0,5}', re.I), ]) if result_dict is None: result_dict = {} for r, option in re_list: # re.I表示大小写无关 if option is not None: pattern = re.compile(r, option) else: pattern = re.compile(r) ret = pattern.findall(data) if len(ret): try: result = [] for t in ret: x = [x for x in t if t in string.printable] x = ''.join(x) result.append(x) result = [t.replace('\n', '').replace('\r', '').strip() for t in ret] for t in result: if t not in result_dict: result_dict[t] = None except Exception as e: print(e) print(traceback.format_exc()) result = '\n'.join(result_dict.keys()) return result