SuSH

大概是以技术文为主的blog

0%

Hackergame 2019 Writeup

Hackergame 2019 Writeup

比赛结束后忙了若干天才有空挤出这篇writeup……

先放一下自己的成绩吧(

签到题

送分题,打开开发者工具,把按钮的disabled属性去掉即可:

输入token后提交即可得到flag:

白与夜

目测是一道图片隐写题。Google搜出来若干篇文章之后知道了StegSolve这个工具。

用其打开这张图片,在Normal Image页面就可以看到若隐若现的flag:

切换至Colour Inversion(Xor)页面后,看到了清晰的flag:

信息安全2077

直接打开题目给出的链接会看到这样的提示:

在开发者工具的Source页面,页面中的脚本如下:

可以看到,在请求flag.txt时,在header处添加了一个If-Unmodified-Since的字段,值为当前时间。如果请求没有成功(返回HTTP 200),则计算当前时间与最后修改时间Last-Modified的差值,将其显示出来。

由此可以推测,flag.txt的修改时间在某个时间点,如果当前时间早于该时间点,那么If-Unmodified-Since就不会为真,请求不会成功。此处返回的是HTTP 412 (Precondition Failed):

那么问题就容易解决了,为了让请求成功,把If-Unmodified-Since的值改在flag.txt的修改时间之后就可以了。在得到lastModified的后一行打个断点,这就是我们需要的修改时间,格林威治标准时间的2077年10月1日0时0分0秒:

(emmmm,果然是2077……)

然后在发送请求前打一个断点,将If-Unmodified-Since的值改为在其之后的时间点:

就可以得到flag:

宇宙终极问题

42

给出\(x,y,z\),使得\(x^3+y^3+z^3=42\)

之前正好看到这个问题已经被解决了\[ x = -80538738812075974 , y = 80435758145817515 , z = 12602123297335631 \]

网页读取器

先看源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
whitelist_hostname = ["example.com",
"www.example.com"]
whitelist_scheme = ["http://"]


def check_hostname(url):
for i in whitelist_scheme:
if url.startswith(i):
url = url[len(i):] # strip scheme
url = url[url.find("@") + 1:] # strip userinfo
if not url.find("/") == -1:
url = url[:url.find("/")] # strip parts after authority
if not url.find(":") == -1:
url = url[:url.find(":")] # strip port
if url not in whitelist_hostname:
return (False, "hostname {} not in whitelist".format(url))
return (True, "ok")
return (False, "scheme not in whitelist, only {} allowed".format(whitelist_scheme))

其过滤网址的方法可以分为以下几步:

  • 检查输入的URL是否以http://开头;
  • 从输入的URL中取出http://之后的字符,以去除协议名;
  • 在上一步的结果中寻找@符号,若有,则取出其后面的字符,以去除用户名信息;
  • 在上一步的结果中寻找/符号,若有,则取出其前面的字符,以去除域名以外的信息;
  • 在上一步的结果中寻找:符号,若有,则取出其前面的字符,以去除端口号;
  • 判断上面的结果是否在白名单(example.com, www.example.com)中。

参考Server-side request forgery (SSRF) 里面的"SSRF with whitelist-based input filters"一节,构造了这样的一个URL:http://web1/flag#@example.com

  • #这个符号在URL规范里是一个Fragment Identifier,该符号前面的部分是一个URL查询,后面的部分将被视为额外的Fragment,不会发送给服务器,而是由客户端进行处理。亦即,访问http://web1/flag#@example.com与访问http://web1/flag,对服务器而言是一样的;
  • 我们来看看这个URL是否能通过上述过滤步骤:
    • 它以http://开头,没有问题;
    • 取出@符号后面的字符,得到example.com
    • 没有/:符号,跳过这两步;
    • example.com在白名单中,检查通过。

检查出的结果是example.com,实际访问的却是http://web1/flag,我们从而绕过了URL检查,得到了flag:

达拉崩吧大冒险

这题显然需要我们将Attack值溢出。抄起开发者工具,在买童子鸡的时候把数量改掉:

但是……改成多少呢?

一开始试的是C语言里面的INT_MAX,并没有溢出……后来用了比较蠢的方法,用了一个比较大的数字(大概是十几个9),提交了几次,终于让Attack值溢出了(流下了不学无术的泪水)

再后来用了Java的Long型的最大值(Long.MAX_VALUE=9223372036854775807, \(2^{63} - 1\)),一发入魂(再次流下了不学无术的泪水)

溢出后是这么个效果:溢出效果

拿到flag:

小巧玲珑的 ELF

拿起神器IDA,打开下载下来的文件,按下F5看一下反编译后的代码。

首先映入眼帘的是这么一串东西:

然后是一些代码逻辑:

由此可以猜测:

  • 一开始看到的那串东西是一个字符数组;
  • 使用系统调用得到的输入存放在buf数组,并对其每一个字符进行处理。对于buf数组的第i个元素buf[i],有如下操作:
    • buf[i] 加上i*2
    • buf[i]i 异或
    • buf[i] 减去i
  • 用处理后的buf数组与上述字符数组进行比对,如果一致,则使用系统调用输出flag。

很容易写一个demo进行逆操作,来得到期望的输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#define LEN 47
int main()
{
char buf[LEN] = {102, 110, 101, 107, -125, 78, 109, 116, -123, 122,
111, 87, -111, 115, -112, 79, -115, 127, 99, 54, 108, 110, -121,
105, -93, 111, 88, 115, 102, 86, -109, -97, 105, 112, 56, 118, 113,
120, 111, 99, -60, -126, -124, -66, -69, -51, 0};
for(int i=0; i<LEN-1; ++i) {
buf[i] += i;
buf[i] ^= i;
buf[i] -= 2*i;
}
printf("%s", buf);
return 0;
}

最后的输出:

三教奇妙夜

Part 1

一个很自然的想法是,黑底白字的部分应该是视频的关键帧。那么把关键帧提取出来,在其中进行筛选就可以了。

使用ffmpeg来导出关键帧,存放在预先建立的pics目录:

.\ffmpeg -i output.mp4 -vf "select=eq(pict_type\,I)" -vsync vfr pics\%04d.jpg

输出了4319张关键帧。工作量已经小很多了,一张一张筛选就是了

发现关键帧的md5值似乎是一样的,用Python写个小脚本筛选一下md5不一样的文件:

1
2
3
4
5
6
7
#!/bin/python
import os
for i in range(1, 4320):
result = os.popen("md5sum " + f'{i:04d}' + ".jpg").read()
md5 = result[:32]
if md5 != "082c3d659340d78fa89d218004c6da7e": # md5sum 0002.jpg
print(f'{i:04d}' + ".jpg")

运行:

感觉……flag少了最后一块(扑通)

Part 2

我开始怀疑,flag片段并不是都在关键帧里的。那就得想个办法把非关键帧里的片段找出来。

刚才找到的flag片段中,最后一个片段大约在视频的9:00:00之后。经过一番参考,得知可以用下面的命令,输出9:00:00之后,画面变化幅度超过0.1的帧:

.\ffmpeg -ss 9:00:00.0000 -i output.mp4 -vf "select=gt(scene\,0.1), scale=640:360" -vsync vfr pics\%04d.png

得到了下列图片:

拼凑所有片段,就可以得到完整的flag:flag{ViDe0_prOcE55_with_program_1s_eaSy}

Reference:

Extract images frame by frame from a video file using FFMPEG

THUMBNAILS (IFRAME / SCENE CHANGE) - 2018

后记

  • Shell骇客本来应该不难,但不是很熟悉msfvenom工具,生成的shellcode并没有起作用
  • 我想有个家那道题,机智地sudo chmod o-x /通过了删除检测,没想到后面还有要求,却没法把权限改回去了,宣告gg,只好重置系统(x