双重md5加密弱等于
当前做过几道php反序列化题目中含有md5双重加密的判断
发现有两个小知识点
科学计数法弱等于
比如说这道极客大挑战2025的题目,要求两个值弱等于且不强等于。
由于弱等于可以把字符串转化为数字比较,而强等于限制了二者不能完全相同
所有用到科学计数法,当双重md5后字符串为0e开头后面全是数字,则可以通过弱比较,二者都等于0,且强比较不同,符合题意。这里给出一个python脚本,可以拿来爆破
import hashlib
import string
import multiprocessing
def double_md5(s):
first_md5 = hashlib.md5(s.encode()).hexdigest()
second_md5 = hashlib.md5(first_md5.encode()).hexdigest()
return second_md5
def is_magic_hash(md5_hash):
return md5_hash.startswith('0e') and md5_hash[2:].isdigit()
def worker_task(args):
charset, length, start_idx, batch_size, max_results_left = args
results = []
count = 0
for i in range(start_idx, start_idx + batch_size):
if i >= len(charset) ** length or count >= max_results_left:
break
candidate_str = ''
temp = i
for j in range(length):
candidate_str += charset[temp % len(charset)]
temp //= len(charset)
hash_result = double_md5(candidate_str)
if is_magic_hash(hash_result):
results.append((candidate_str, hash_result))
count += 1
return results
def parallel_brute_force(max_results, charset, desc=""):
max_length = 6
batch_size = 100000
found = []
print(f"\n开始并行暴力破解“{desc}”集,目标找到 {max_results} 个...")
for length in range(4, max_length + 1):
print(f"\n搜索长度 {length} 的字符串...")
total_combinations = len(charset) ** length
with multiprocessing.Pool(processes=multiprocessing.cpu_count()) as pool:
tasks = []
for start_idx in range(0, total_combinations, batch_size):
left_to_find = max_results - len(found)
if left_to_find <= 0:
break
tasks.append((charset, length, start_idx, batch_size, left_to_find))
for i, result_batch in enumerate(pool.imap_unordered(worker_task, tasks)):
if result_batch:
for string_val, hash_val in result_batch:
print(f"找到匹配! 字符串: {string_val}, 哈希: {hash_val}")
found.append((string_val, hash_val))
if len(found) >= max_results:
print("已达到目标数量,提前结束")
pool.terminate()
break
if len(found) >= max_results:
break
if i % 10 == 0:
progress = min((i + 1) * batch_size, total_combinations)
print(f"进度: {progress}/{total_combinations} ({progress/total_combinations*100:.1f}%)")
if len(found) >= max_results:
break
print(f"\n全部找到的魔术hash({desc})如下:")
for idx, (s, h) in enumerate(found, 1):
print(f"{idx:02d}. 字符串: {s}, 哈希: {h}")
return found
if __name__ == "__main__":
num = int(input("请输入要找到的魔术hash数量: "))
print("-" * 30)
# 先用纯字母集爆破
results_alpha = parallel_brute_force(num, string.ascii_letters, desc="字母")
print("-" * 30)
# 再用字母+数字集爆破(不会重复已找到的结果)
results_alphanum = parallel_brute_force(num, string.ascii_letters + string.digits, desc="字母+数字")
然后这里再给出几个爆破结果
全部找到的魔术hash(字母)如下:
01. 字符串: mBeSja, 哈希: 0e210860082616560753197903773939
02. 字符串: RleoIb, 哈希: 0e165155735388603862205760323672
03. 字符串: IKsHGc, 哈希: 0e022289409330782264224545582392
04. 字符串: LOhlKc, 哈希: 0e852429040529624829369802171953
05. 字符串: iQAwXc, 哈希: 0e999179829757837097870506517663
06. 字符串: KtnAJe, 哈希: 0e787639518490550583554438466566
07. 字符串: LejvIf, 哈希: 0e111484964175819120956442834140
08. 字符串: rjvJNf, 哈希: 0e736903779667020579552711625557
09. 字符串: RwOOei, 哈希: 0e800236998473922397186801398019
10. 字符串: KWMDli, 哈希: 0e081194590188158636719044384199
全部找到的魔术hash(字母+数字)如下:
01. 字符串: iv2Cn, 哈希: 0e759070535261955870964738616588
02. 字符串: O5KIA, 哈希: 0e844204234135990947908741466581
03. 字符串: f2WfQ, 哈希: 0e997766059721689977306698103413
04. 字符串: mBeSja, 哈希: 0e210860082616560753197903773939
05. 字符串: 3cXHka, 哈希: 0e958555339178072545376428935878
06. 字符串: D8Urza, 哈希: 0e238311354792814154407054340292
07. 字符串: WWbd4a, 哈希: 0e749455434249576441309004609713
08. 字符串: RleoIb, 哈希: 0e165155735388603862205760323672
09. 字符串: 4FiJIb, 哈希: 0e301452408972530419353168017689
10. 字符串: iS4XRb, 哈希: 0e161587431976517563275813980840
数字前缀弱等于
如果出现条件:if (md5(md5(“x”)) == 114)
如果我们的字符串x的双重md5加密值为114开头且后面一位是字母(除e加数字外),或者后面的两位是e+字母,则可以通过弱等于(PHP7)
这里给出一个python脚本用于爆破
import hashlib
def double_md5(s):
h1 = hashlib.md5(s.encode()).hexdigest()
h2 = hashlib.md5(h1.encode()).hexdigest()
return h2
def brute_force(prefix, max_count=1, start=0):
found = 0
i = start
prefix_len = len(prefix)
while found < max_count:
candidate = str(i)
result = double_md5(candidate)
if result.startswith(prefix):
# 第x+1位
if len(result) > prefix_len:
nxt1 = result[prefix_len]
# 满足:不是数字
if not nxt1.isdigit():
print(f"第{found+1}个: 明文={candidate}, 双md5={result}")
found += 1
# 如果第x+1位是e,则第x+2位不能是数字
elif nxt1.lower() == 'e' and len(result) > prefix_len + 1:
nxt2 = result[prefix_len + 1]
if not nxt2.isdigit():
print(f"第{found+1}个: 明文={candidate}, 双md5={result}")
found += 1
i += 1
if __name__ == "__main__":
prefix = input("请输入你想要的双md5前缀:") # 比如 '1145'
max_count = int(input("请输入最多爆破多少个:")) # 比如 2
brute_force(prefix=prefix, max_count=max_count)
因为“数字e数字”会被当成科学计数法解析,比如114e3会被解析为114000(114x10^3)
Comments