Wp for hackergame2020

最后几天没时间玩了,屯的flag都没交,哭哭

但u1s1,shallow师傅推荐的比赛确实质量高,shallow,永远滴神!

0x01 签到

F12,把max改成1,直接拉满后点提取,flag到手

15.png

0x02 猫咪问答++

开 幕 雷 击

16.png

梅 开 二 度

17.png

告辞!

用burp对这俩阴间空进行爆破,然后得到flag

0x03 2048

2048?看我玩过去!

18.png

对不起打扰了

选择查看网页源代码,发现有以下提示信息

1
2
3
4
<!-- 
changelog:
- 2020/10/31 getflxg @ static/js/html_actuator.js
-->

然后点进去html_actuator.js,搜索关键词win,找到以下内容

1
2
3
4
5
if (won) {
url = "/getflxg?my_favorite_fruit=" + ('b'+'a'+ +'a'+'a').toLowerCase();
} else {
url = "/getflxg?my_favorite_fruit=";
}

后面的玩意不知道是个啥,丢进Console里

19.png

直接访问url得flag

1
/getflxg?my_favorite_fruit=banana

0x04 一闪而过的 Flag

不知道想考啥,cmd打开就能看见flag

0x05 从零开始的记账工具人

下载下来一个表格要计算和,写个脚本自己跑一边就好了,因为数字都比较小,所以就投了个懒去网上搜了一个,能跑出结果就行,另外Python直接从Excel里读的数字好像有点问题,就在Excel里先转成大写数字后再解析一遍了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import xlrd

data = xlrd.open_workbook('bills.xlsx')

table = data.sheets()[0]

def aoligeiganle(amount):
chinese_num = {'零': 0, '壹': 1, '贰': 2, '叁': 3, '肆': 4, '伍': 5, '陆': 6, '柒': 7, '捌': 8, '玖': 9}
chinese_amount = {'分': 0.01, '角': 0.1, '元': 1, '拾': 10, '佰': 100, '仟': 1000, '圆': 1}
amount_float = 0

amount_yuan = 0
for i in chinese_amount:
if i in amount:
if amount[amount.index(i) - 1] in chinese_num.keys():
amount_yuan += chinese_num[amount[amount.index(i) - 1]] * chinese_amount[i]
amount_float += amount_yuan
if(amount.startswith('拾')):
amount_float += 10

return amount_float


CN_NUM = {
'〇' : 0, '一' : 1, '二' : 2, '三' : 3, '四' : 4, '五' : 5, '六' : 6, '七' : 7, '八' : 8, '九' : 9, '零' : 0,
'壹' : 1, '贰' : 2, '叁' : 3, '肆' : 4, '伍' : 5, '陆' : 6, '柒' : 7, '捌' : 8, '玖' : 9, '貮' : 2, '两' : 2,
}

CN_UNIT = {
'十' : 10,
'拾' : 10,
'百' : 100,
'佰' : 100,
'千' : 1000,
'仟' : 1000,
'万' : 10000,
}

def chinese_to_arabic(cn:str) -> int:
unit = 0 # current
ldig = [] # digest
for cndig in reversed(cn):
if cndig in CN_UNIT:
unit = CN_UNIT.get(cndig)
if unit == 10000 or unit == 100000000:
ldig.append(unit)
unit = 1
else:
dig = CN_NUM.get(cndig)
if unit:
dig *= unit
unit = 0
ldig.append(dig)
if unit == 10:
ldig.append(10)
val, tmp = 0, 0
for x in reversed(ldig):
if x == 10000 or x == 100000000:
val += tmp * x
tmp = 0
else:
tmp += x
val += tmp
if(cn.startswith('拾')):
val += 10
return val



sum = 0

for i in range(1,1001):
x = table.cell(i,0).value
num = table.cell(i,2).value
# print(x)
ans = round(aoligeiganle(x),2)
num = chinese_to_arabic(num)
# print(ans,num)
sum += num * ans
sum = round(sum,2)
# print(sum)

print(sum)

0x06 超简单的世界模拟器

看了半天看不懂题目,小破站里搜到了这个网站,里面有模型

第一问巨简单,找到对应的行数放一个直线运动的模型就行

第二问把模型改一改,然后多组合几个让变化一直往右下进行就行了,瞎输一顿总能成功

0x07 从零开始的火星文生活

看了半天不知道说啥,应该是把flag用几种不同的编码解码了好几次,有工具网站,多试几次就行了

1
2
3
4
我攻破了 Hackergame 的服务器,偷到了它们的 flag,现在我把 flag 发给你:
flag{H4v3_FuN_w1Th_3nc0d1ng_4Nd_d3c0D1nG_xxxxxxxx}
快去比赛平台提交吧!
不要再把这份信息转发给其他人了,要是被发现就糟糕了!

0x08 自复读的复读机

先写一个能复读自己代码的脚本,然后加上[::-1]就行了,这里要注意的一个点是记得处理掉\n,因为这个卡了好久不知道自己错哪了

T1:

1
quotation = chr(0x22);newline = chr(0x0a);s = "quotation = chr(0x22);newline = chr(0x0a);s = {1}{2}{1};s = s.format(newline, quotation, s);print(s[::-1],end='')";s = s.format(newline, quotation, s);print(s[::-1],end='')

T2:

1
import hashlib;a=b"import hashlib;a=%a;print(hashlib.sha256(a%%a).hexdigest(),end='');";print(hashlib.sha256(a%a).hexdigest(),end='');

0x09 233 同学的字符串工具

首先python自己本身没有什么漏洞,不像PHP,所以需要利用函数的特性来打到我们的目的

T1 Unicode字符折叠

这里给个url(如果不咕咕我应该也会写一个相关的),关于unicode讲的都挺好的,利用的就是unicode字符折叠upper后会变回两个或多个字符这一特性

T2 utf-7编码

去看flag里那个url,能学到不少东西,这个题只要提交flag的utf-7编码就好了

0x0a 233 同学的 Docker

虚拟机连不上,wsl1更新不了,之后只能用服务器瞎搞,因为用命令删除flag.txt后,别的层里可能没有删掉,把镜像pull下来之后在里面找flag就行了

0x0b 从零开始的 HTTP 链接

虚拟机连不上,wsl1连不上,最后用的还是服务器,先curl 202.38.93.111:0看到源码,再利用websocket通信连接地址,然后用了各种各样的办法成功安装上websocket之后websocat ws://202.38.93.111:0/shell连接,提交token就能看到flag了

0x0c 来自一教的图片

搜索题目关键信息傅里叶光学,对图片进行FFT处理,然后进行一下地狱难度的拼图,就能拼出flag了(如果实在看不清可以调整一下对比度)

1
2
3
4
5
6
7
8
9
10
11
12
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('4f_system_middle.bmp', 0)

f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
res = np.log(np.abs(fshift))

plt.imshow(res, 'gray')
plt.show()

0x0d 超简陋的 OpenGL 小程序

尝试魔改程序,在尝试了一万种方法之后发现把basic_lighting.vs里的最后一行改成gl_Position = projection * view * vec4(FragPos, 1.0) - vec4(0,3,0,0);,就能看到flag了

0x0e 生活在博弈树上

T1 栈溢出

下载源码并阅读,看到敏感函数gets(),和这里的判断代码

1
2
3
4
5
if (success) {
puts("What? You win! Here is your flag:");
flag_decode();
puts(flag);
}

使gets()函数发生栈溢出,将源代码中success变量变成True就行了

1
2
3
target = 0x402527
rbp = 0x4a8320
payload = b'a'*0x90+p64(rbp)+p64(target)

T2不会pwn,爬了

0x0f 来自未来的信笺

看了榜一的WP,学会了学废了


先进行二维码识别,但是 pyzbar 这个库不能处理二进制(会在\0截断)。patch 该库也没用,然后发现是 zbar 自身的问题。
Google 一番后得知,zbar 的高版本才能处理二进制,于是用高版本(arch 带的版本)+ os.system 来处理。

1
2
3
4
5
6
7
8
import os

cmd='zbarimg --raw -Sbinary %s > %s'
n = 351
for i in range(0, n):
fi = 'frames/frame-x%s%s.png' % (chr(i // 26 + 97), chr(i % 26 + 97))
fo = 'output/%d.txt' % i
os.system(cmd%(fi,fo))

把所有输出拼起来可以得到一个 tar 文件,解压出一个 repo.tar.xz,再解压就得到了 flag。


0x10 狗狗银行

随便玩一玩发现银行是四舍五入计算利息的,那就让信用卡的利息<0.5,让储蓄卡的利息>0.5,即保持信用卡的欠钱数x满足$2000\leq x <2100$,同时每天储蓄卡的利息大于信用卡的利息+10,这样就可以不停地薅羊毛了,在用手点了三个小时后,用burp进行攻击,或者写脚本也行,当净资产>2000时,flag就有了

20.png

负 债 累 累.jpg

0x11 超基础的数理模拟器

懒得解析,不想手算,啥也不会,爬了

0x12 永不溢出的计算器

这题目怎么看怎么像RSA,所以我们可以先搞到 $n$ ,让服务器计算 $0 - 1\ (mod\ n)$ ,服务器就会返回 $n-1$ ,这样一来有了 $n$ ,只要想办法分解 $n$ 就万事大吉了,在尝试了各种奇奇怪怪的计算方式之后,发现服务器中基本功能本地都可以跑,只有 $sqrt(x)$ 功能不行,多次尝试后发现其会返回在有限域 $GF(n)$ 内的平方根,也就是说只要我们发送的 $x$ 是 $n$ 的二次剩余,服务器就会返回其在有限域内的平方根

而当我们选择 0~n 中的任意整数 $x$ ,给服务器计算 $y=sqrt(x^2)$ ,每一个能够在 $ mod\ n $ 意义下开平方(二次剩余)的非零整数都有 4 个平方根,分别是 $a、b、n-a、n-b$,当我们获得的数是 $x$ 或是 $n-x$ 时,显然对我们来说没有有用的信息,再发一个就行了,而当我们拿到了另外两个数时,根据关系 $x^2=y^2\ (mod\ n)$ ,可以推得: $x^2=y^2\ (mod\ n)$ ,即 $x^2-y^2=k\cdot n$ ,则 $n\ |\ (x+y)\cdot (x-y)$ ,但显然 $x+y、x-y$ 不可能是 $n$ 的因子,那就是说 $x+y$、$x-y$ 中分别包含 $n$ 的一个因子,则 $p=gcd(x+y,n),q =gcd(x-y,n)$ 进而达到分解n的目的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from Crypto.Util.number import *
from gmpy2 import *
n = 63844357941350242178319124095202481115953584192426618878732935935494834491816826661998861512314880163805697716449959448752976927112954730282916961050961825787515398914123651824294676790072133464576773845129309793573874518742295125788319117463509944821578109553336342869377806251535394443075383675560895153889
x = 123456789021893174903650635675814737536508951450414958364715686536861342396423579368274820142478176573615325936563821749809712758293516356473872587346576457823567826581305234356475896875325463576879854633145263786976543657098425637865432456789765432546786543245678908765432456789765432456789765435678976521453475438657563461373457638769787542657635251524736575462463535
y = 10846691131738259785471222827308910495801759515077645404110247868474133623116109646222365262033737854466441553160299139874151345544060555572980249336846733721387494114433499021384759103856864087154066511739947461316277184688508736656643351154950168083887079604212529291597732445055805912583815500222964765625
c = 41405348264834004155980231506987237741080939152961658436177953795358672013903237175367548103505970706334327307237110222977753966399211501368475417631358331375005030300076478586213047732879710803232046846520582624126685566892150989783694565081820869966206280829504485919835618809474126374909534966769989******
p = gcd(x+y,n)
assert n % p == 0
q = n // p
e = 65537
phi = (p-1) * (q-1)
d = inverse(e,phi)
m = pow(c,d,n)
flag = long_to_bytes(m)
print(flag)

x是我随便乱打的,开头是1234567890的原因就是为了人工好判断是否一样)

21.png

0x13 普通的身份认证器

这题一眼就感觉是jwt令牌认证,burp抓个包之后看到了jwt格式,但是当时在选修课上,其实就是不想做web,最后就没写了,爬了

0x14 超精巧的数字论证器

是好题,就是有点臭

先说我的nt做法,写了个大法师爆搜三十分钟妄图打表,附近有成功表达出的数可以用-~x~-x进行表示,结果到了2k或者往上大面积的无解让我在第四轮四五轮就gg了

正解:如上 -~x=x+1,同理~-x=x-1,所以我们可以通过若干次+1操作来表示0~9内的任何数,显然题目中的数最多只会有六位,那么我们可以通过如下 xxxxxx = (((((0+a)*10+b)*10+c)*10+d)*10+e)*10+f​ 的方式来构造,其中0 10 10 10 10 10利用~-1 -~-~-~-~-~-~-~-~-~1 -~-~-~-~-~-~4 -~-~-~-~-~5 -~-~-~-~-~-~-~-~-~1 -~-~-~-~-~-~4表示,而a b c d e f使用~--~来表示,就能在规定的长度内成功完成数字论证,另外交互时间只有1min,用pwntools打应该会好一些,除非你手速足够快能2s算一个,这里贴一个官方的脚本,别问为什么不是我的,因为写的太丑了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pwn

def getans(number):
jz = 10
s = []
e = "114514"
for c in e[:1]:
s.append("~-" * (int(c)) + c)
for c in e[1:]:
s.append("-~" * (jz - int(c)) + c)
ans = ""
for i in range(len(e)):
digit = (number // (jz ** (len(e) - 1 - i))) % jz
ans = "(" + ans + "*" + s[i] + ")" if i > 0 else s[i]
ans = "-~" * digit + ans
return ans

conn = pwn.remote('202.38.93.111', 10241)
token = open('token', 'r').read()
conn.sendlineafter('Please input your token:', token)

for _ in range(32):
number = int(conn.recvuntil('=').decode('utf-8').split()[-2])
ans = getans(number)
conn.sendline(ans)
print(str(number) + ' = ' + ans + ' ' + conn.recvline().decode('utf-8').strip())

conn.interactive()

0x15 室友的加密硬盘

还没看,爬了

0x16 超简易的网盘服务器

还没看,爬了

0x17 超安全的代理服务器

还没看,爬了

0x18 证验码

还没看,爬了

0x19 动态链接库检查器

二进制,爬了

0x1a 超精准的宇宙射线模拟器

二进制,爬了

0x1b 超迷你的挖矿模拟器

听说有非预期?那我也不会

还没看,爬了

0x1c Flag 计算机

二进制,爬了

0x1d 中间人

还没看,爬了

0x1f 不经意传输

T1构造 $v=x_0$ ,则 $m_0’=m_0$ ,flag就有了

T2 还没看,爬了