1. 程式人生 > >CTF之MD5截斷比較

CTF之MD5截斷比較

md5 截斷驗證

ctf中經常用MD5的截斷比較做驗證,如:substr(md5($str), 0, 6) === “3322cf”,通過這種方式限制指令碼的自動化攻擊。

通常可以寫指令碼去爆破MD5, 但是花費時間和比較字串的長度有關,並且花費時間通常比較長,這不利於指令碼自動攻擊,下面給出爆破指令碼和使用方式。

submd5.py

# -*- coding: utf-8 -*-
import multiprocessing
import hashlib
import random
import string
import sys
CHARS = string.letters + string.digits
def
cmp_md5(substr, stop_event, str_len, start=0, size=20):
global CHARS while not stop_event.is_set(): rnds = ''.join(random.choice(CHARS) for _ in range(size)) md5 = hashlib.md5(rnds) if md5.hexdigest()[start: start+str_len] == substr: print rnds stop_event.set() if
__name__ == '__main__': substr = sys.argv[1].strip() start_pos = int(sys.argv[2]) if len(sys.argv) > 1 else 0 str_len = len(substr) cpus = multiprocessing.cpu_count() stop_event = multiprocessing.Event() processes = [multiprocessing.Process(target=cmp_md5, args=(substr, stop_event, str_len, start_pos)) for
i in range(cpus)] for p in processes: p.start() for p in processes: p.join()

用法:

#python submd5.py substr startpos
$ python submd5.py "3d4f4"
SponhjOhIZ30IaM1fweb
$ python submd5.py "3df4" 2
G8tr6VhonA1z3xJdaGBu

想要在較短時間內獲得可用的md5,可以使用彩虹表類似的方式去實現,通過空間去換時間。

生成md5檔案,並排序:

gen_md5.py

# -*- coding: utf-8 -*-
import itertools
import hashlib
import string
CHARS = string.letters + string.digits
str_len = 8
for s in itertools.product(CHARS, repeat=str_len):
    s = ''.join(s)
    print "{0} {1}".format(hashlib.md5(s).hexdigest(), s)

命令列排序: python gen_md5.py | sort -o md5_sorted.txt

md5 檔案搜尋(二分查詢):

match.py

# -*- coding: utf-8 -*-
import itertools
import hashlib
import string
import os
def match(s):
    md5_file = "md5_sorted.txt"
    byte_size = os.path.getsize(md5_file)
    with open(md5_file, 'rb') as f:
        line_len = len(f.readline())
    print line_len
    with open(md5_file, "rb") as f:
      L = 0
      R = byte_size / line_len - 1
      while R - L > 0:
        C = L + (R - L) / 2
        offset = C * line_len
        f.seek(offset)
        ln = f.read(line_len).strip()
        #print ln
        head = ln[:len(s)]
        if s == head:
          return ln.split(" ")[1]
        if s < head:
          R = C
          continue
        L = C
      return
# print match('fef')