前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >hctf2016 giligili writeup

hctf2016 giligili writeup

作者头像
LoRexxar
发布2023-02-21 15:49:30
1570
发布2023-02-21 15:49:30
举报
文章被收录于专栏:LoRexxar's Blog

题目是我很早以前做的sctf q1中的web500,我做的时候踩了坑,所以花了很久,感觉题目很有意思,所以就修改了题目又放上来了。

正解wp https://github.com/sternze/CTF_writeups/blob/master/sCTF/2016_Q1/obfuscat/readme.md

最终分数:124 完成队伍:64

解题人数意外的多,感觉还是有很多py的人,迷…

分析代码

代码语言:javascript
复制
h = new MersenneTwister(parseInt(btoa(answer[_[$[6]]](0, 4)), 32));

首先我们根据第一句得到h,h为一个伪随机的数组,根据前四位构成,所以flag的头hctf很重要。

紧接着很多伪随机数都成了固定的数字,也就便于分析了

代码语言:javascript
复制
o = answer.split("_");

这里把输入根据下划线分割得到o

代码语言:javascript
复制
e =- (this[_[$[42]]](_[$[31]](o[1])) ^ s[0]); if (-e != $[21]) return false;
e ^= (this[_[$[42]]](_[$[31]](o[2])) ^ s[1]); if (-e != $[22]) return false; e -= 0x352c4a9b;

根据这部分,相互异或得到了中间两部分的ascii码,这里其实分析逻辑容易进入误区,这里要肯定的是,其实flag一定是可显示的字符,所以肯定不可以是3位或更多位分割,这么一来就很容易确认了

代码到了这里

代码语言:javascript
复制
a += _[$[31]](o[3].substring(o[3].length - 2)).split("x")[1];
//o[3]的最后两位
d = parseInt(a, 16) == (Math.pow(2, 16)+ -5+ "") + o[3].charCodeAt(o[3].length - 3).toString(16) + "53846" + (new Date().getFullYear()- +1+ "");

出现了很多可变的东西,首先是a a由o[0]和o[3]共同决定

代码语言:javascript
复制
a = parseInt(_[$[23]]("1", Math.max(o[0].length, o[3].length)), 3) ^ eval(_[$[31]](o[0]));

其次a会在十进制的基础上,拼接上o[3]出大括号的后两位的十六进制,转十进制 a += _[$[31]](o[3].substring(o[3].length - 2)).split("x")[1];

和a相比较的后面的代码,其中有一个可变量为o[3]的倒数第三位,这里出现了隐藏条件 1、中间的o[3]倒数第三位转十六进制后不允许存在字母 2、整体转16进制之后,除了后四位不能存在字母 3、倒数2位必须可显

综合上面的条件,我们就需要脚本来解决问题了

代码语言:javascript
复制
for i in range(30,120):

	 if 'a' not in hex(int("65531" + repr(i) + "53846" + "2015"))[2:-5]:
	 	if 'b' not in hex(int("65531" + repr(i) + "53846" + "2015"))[2:-5]:
	 		if 'c' not in hex(int("65531" + repr(i) + "53846" + "2015"))[2:-5]:
	 			if 'd' not in hex(int("65531" + repr(i) + "53846" + "2015"))[2:-5]:
	 				if 'e' not in hex(int("65531" + repr(i) + "53846" + "2015"))[2:-5]:
	 					if 'f' not in hex(int("65531" + repr(i) + "53846" + "2015"))[2:-5]:
							print i
							print hex(int("65531" + repr(i) + "53846" + "2015"))
							print hex(int("65531" + repr(i) + "53846" + "2015"))[-5:-1]
							# print chr(int(hex(int("65531" + repr(i) + "53846" + "2015"))[-5:-3],16))
							# print chr(int(hex(int("65531" + repr(i) + "53846" + "2015"))[-3:-1],16))

下面我们得到了7条,紧接着,筛选可显示字符 只剩下3个了

代码语言:javascript
复制
64
0x17481184783f3fL
3f3f

只剩下这个了,那么最后二位是??,倒数第三位是d

那么我们现在还得到了o[3]和o[0]相关的关系,那么我们接下去看

代码语言:javascript
复制
i = 0xffff;
n = (f = _[$[23]](o[3].charAt(o[3].length - 4), 3)) == o[3].substring(1, 4);
// f 是o[3]的倒数第4位重复3遍和o[3]234位相等
g = 3;
t = _[$[23]](o[3].charAt(3), 3) == o[3].substring(5, 8) && o[3].charCodeAt(1) * o[0].charCodeAt(0) == 0x2ef3;
//o[3]的第四位重复三遍和o[3]的678位相同,o[3]第2位的阿斯克码-2×o[0]第1位的阿斯克码==0x2ef3

这里我们拆解0x32ab得到119和101 得到两个字符分别为e和w,那么可以确定2位,但是不确定顺序

下面接着分析

代码语言:javascript
复制
i = 0xffff;
g = 3;
h = ((31249*g) & i).toString(16);
i = _[$[31]](o[3].split(f).join("").substring(0, 2)).split("x")[1];
s = i == h;

这里的s判断给了我们新的信息,因为h已知,所以我们就能得到o[3]的第一位和第五位,这么一来,o[3]所有的位我们都知道了是 neee3eeed??

现在我们知道了长度,可以肯定的是,o[3]肯定比o[1]长,那么基本可以得到o[1]了,回到刚才的逻辑

代码语言:javascript
复制
a = parseInt(_[$[23]]("1", Math.max(o[0].length, o[3].length)), 3) ^ eval(_[$[31]](o[0]));

这里我们得到的o[0]为h3r3, 特别的是,我们刚才得到o[0]第一位为w,这里有个小坑,由于parseInt(_[$[23]]("1", Math.max(o[0].length, o[3].length)), 3)过小,所以异或没有影响到所有的位,根据意思,我们加上了w,那么getflag

代码语言:javascript
复制
hctf{wh3r3_iz_y0ur_neee3eeed??}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016/11/19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档