战队解题信息
战队名称:Nebula
战队排名:50
解题情况:
AllInOne赛题一血,无pwn手,所以pwn基本没看,主要靠re和web拿的分。
Reverse
1. EzMath
拿到题目拖入 ida pro
,main
中让用户输入,然后将每两字符作为一个__int16 传入函数,返回值与给定的 double 数组值作比较,相同才正确。跟入函数,只有一个循环,迭代 v3 = e – i * v3,本来以为直接正向爆破就行,发现 v3 很快就到 inf 了。查找.init_array
,找到第二个函数,原来这里修改了上面迭代函数的初值,那就可以通过动态调试得到初值,再跑程序正向爆破,但是迭代还是很快到达 inf。再仔细分析.init_array 的函数,发现它是求下面的积分
通过数 学计算可知这个积分项有 an= e - n * an-1 ,也就是那个迭代函数里的式子,那 么给定的值应该是某个 n 对应的积分值,也就可以写程序求积分与给定值比较。 但是有更简单的方式,这个积分值必定是正数,并且会比当前值小,那么可以将 给定 double 值作为初始值迭代一次,通过猜测 n 得到正确的输入,编写脚本:
1 | import math |
得到flag
flag{saam_dim_gei_lei_jam_caa_sin_laa}
2. AllInOne (一血)
拿到 apk,模拟器中运行,随便输入后 check,提示 sorry, you are wrong,拖到 jadx-gui,搜索这个字符串,发现有多个 onClick()对应,不想从 MainActivity 里跟入分析绑定了哪个 OnClickListener,那就使用 mt 文件管理器(ak 反编译失败)修改逻辑,在每个 onClick 处添加 log,模拟器运行,打开 cmd 执行 adb logcat –s debug 监听加入的 log,从而得到被调用的 onClick。在 onClick 中跟入,发现程序逻辑被严重混淆,程序根据传入的参数类决定执行流程。但是 jadx-gui 可以很方便的查找到类名引用,找到 instanceof 那一行,下面的代码块就是正确的执行流程。虽然每个类会在多个地方引用,但是看一下就知道只要是判断的相同的类,不同地方的代码逻辑是一样的,所以随便找一个地方分析代码逻辑就行了。
最终恢复出程序主流程:
1 | Object[] args = new Object[4]; args[0] = input; |
后面应该是什么串匹配算法,没认真看了,反正没有修改 args[0]。最后两个流程块是判断变换后的输入的,也就是变换后的输入需要是给定串的某个给定起始位置字串的前缀。第一次更新附件将错误逻辑修复了,第二次更新附件是将错误的给定串修复了,确定主逻辑后写出逆向脚本再提取出该串跑脚本就行了,最后在显示出的一大堆东西中找到 flag。
脚本:
1 | #!/bin/python |
3. StandOnTheGiants
拿到 apk,拖入 jadx-gui,java 层逻辑很简单,点击按钮后将输入的字符串传给6 native 层方法 check,根据返回值确定是否正确。从 apk 中提取出 so,拖入 ida pro,发现程序将输入转换为 16 进制串,然后初始化一些变量,函数内还可以看 到 crypto/bn/bn_ctx.c 等字符串,那么可以确定这是大数相关的,输入得到的 16 进制串将被用于初始化一个大数变量。之后又初始化了两个大数,一个是
1 | 0x1321D2FDDDE8BD9DFF379AFF030DE205B846EB5CECC40FA8AA9C2A85CE3E992193E873B2BC667DABE2AC3EE9DD23B3A9ED9EC0C3C7445663F5455469B727DD6FBC03B1BF95D03A13C0368645767630C7EABF5E7AB5FA27B94ADE7E1E23BCC65D2A7DED1C5B364B51 |
另一个是 0x010001,看到 0x10001 就有感觉,这 是 RSA 中常用的 e 的值。继续向下看,程序又创建了一个大数变量,并将这变 量和上面的几个大数变量全部传入一个函数,跟入后看到有 crypto/bn/bn_exp.c 字符串,那么可以确定这里是做乘方运算,正好符合 RSA 的运算,也就是 n 为 上面很长的那一串数字,e 为 0x10001,输入为 m,乘方后得 c。之后的逻辑是 对 c 转化为二进制串,然后使用 base64 编码,与给定的字符串比较。base64 的 表与正常的表不同,需要自己解码,但是还注意到码表有两个重复的’+’和’-‘,所 以有多种解码的二进制串对应,需要爆破。 整个流程清楚了,先在 http://factordb.com/index.php 分解 n,直接得到 p、q, 那么编写脚本爆破,得到 flag
1 | #!/bin/python |
得到:
flag{7hiS_is_A_$O_8Ig_C1@Ss}
WEB
1. [强网先锋] 寻宝
题目分为两个部分,key1 和 key2。 Key1: 题目的意思其实就是找到五个值 number1、number2、number3 、number4、number5 满 足五个关卡。第一个’1025b’利用 php 做比较时会做类型转换,这时候会把‘1025b’最后的那 个 b 给去掉。然后 1025>1024。 第二个是用比较少的长度来表示大的值,所以用科学计数法即可。 第三个需要构造 md5 的 hash 碰撞,网上搜到脚本:
1 | import hashlib |
第四个直接用‘0000000’有 filter 会拦截。所以与第一个采取同样思路加 b 解决。 第五个需要进行部分尝试,最后按照直觉是出来‘null’,可以成功通过判断。 number1 ‘1025b’ number2 ‘6E9’ number3 61823470 number4 ‘000000b’ number5 ‘null’
php 代码如下:
1 |
|
得到 key1: KEY1{e1e1d3d40573127e9ee0480caf1283d6}
key2: 处理doc文件代码:
1 | import docx |
结果保存在 https://rec.ustc.edu.cn/share/472dc660-cbfe-11eb-b62f-99aa1c910015 里,再搜索key2 得到key2:KEY2{T5fo0Od618l91SlG6l1l42l3a3ao1nblfsS}
。
得到:flag{0dd5f13e-8ca9-4279-bf27-b390ada9537b}
2. pop_master
简单的 pop 链构造,但是给的 class 设计的很恶心人,困难之处在于写脚本。 初始数据放于 class.txt,初始函数放入 func_list,handle.py 解析出能用的 pop 链 后,手动写入 func_list, 注释掉 handle 函数,取消之后函数块的注释,再次执行, 这样就把需要的类放入 classa.txt。然后执行 payload.py 构造 payload: Handle.py
1 | import re |
最后Payload.py
1 | import re |
得到: flag{d1b7b7b0-9e8e-4590-889a-13555c2b410e}
3. [强网先锋] 赌徒
反序列化,payload 构造如下:
1 | <?php |
MISC
1. EzTime
日志分析,转为 db/CSV 格式,使用 NTFS_Log_Tracker_CMD_V1.6 将 NTFS 的日 志$Logfile 和主文件目录$MTF 转为可读日志记录,如图:
得到的日志表如下,可以看到时间相关的属性是ModifiedTime ,MFT_ModifiedTime,AccessTime,几个属性,从中进行筛选(多尝试),在查找ModifiedTime 和MFT_ModifiedTime不相同的表项时,得到如下文件:
再详细地看该文件在日志中的相关操作,发现其时间属性被修改:
主要关注的是RedoIndo:Update Resident Value,这个操作会改变文件的属性值,所以联合两个一起过滤,大概需要检查的项只有几个。
比赛运气比较好,第一个看这个文件名字很奇怪,直接试一下这个文件,即是flag。
{45EF6FFC-F0B6-4000-A7C0-8D1549355A8C}.png
2. Extremely Slow(未完成)
卡在了pyc文件反汇编上面,一个奇怪的magic头。