MD5截断比较
md5 截断验证
ctf中经常用MD5的截断比较做验证,如:substr(md5($str), 0, 6) === "3322cf"
,通过这种方式限制脚本的自动化攻击。通常可以写脚本去爆破MD5, 但是花费时间和比较字符串的长度有关,并且花费时间通常比较长,这不利于脚本自动攻击,下面给出爆破脚本和使用方式。
- submd5.py
1 # -*- coding: utf-8 -*- 2 3 import multiprocessing 4 import hashlib 5 import random 6 import string 7 import sys 8 9 CHARS = string.letters + string.digits 10 11 def cmp_md5(substr, stop_event, str_len, start=0, size=20): 12 global CHARS 13 14 while not stop_event.is_set(): 15 rnds = ''.join(random.choice(CHARS) for _ in range(size)) 16 md5 = hashlib.md5(rnds) 17 18 if md5.hexdigest()[start: start+str_len] == substr: 19 print rnds 20 stop_event.set() 21 22 23 if __name__ == '__main__': 24 substr = sys.argv[1].strip() 25 26 start_pos = int(sys.argv[2]) if len(sys.argv) > 1 else 0 27 28 str_len = len(substr) 29 cpus = multiprocessing.cpu_count() 30 stop_event = multiprocessing.Event() 31 processes = [multiprocessing.Process(target=cmp_md5, args=(substr, 32 stop_event, str_len, start_pos)) 33 for i in range(cpus)] 34 35 for p in processes: 36 p.start() 37 38 for p in processes: 39 p.join()
用法:
1 $ python submd5.py "3d4f4" 2 SponhjOhIZ30IaM1fweb 3 4 $ python submd5.py "3df4" 2 5 G8tr6VhonA1z3xJdaGBu
生成md5文件,并排序:想要在较短时间内获得可用的md5,可以使用彩虹表类似的方式去实现,通过空间去换时间。
- gen_md5.py
1 # -*- coding: utf-8 -*- 2 3 import itertools 4 import hashlib 5 import string 6 7 8 CHARS = string.letters + string.digits 9 str_len = 8 10 11 for s in itertools.product(CHARS, repeat=str_len): 12 s = ''.join(s) 13 print "{0} {1}".format(hashlib.md5(s).hexdigest(), s)
md5 文件搜索(二分查找):命令行排序: python gen_md5.py | sort -o md5_sorted.txt
- match.py
1 # -*- coding: utf-8 -*- 2 3 import itertools 4 import hashlib 5 import string 6 import os 7 8 9 def match(s): 10 md5_file = "md5_sorted.txt" 11 byte_size = os.path.getsize(md5_file) 12 with open(md5_file, 'rb') as f: 13 line_len = len(f.readline()) 14 15 print line_len 16 with open(md5_file, "rb") as f: 17 L = 0 18 R = byte_size / line_len - 1 19 20 while R - L > 0: 21 C = L + (R - L) / 2 22 offset = C * line_len 23 f.seek(offset) 24 ln = f.read(line_len).strip() 25 #print ln 26 27 head = ln[:len(s)] 28 if s == head: 29 return ln.split(" ")[1] 30 31 if s < head: 32 R = C 33 continue 34 35 L = C 36 37 return 38 39 # print match('fef')
不忘初心,方得始终。