Hackergame 2020比赛解题分析
1 前言
Hackergame 2020,中文名是:中国科学技术大学第七届信息安全大赛。
题目很多而且涉及方面极广,在这次比赛中学到了很多东西,虽然大部分题都没有做出来,但是锻炼了自己的同时涉及的方面也更宽广了,最后成绩不怎么样,但是好在锻炼了自己:
2 正文
2.1 签到
(1)题目分析:
要求给出整数倍的数值提交,但是页面上的滑条很灵敏,很难正好弄到整数。
(2)解题步骤:
直接点击提交,可以在url栏看到是以get方式提交的number变量值,直接修成1再次提交即可:
2.2 猫咪问答++
(1)题目分析:
一个表单,有各种各样的问题,分别需要你填出正确的答案:
(2)解题步骤:
解题思路就是利用网络搜索工具,考察我们的信息搜索能力,依次解决答案即可。
1.
问:以下编程语言、软件或组织对应标志是哺乳动物的有几个?
Docker,Golang,Python,Plan 9,PHP,GNU,LLVM,Swift,Perl,GitHub,TortoiseSVN,FireFox,MySQL,PostgreSQL,MariaDB,Linux,OpenBSD,FreeDOS,Apache Tomcat,Squid,openSUSE,Kali,Xfce.
提示:学术上一般认为龙不属于哺乳动物。
答:第一小题明显是最复杂的,可以最后一一尝试。
2.
问:第一个以信鸽为载体的 IP 网络标准的 RFC 文档中推荐使用的 MTU (Maximum Transmission Unit) 是多少毫克?
提示:咕咕咕,咕咕咕。
答:以关键词在搜索引擎搜索即可:
关键信息:
1990年4月1日,David Waitzman向互联网工程任务组的网络工作小组提交了一份名为《禽类载体IP数据报传输标准》的制订标准(简称RFC),如今简称为IPoAC。RFC 1149当中描述了“一种在禽类载体当中封装IP数据报的实验性方法”,以及一系列用于解决服务质量问题以及向IPv6过渡的更新建议(二者分别发布于1999年4月1日与2011年4月1日)。
RFC 1149:https://www.rfc-editor.org/rfc/rfc1149.txt
关键信息:
The MTU is variable, and
paradoxically, generally increases with increased carrier age. A
typical MTU is 256 milligrams.
答案:256
3.
问:USTC Linux 用户协会在 2019 年 9 月 21 日自由软件日活动中介绍的开源游戏的名称共有几个字母?
提示:活动记录会在哪里?
答:使用GoogleHaking的语法
GoogleHacking:site:lug.ustc.edu.cn intext:2019年9月21日+自由软件日
搜到的网址:https://lug.ustc.edu.cn/oldwiki/lug/events/sfd
Teeworlds
答案:9
4.
问:中国科学技术大学西校区图书馆正前方(西南方向) 50 米 L 型灌木处共有几个连通的划线停车位?
提示:建议身临其境。
答:搜索中国科学技术大学的全景3D图片
答案:9
5.
问:中国科学技术大学第六届信息安全大赛所有人合计提交了多少次 flag?
提示:是一个非负整数。
答:直接搜索相关信息
答案:17098
最后从尝试第一题的:16-12
答案:12
就可以了
(3)拓展:
本道题还可以使用burpsuit或者python等工具直接进行爆破解题,但是一一搜索也锻炼了信息搜集能力。
2.3 2048
(1)题目分析:
打开是一个简单的移动砖块小游戏,需要达到足够高的分数才能给flag,但是真的达到那个分数是很难的,此时我们应该找其他方法。
(2)解题步骤:
故意失败一次,利用F12中的Network捕捉发送包的定位:
选择然后定位本地传输的js代码位置,然后就会看到下面的代码:
分析代码即可得知,如果赢了就会发送如下url:
url = "/getflxg?my_favorite_fruit=" + ('b'+'a'+ +'a'+'a').toLowerCase();
直接在控制台看一下的('b'+'a'+ +'a'+'a').toLowerCase();值:
于是可以构建答案:
payload:
?my_favorite_fruit=banana
flag:
flxg{8G6so5g-FLXG-aa63af33cd}
2.4 一闪而过的 Flag
(1)题目分析:
下载下来是个可执行控制台程序,但是一执行就会直接消失。
(2)解题步骤:
打开cmd命令行,在cmd中执行程序:
此时显示的内容就不会再消失。
2.5 从零开始的记账工具人
(1)题目分析:
给出一个Excel表格,其中全部都是繁体文字写出的钱的数值,要求要将它们全部加起来计算出结果。
(2)解题步骤:
1.下载方方格子Excel插件,这个插件有将简体中文数值转化为数字的功能。
2.但是很明显题目中的数值全部都是繁体中文,方方格子并不能全部转换,而且其中还有许多小数,小数部分也是不能直接转换的。
3.我需要写python脚来讲繁体中文转化为简体中文,并且对小数部分和整数部分分别处理,以免方方格子在转化数字时发生错误:
#!/usr/bin/python
'''
区分元的代码
c=s.split('元')
print(c[0],c[1])
f.write(c[1])
f.write('\n')
'''
a=open('以元结尾.txt','r')
text=a.read()
a.close()
f=open('out.txt','w')
st=text.split('\n')
for s in st:
ans=""
for c in s:
#print(c)
if c=='壹':
c='一'
elif c=='贰':
c='二'
elif c=='叁':
c='三'
elif c == '肆':
c = '四'
elif c == '伍':
c = '五'
elif c == '陆':
c = '六'
elif c == '柒':
c = '七'
elif c == '捌':
c = '八'
elif c == '玖':
c = '九'
elif c=='佰':
c='百'
elif c == '拾':
c = '十'
elif c=='零':#对元部分的处理
c='零'
#elif c=='元':
# c='百'
# elif c=='角':
# c='十'
# elif c=='零' or c=='分':#对分部分的处理
# c=''
# elif c=='整':
# c='零'
else:
print('error')
exit(-1)
ans+=c
f.write(ans)
f.write('\n')
f.close()
4.然后将它们含元的部分、不含元的部分还有以分结尾的部分,分别处理,最后相加。
5.最后得到和:17456.95
2.6 超简单的世界模拟器
(1)题目分析:
由题目提示了解到是一种数字游戏叫做:生命游戏(Conway's Game of Life)
需要我们在这个游戏中达到它想要的目的,即让细胞碰到右侧的两个砖块。
(2)解题步骤:
1.搜索和了解了生命游戏的基本原理和玩法。
2.在维基百科中得到了一些基本的细胞结构,比如太空船,就可以轻松解决第一小题:摧毁一个砖块。
payload1:
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000001001000000
000000000100000
000001000100000
000000111100000
3.第二小题我在比赛中没有解出来,同时摧毁上下两个砖块太过困难,官方wp给出了一个可行的例子:
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000011000000
000000001100000
000000011000000
000000010000000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
(3)拓展:
官方指出,除了手工构建的方法以外,还能用暴力破解的方法,还是python学的不到家,需要继续努力。
2.7 自复读的复读机
(1)题目分析:
编写两个只有一行的 Python 代码:
其中一个要输出代码本身的逆序(即所有字符从后向前依次输出)
另一个是输出代码本身的 sha256 哈希值,十六进制小写(2)解题步骤:
(2)解题步骤:
1.通过关键词搜索相关信息,可以看到一些教程和结果:
#教程网址:
#https://zhuanlan.zhihu.com/p/34882073
#https://tio.run/##K6gsycjPM/7/P95WPd5Wtci6oCgzr0QjXlU1XlMdzonX/P8fAA
#='=%r;print(%%)';print(%)
#这一行代码能输出本身
2.题目要求是输出字符串的逆序,所以需要自己进行修改构造:
好不容易构建出来一行代码:
_=")'_='+]1-::[_%%_(tnirp;%r";print(_%_[::-1]+'=_')
输出和原来的相反一毛一样,然后发现,人家题目连回车符也算上了。。。
这样提交之后有一个问题,就是输出比代码多了一个 \n,这是由于输入的代码结尾没有换行符而 print 输出的内容结尾会自带换行符,我们只需要让 print 不输出换行符,加一个 ,end="" 即可。
exp:
_=")''=dne,'_='+]1-::[_%%_(tnirp;%r";print(_%_[::-1]+'=_',end='')
(3)拓展:
官方的解法更加简洁:
第一问(每行都是一个可能的构造):
exec(s:='print(("exec(s:=%r)"%s)[::-1],end="")')
s='s=%r;print((s%%s)[::-1],end="")';print((s%s)[::-1],end="")
第二问(每行都是一个可能的构造):
exec(s:='print(__import__("hashlib").sha256(("exec(s:=%r)"%s).encode()).hexdigest(),end="")')
exec(s:='import hashlib;print(hashlib.sha256(("exec(s:=%r)"%s).encode()).hexdigest(),end="")')
import hashlib;s='import hashlib;s=%r;print(hashlib.sha256((s%%s).encode()).hexdigest(),end="")';print(hashlib.sha256((s%s).encode()).hexdigest(),end="")
2.8 来自一教的图片
(1)题目分析:
题目给了一张上面有奇怪的杂乱纹路的图片,然后给出提示是做傅里叶光学实验的图片:
(2)解题步骤:
根据提示搜索相关代码,搜索到可以进行傅里叶光学转码的代码,然后进行转码即可:
exp:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('./4f_system_middle.bmp', 0)
f = np.fft.fft2(img)
logf = 20*np.log(np.abs(f))
plt.imshow(logf, 'gray')
多次解析就可以看出来flag:
2.9 生活在博弈树上
(1)题目分析:
给一个可执行程序,要求逆向分析找出漏洞利用。
(2)解题步骤:
这是一个pwn题,直接放入ida中:
分析了好几次代码,最终确定,解题方法就是用gets函数覆盖success这个变量的值
首先可以看到临时变量的设定:
rbp没见过,但是只能当成ebx来看了啊,知识面还是太窄,可以看到是-90h,也就是-9*16=-144
找了半天没找到success变量的位置,注释原来是不会显示在反编译文件中的啊
根据代码输出可以大概找到定义位置,也看不太懂。。。
对照着源码看好像明白了一点,前面两个方框是代码中的定位光标的作用。
那么第三个方框就是处理变量了吧,估计succes应该就是rbp+var_1,var_1=-1,差距也就是-1-(-144)=143咯。
设计payload:
payload="(1,1)"+"A" * 138 + "\x01"
过了!!!
flag:
flag{easy_gamE_but_can_u_get_my_shel1}
这道题还有后面一道题,相当于我现在做了半道,但是没有新的源代码和服务端了,仔细看了看源代码,也不可能有第二个flag,所以猜测应该要拿到它的shell,但是源码中没有直接的函数可以拿到shell,也就是说可能是代码注入pwn。
难办,这方面我还没学,也就不能做了。
2.9 狗狗银行
(1)题目分析:
经过借钱还钱、开信用卡、储蓄卡等操作使净资产确实高于 2000 时才会给出 flag
(2)解题步骤:
刚开始我的思路就错了,一直在找包的漏洞,结果发现包中的参数都是不能利用的值,api也是非常简化的调用形式,所以根本找不到可利用处,也就是说辛苦的抓包白费了,人家就是一个全服务区的后端引用。
无奈之下,我从“狗狗银行”这个名字入手,找了一下类似的题,结果还真让我找到了,漏洞应该就是整形溢出了:
经检验,在信用卡转给储蓄卡极值之后,净资产会加1,原理还不太明白,但是一张信用卡最多给一张储蓄卡加2,那就需要最少500张信用卡和500张储蓄卡了。。。
想把注意打到bp的多线程上,但是太麻烦了,先看看有没有其他思路。
9007199254740991,查了一下,这个数字是js的最大精确整数Math.pow(2,53)-1
同时,我又看到了官方的一条公告:
公告 1:本题前端计算存在浮点数导致的计算误差,数字特别极端时显示可能不正确。但后端采用大整数精确计算,只有净资产确实高于 2000 时才会给出 flag。
额。。。那这条思路是不是没戏 了。。。
然后尝试了各种大数据、特殊数据:
167时,利息为1
利息为2的话最起码要500左右,也就是说,167是利率最大的时候
834,利息为3
本金1000,最多能分为167*5+165
连吃饭钱也赚不回来,那就借吧!
因为开始时,信用卡利息最小是10,利率为0.5%,也就是说,欠款达到2000时才会让利息更多。
2000/167=11.9,不够啊,没顿加利息是20块啊。。。
500,能弄4张,也就是8块,不够
3099/167=18.56,还是不够
思路一度十分僵化。。。。。
但是功夫不负有心银啊!突然想到,信用卡利率是0.5%,也就是说200币是1币的利息,而储蓄卡只要167就能挣到1币,也就是说我每转一张卡就有23币的抽成!这绝对是解题点!
官方给的限制是最多1000张卡,完全够用!
开始我手输了一段,,,太痛苦了,也完全不够用,还是乖乖回来用python了,也学习了一下requests模块的简单使用,这波不亏!
exp:
import requests
url='http://202.38.93.111:10100/api/create'
header={'Host':'202.38.93.111:10100'
,'Accept':'application/json, text/plain, */*'
,'Authorization':'*************'
,'Content-Type':'application/json;charset=UTF-8'
,'Accept-Encoding':'gzip, deflate'
,'Accept-Language':'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6',
'Cookie': 'session=*****'
}
for i in range(83,800):
data = '{"src":2,"dst":%d,"amount":167}'%i
print(i)
r=requests.post('http://202.38.93.111:10100/api/transfer',headers=header,data=data)
r.encoding='utf-8'
print(r.text)
print(r.status_code)
结果:
图17 狗狗银行3
flag:
flag{W0W.So.R1ch.Much.Smart.52f2d579}
3 结尾
本次比赛我做出来的题只是一小部分,但是受益却是颇多,不断学习和不断成长的这个过程让我很是享受,这也正是网络安全这门课程的魅力之处。
同时Hackgame这个比赛也非常好,有意思的地方远远不止我写的这些东西,光是消化其中的知识就需要好久吧,我很高兴能在这次比赛中用到我在网络安全课中学到的知识,也希望自己能不忘初心,走的更高更远!
ps:这篇文章原是在word中写的,后来腾出来,导致这些图片都不太清晰,希望大家不要在意。