64位PE程序,ida打开得到分析得到

进入sha1_change函数,该函数对每个input的值进行了以下操作

进入v_k_init函数有

构建结构体得到五个初始魔改向量v,4个k值

进入encrypt函数得到

开始的数据填充区
R < 448,在最后一组的末尾填充1个“1”及若干个“0”,直到满足448b(b + paddingLength % 512 = 448);再在这448位的基础上填充64位,这64位是M的原始长度的二进制表示
R >= 448,在最后一组的末尾填充1个“1”及若干个“0”,使最后一组位数达到512;再新增一组,添加448个“0”和64位M的原始长度的二进制表示。
每个字符为1字节,0x38*8=448bit,input>0x38填充到512字节后添加448个“0”和64位M的原始长度进行两次sha1,else则直接添加原始长度进行一次she1
进入sha1函数

对应以下,k的值会随着轮数的不同而不同


进入encrypt的最后部分
最后的结果只取了魔改sha1结果移位后的前四字节

在后续代码中发现了SEH

汇编中可以看到

v7在程序一开头就赋值



当我们没调试后并且输入错误后error函数中会变成1/0出发异常到新的分支执行语句,该程序的流程为:判断是否为调试状态----->按照目前状态判断是否执行SEH反调试----->输入flag(长度为88)----->进入魔改sha1----->对比
我们可以借此修改代码使其输出i值,因为每输入正确一个数i的值会增加

将图中nop掉并将箭头处改为i的地址

记录下i的机器码44 24 20

在1e04处改

执行python语句爆破得到flag
import subprocess
flag = 'moectf{'
for i in range(7, 88):
for j in range(0x21,0x7f):
tmp = flag + chr(j) * (88 - i)
p = subprocess.Popen(["C:\\User\\Downloads\\Broken_hash.exe"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.stdin.write(tmp.encode())
p.stdin.close()
out = p.stdout.read()
p.stdout.close()
if out[-1] > i:
flag += chr(j)
print(flag)
break
flag += '}'
print(flag)
Comments NOTHING