MD5切り捨ての比較

ctfでは、検証にMD5切り捨て比較を使用することがよくあります。たとえば、substr(md5($ str)、0、6)=== "edef"は、この方法でスクリプト自動化攻撃を制限します。この場合、通常は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()

使い方:

検証:

同時に、レインボーテーブルと同様の方法を使用して、空間全体の時間を変更できます。

まず、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

次に、バイナリ検索を使用します。

  • 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

参照リンク:http//www.beesfun.com/2017/03/21/%E3%80%90CTF%E3%80%91MD5%E6%88%AA%E6%96%AD%E6%AF%94% E8%BE%83 /

おすすめ

転載: blog.csdn.net/Fly_hps/article/details/106941662
おすすめ