首页
社区
课程
招聘
[2020][KCTF] 第十二题 白云苍狗 wp
2020-5-14 10:27 6445

[2020][KCTF] 第十二题 白云苍狗 wp

ccfer 活跃值
16
2020-5-14 10:27
6445
  • 女装游戏开始了
int sub_A7E490()
{
  int result; // eax
  signed int v1; // [esp+0h] [ebp-8h]
  signed int v2; // [esp+0h] [ebp-8h]
  signed int i; // [esp+4h] [ebp-4h]

  v1 = sub_401000();
  if ( v1 )
  {
    for ( i = 0; i < 3; ++i )
      sub_4013E0(v1);
    v2 = sub_401220();
    if ( v2 == 1 )
      sub_A808A2("You Win! You are very clever!");
    else
      sub_A808A2("Game Over");
    sub_A807EB(v2);
    result = 0;
  }
  else
  {
    sub_A808A2("Game Over");
    sub_A807EB(0);
    result = 0;
  }
  return result;
}

输入转成72位的全局变量A919DF处,经过sub_4013E0运算,输出也从这里返回
比较结果的地方在这里:

00401398   0FB691 DF19A900  MOVZX EDX,BYTE PTR DS:[ECX+A919DF]
0040139F   83E2 01          AND EDX,1
004013A2   8B45 A0          MOV EAX,DWORD PTR SS:[EBP-60]
004013A5   0FB64C05 B4      MOVZX ECX,BYTE PTR SS:[EBP+EAX-4C]
004013AA   3BD1             CMP EDX,ECX
004013AC   74 09            JE SHORT Totoro20.004013B7
先把KCTF对应的结果抓出来备用:
00 00 01 00 01 00 01 00 01 00 01 01 01 01 01 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

sub_4013E0里面非常长,清一色的与非门操作,一共是340181个与非门
这么大规模的与非门化简,是准备要玩点技术了,经过两天奋战,发现实力它不允许啊,得到的还是10几万行操作

 

二 换成没有技术的战术
输入输出在A919DF,与非门操作的数据从A918B8开始

先从sub_4013E0入口开始玩,把A919DF处72字节改成:
01 01 01 00 00 ...
在A919DF下个硬件内存写断点,运行第一次断下来:
005F8BE2   A2 DF19A900      MOV BYTE PTR DS:[A919DF],AL
005F8BE7   A0 DF19A900      MOV AL,BYTE PTR DS:[A919DF]
005F8BEC   8A25 DF19A900    MOV AH,BYTE PTR DS:[A919DF]
005F8BF2   22C4             AND AL,AH
005F8BF4   F6D0             NOT AL
005F8BF6   A2 DF19A900      MOV BYTE PTR DS:[A919DF],AL
005F8BFB   A0 E019A900      MOV AL,BYTE PTR DS:[A919E0]
观察A918B8:
01 00 00 00 01 01 00 00 ... ...

多试几个不同的情况,发现A918B8处刚好是输入的平方,sub_4013E0已经跑过了大概四分之一,这四分之一的操作只是个平方x*x,那整个操作估计也就4步运算
然后发现输出总是0,感觉有什么问题,可能输入被改小了,被检查到了
反正已经知道一步操作是平方了,用公开的一组正常key,等到第二次写断点的时候差不多函数要结束了
所以取消A919DF的硬件写断点,在前面得到的5F8BFB处下个int3断点,断下来后在A919DF设置成硬件读取断点
把A918B8的144位乘法结果全清0,改成小点的数方便观察
运行在这里断下来:

00740513   A0 DF19A900      MOV AL,BYTE PTR DS:[A919DF]
00740518   8A25 281AA900    MOV AH,BYTE PTR DS:[A91A28]
0074051E   22C4             AND AL,AH
00740520   F6D0             NOT AL
00740522   A2 4819A900      MOV BYTE PTR DS:[A91948],AL

看进度又推进了大约四分之一,并发现A918B8处的结果一直没有变化,直到前一步把A918B8处的144位乘法结果改成后72位不是0的时候结果才会发生剧烈变化
这是什么算法?乘法后还要可逆,首先想到的是取模,并且符合小于模的数输出不变,超过模以后会剧烈变化
再重来一下推算这个模n,A918B8处前72位全填0,第73位填1,后面全0
得到:

01 00 01 00 00 01 01 01 01 00 00 01 00 01 01 01 01 00 01 00 01 01 00 00 00 00 01 01 01 01 00 01 00 01 01 00 00 00 01 01 00 00 01 00 01 01 00 00 01 01 00 00 00 00 00 01 01 00 00 00 00 00 01 01 01 00 01 00 01 00 00 00
这样用2的72次方减去它得到模n(实际就是把上面一行取反加1):
01 01 00 01 01 00 00 00 00 01 01 00 01 00 00 00 00 01 00 01 00 00 01 01 01 01 00 00 00 00 01 00 01 00 00 01 01 01 00 00 01 01 00 01 00 00 01 01 00 00 01 01 01 01 01 00 00 01 01 01 01 01 00 00 00 01 00 01 00 01 01 01

后面就懒得详述了,肯定是第三步某运算,再第四步取一次模
最终得到运算关系:

y = x*x*x % n

sub_4013E0运行3次,最终就是27次方
n=0xEA3E7CCB3943CA161B
y=0x87D54

 

sage里计算结果:('%X' % (Zmod(0xEA3E7CCB3943CA161B)(0x87D54).nth_root(27))).upper()[::-1]
得到:4A3A9740B735704562


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2020-5-15 13:03 被ccfer编辑 ,原因:
收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回