2021WMCTF的Re1题wp

感觉比赛难度太高了,这题做了1天多才做出来,不过不得不感慨年纪大了,智商也下降的厉害。
附件解压是个exe程序,放到IDA里分析咋一看也没啥特别的:
在这里插入图片描述
前面是常规的flag头部和{}的格式判断,然后是字符串处理,后面再看。
在这里插入图片描述
刚开始是用输入的4个字符生成字符串,然后对4个字符串进行类似CRC32的校验码
在这里插入图片描述
这里我分别对4个校验值命名为a,b,c,d,然后发现有个4个等式需要为真,也就是说可以通过方程求出a,b,c,d

from z3 import *

s=Solver()
a=BitVec('a',32)
b=BitVec('b',32)
c=BitVec('c',32)
d=BitVec('d',32)

s.add((b + a)&0xffffffff == 296450682)
s.add((b - c)&0xffffffff == 483717666)
s.add((d + c)&0xffffffff == 0xC940F021)
s.add((c + a - d)&0xffffffff == 2088593617)
if s.check() == sat:
    print(s.model())

然后计算出
c = 1357369498
a = 2750330814
d = 2019106695
b = 1841087164
再看下后面的一个函数:sub_7FF7319F3840

在这里插入图片描述
这里明显是个XTEA算法,修改了delta而已
还需要注意的是,主函数的419-422行使用之前赋值的0xdead对c和d进行了修改,导致key发生变化,然后利用最终的结果我们解密,发现解密后居然是乱码!
然后经过一段时间验证,回顾了下,判断操作应该是没有问题,那就应该是key还是不对,因此对可能修改的地方进行了爆破,发现0xdead应该是0xb7ad,解密后的文本是:

_D0_yOu_L1kE_It!

嗯,感觉看起来接近了,但其实还早~(我得反思下,后面的十几个小时是咋耗费掉的)
这样我们就有了flag{}中的16个字符了,再看下前面4个,用来生成字符串做CRC的。
采用如下的脚本爆破下,就可以得到能够生成a,b,c,d分别的字符

for i in range(0x20,0x7f):
    buf=[]
    for j in range(256):
        buf.append((i+j)&0xff)
    if crc(0x0FFFFFFFE,buf,256)==a:
        print(chr(i))
        break
else:
    print('failed')

这样得到最前面的4个字符,和之前解密的字符串拼起来就是:

Hah4_D0_yOu_L1kE_It!

然后再看最关键的修改密钥部分,看0xb7ad的位置在Block偏移0x222的位置,就需要把0x223的0xde改成0xb7才可以成功。
但是如何能修改这部分Block校验块的内存数据呢,答案就在前面代码的第二步循环处理,这里程序会持续读入一个字符和4个HEX数字,然后调用对应的函数进行修改内存的操作。
这里我把整个这段解析处理的逻辑画成表格展示出来:
在这里插入图片描述
需要注意的是,同一组的操作只能做一次,而且flag长度限制总共只能做3次。
可以看到,如果需要修改0x223的字节,看起来有3个方案:
1、前导字符“+”,但是需要修改0x204,但由于flag长度限制,只能修改3次内存,所以还需要改回原值,再加上同组操作只能做一次,不可能。
2、前导字符”$“,但需要修改0x21b,原理同上,也不可能
3、前导字符“-”,但是修改的范围只能是16个字节以内,也就是从0x210-0x21f,也没用
到这里就陷入困境了,其实上面的每一步都花了很久,反复思考有没有漏过什么细节,后来灵机一动,发现第三个方案里0x210也可以被修改,如果改成0x20,就可以修改0x210-0x22f的内容
然后再看,如何修改0x210的值:
搜索满足条件的操作,只有“+”,“#”两个方案,但“+”由于和“-”同组,所以只能是“#”。
这里如果需要用“#”操作,还需要满足一个前提:*0x100==0xfe
这里看似没有解决办法,因为所有的操作都覆盖不到这个范围,但是通过仔细检查汇编代码,发现“@”操作这里a2实际是可以为负值的,比如输入0xff就表示-1
这样得到flag:

WMCTF{Hah4_D0_yOu_L1kE_It!@FFFE#0F20-11B7}

那么这样的flag是不是唯一的呢,因为flag长度限制是45个字符,而上面的长度才42。
如果你在后面}前加上任意字符,程序就会有一个特殊处理,根据你的输入修改了内存里的数据,导致前面CRC的结果出错。
其实我在找到正确的flag前,还找到了一个非预期的解法,也发现这题是多解的。这个非预期的解法是由于0x21b这里可以被输入控制,比如正确flag里的这个L1kE中的1这个字节直接改成0xce,这样就可以直接进行“$”操作,然后用“-”操作改回0x31即可,这样仅用两个操作就修改了key,后面还有很多字符可以随意组合,造成多解,验证看下图。
在这里插入图片描述
总结一下,对我来说题目难度很高,感觉年纪大了,只能靠多刷题来提升技能。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值