看雪CTF 2018国庆题 WriteUp

admin 2021年9月15日09:41:22评论207 views字数 2093阅读6分58秒阅读模式

叹息之墙

题目及题解文件打包:wall.zip

之前玩过几次看雪CTF,确实玩不动玩不动,题目好难啊。前几名是魔鬼吧,逆向分析能力惊人,很快就出flag了。

这次国庆只放出了一题,用来测试平台团队功能,为后面的团队赛做准备。

国庆假期出去玩了几天,回来看了一下这道题。花了一天半时间解出来,解法可能不是很优秀哈~

流程框图

这张图确实像一面墙,难怪叫“叹息之墙”。这也让我想起某次比赛的“给大佬递IDA”。 (╭・ω・)╭IDA

流程分析

每个函数内部大致情况就是,不断的二叉树判断条件,判断进入哪个代码段去执行,可以理解为很多个 if 和 elseif 。此函数中 [esi+301Ch] 存储的值为判断条件(我把它叫做 jump code ,然后该值对应进入的代码段首地址叫做 jump addr )。

分析主函数 main_func

使用搜索功能,找到一些关键代码段,进一步分析出代码段的功能,然后发现部分相同的代码段会重复出现在不同地址处,有些不会被调用到,估计是为了混淆代码。

下面列出已知代码段的 jump addr

entry 代码段:0x40bdc1
功能:主函数首先会进入的代码段

welcome 代码段:0x40bff3, 0x4513a6, 0x45bc28
功能:分别输出两条字符串,然后读取用户输入

format error 代码段:0x437db2, 0x43922e, 0x443c31, 0x45a2e4, 0x45bacb, 0x45bb3c
功能:输出“格式错误”

incorrect 代码段:0x44ec31, 0x45bbd5
功能:输出“输入错误”

correct 代码段:0x44f13d
功能:输出“输入正确”

ret 代码段:0x45104d
功能:返回,退出函数

虽然已知部分代码段的功能,但还是无法掌握整个函数的运行流程。

因此,我专门根据每个代码段里面,出现下一次 jump code 的位置规律,编写了一个用于生成函数内代码段调用顺序框图的脚本。详见文件打包内的生成脚本 flow_main_func.py

生成结果 flow_main_func.png (点此查看大图)

correct 代码段往前推导,根据条件判断标志,找到两处关键函数 0x44d1700x44c195

分析代码段 0x44d170

此处调用 calc_raw 函数,传递了4个32位参数,其实是2个64位数。

第一个64位数为 dword_49F57C ,第二个64位数来自 0x44c195 代码段里的累加结果(详情见下节)。

返回结果需要等于 dword_49F580 才能进入 correct 代码段,否则进入 incorrect 代码段。

通过动态调试,传入不同值,尝试了几十次的函数调用,根据返回传入值和结果的规律,得知了函数的功能。

然后编写出了爆破脚本,详见文件打包内的 cpu爆破脚本 calc_cpu.py 和 gpu爆破脚本 calc_gpu.py

分析代码段 0x44c195

dword_49FE40 处存储着用户输入的那几组整数,整数范围[0,351),然后分别去 dword_49F000 中取出对应数字进行累加,累加结果小于 0x900000000

累加结果在 0x44d170 代码段中,作为 calc_raw 函数的参数传入(第二个64位数)。

仔细发现 dword_49F000 里的351个32位数字其实是有规律的,可以挑选出9个特别的数字,这351个数字是这9个数字的倍数。

解法一

使用爆破脚本 calc_cpu.pycalc_gpu.py ,把 calc_raw 函数第二个64位数的可能值跑出来。

爆破得到的可能值:
0x55121c15, 0x154b3eba3, 0x25455bb31,
0x353f78abf, 0x453995a4d, 0x5533b29db,
0x652dcf969, 0x7527ec8f7, 0x852209885

然后再根据代码段 0x44c195 的功能,编写脚本 getflag_normal.py 解方程并排除无效项,得到序列号。

分析主函数 calc_raw

使用脚本生成代码段调用顺序框图。详见文件打包内的生成脚本 flow_calc_raw.py

生成结果 flow_calc_raw.png

使用上面相同的倒序推导方法,结合动态调试,得到函数内部进行运算的原理。

编写出计算脚本 calc_raw.py

解法二

根据“351个数字是其中9个数字的倍数”规律,把数字划分为9组,进行迭代组合,计算累加结果。

将累加结果代入到 calc_raw.py 里计算,判断结果是否等于 dword_49F580 (进入 correct 代码段的条件)。

将以上解法二过程编写成脚本 getflag_raw.py ,运行脚本得到序列号。

正确的序列号

序列号:17x27x60x97x133x161x243x292x309X

Source: impakho.com | Author:impakho

相关推荐: 蓝帽杯决赛 WRITEUP

前言上周六参加『 蓝帽杯 』全国大学生网络安全技能大赛线上决赛记录,先挖个坑等一手之后官方的 WP 。 0x01 签到题操作内容题目给了一些数字: 1[102, 108, 97, 103, 123, 119, 101, 49, 99, 48, 109, 101…

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年9月15日09:41:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   看雪CTF 2018国庆题 WriteUphttp://cn-sec.com/archives/543786.html

发表评论

匿名网友 填写信息