写在前面
菜鸡第一次打CTF比赛写wp,没什么经验,写下博客记录一下,如果有错误还请各位师傅指出,欢迎交流讨论
Misc
Terminal Hacker

解压附件后得到HackMe.exe

双击打开exe文件,进入终端,按照步骤输入即可得到flag

flag{Cysay_terminal_game_hacked_successfully}
Crypto
dp
出题人说得对☝️🤓

根据题目和给出的信息可以知道是RSA中的dp泄露
已知n、dp、c、e
知识点
dp定义:dp = d mod (p-1),即私钥d在模数p-1下的余数。根据RSA密钥生成过程,e·d ≡ 1 mod φ(n)(φ(n)=(p-1)(q-1))
当dp泄露时,存在整数k使得 e·dp ≡ 1 + k(p-1)。通过遍历k值可解出p的候选值,并验证是否整除n以确定真正的p
通过以下代码快速定位p:
p = gmpy2.gcd(pow(2, e*dp, n) - 2, n)
#pow(2, e*dp, n) - 2是p的倍数,与n求最大公约数可直接得到p
通过以上方法得到p后通过q = n // p得到q,完成模数n的分解
解密过程
-
计算欧拉函数:
phi_n = (p-1)(q-1) -
求私钥d:
d = gmpy2.invert(e, phi_n) #即解e·d ≡ 1 mod phi_n -
解密明文:
m = pow(c, d, n) flag = libnum.n2s(int(m)) #并使用libnum转为字节
拿出我珍藏多年的脚本献上
import gmpy2
import libnum
n= 110231451148882079381796143358970452100202953702391108796134950841737642949460527878714265898036116331356438846901198470479054762675790266666921561175879745335346704648242558094026330525194100460497557690574823790674495407503937159099381516207615786485815588440939371996099127648410831094531405905724333332751
e= 65537
c= 59325046548488308883386075244531371583402390744927996480498220618691766045737849650329706821216622090853171635701444247741920578127703036446381752396125610456124290112692914728856924559989383692987222821742728733347723840032917282464481629726528696226995176072605314263644914703785378425284460609365608120126
dp= 3086447084488829312768217706085402222803155373133262724515307236287352098952292947424429554074367555883852997440538764377662477589192987750154075762783925
p=gmpy2.gcd(pow(2,e*dp,n)-2,n)
print(p)
q = n // p
phi_n = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi_n)
m = pow(c, d, n)
print(m)
flag = libnum.n2s(int(m))
print(flag)
flag{C5G0_1s_the_8eSt_FPS_G@m3}
Valorant_1s_the_8eSt_FPS_G@me
easy_rsa
又是rsa,打开附件txt
e = 65537
n = 1000000000000000000000000000156000000000000000000000000005643
c = 418535905348643941073541505434424306523376401168593325605206
分享一个工具终于不用写脚本了,将内容输入进去

右键分解模数,填入n,调用yafu.exe就可以解出来p和q

将p、q填入,逗号分隔

右键,计算私钥d,然后再计算明文,再右键,明文转字符即可得到flag

还是附上python脚本吧
import gmpy2
import binascii
# 已知的 RSA 参数
e = 65537
n = 1000000000000000000000000000156000000000000000000000000005643
c = 418535905348643941073541505434424306523376401168593325605206
# 费马因数分解法
def fermat_factorization(n):
a = gmpy2.isqrt(n) # 计算 n 的整数平方根
while True:
b2 = a * a - n
if b2 >= 0 and gmpy2.is_square(b2): # 检查 b2 是否是完全平方数
b = gmpy2.isqrt(b2)
p = a + b
q = a - b
return int(p), int(q)
a += 1
# 分解 n
p, q = fermat_factorization(n)
print("找到的因数 p 和 q:", p, q)
# 计算私钥 d
phi_n = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi_n)
# 解密密文 c
m = gmpy2.powmod(c, d, n)
# 将明文转换为字符串
try:
flag = binascii.unhexlify(hex(m)[2:]).decode('utf-8')
print("解密后的明文:", flag)
except Exception as e:
print("解密后的明文可能不是十六进制字符串,直接输出明文数字:", m)
简单编码
题目描述:简简单单的编码
打开附件,看到全是A和B,还7个或者6个连在一起,空格隔开
ABBAABB ABBABAB ABABAAA ABABAAB ABBBBAA ABBAABA ABABBAA ABBAAAA ABBAAAB ABBABAB ABBBAAA ABAABBB ABABBAA ABABABB ABABBAA ABBABBB ABBABAA ABABABA ABAABAB ABBBAAA ABBBABA ABABBAB ABBBBAA ABABBAB ABBBAAA ABBABAB ABBAABA ABABAAA ABABABA AABBAB ABBBABB ABBAABA ABBABAB AABABA ABBBBAA ABBBAAB ABBAABA AABBAB ABABBAA ABBAAAB ABBBAAA ABBABAB ABBABAA ABABABB ABBBABA ABABABB ABBAABB ABBABAA ABBABAB ABBABAB ABABAAA ABBBABA AABABB ABABBAB AABBAB ABABAAA ABBAAAB ABBBBAB ABBBAAA ABABABA ABBAAAA ABABAAB ABABABB ABBABBA ABBABAB AABABA ABBABAA ABBBABA ABBBABA AABBAA ABBBBAA ABBAAAA ABABBBB ABBABAB ABABABB ABAABBB ABBAAAA ABABAAA ABABABB ABBABAA ABBABBA ABABABA ABAABAB ABABABA AABABB ABABBAB ABBBBAA ABBBBAB ABBBAAA ABABAAB ABBABBB ABABAAB ABBAAAA ABAABAB ABBBABB ABBABAA ABBABAB ABABABA ABAABAB ABBBABA ABBAABA AABBAB ABABBAA ABAABAB ABBBAAA ABBABAB ABBBABA ABAABBB ABABBBA ABABABB ABABBAA ABBABBB ABBABAA ABAABAB ABABABA ABBBAAB ABABBAA ABBAABA ABABBAA ABAABAB ABBBAAA ABBABAB ABBABBB ABBBABB ABBBABA ABABBAA ABBABAB ABABABA ABBAABA ABAABAB ABBAABA ABBABBB ABBBAAA ABBAABA ABBBBAA ABBAAAA ABBABAA ABABBAB ABBABAA ABAABBB ABABABA ABABABB ABABABB AABBAB ABBAAAB ABBBBAB ABABABA ABBBABA AABBAB ABABABA ABBABAB ABBBAAB ABBBAAA ABBAAAB ABBBBAA ABBBBAA ABBABAA ABBAABA AABBAB ABBBABA
只有A和B,所以想到二进制,观察看出每一串都是A开头,所以猜测A是1,B是0,将其全部替换后得到
1001100 1001010 1010111 1010110 1000011 1001101 1010011 1001111 1001110 1001010 1000111 1011000 1010011 1010100 1010011 1001000 1001011 1010101 1011010 1000111 1000101 1010010 1000011 1010010 1000111 1001010 1001101 1010111 1010101 110010 1000100 1001101 1001010 110101 1000011 1000110 1001101 110010 1010011 1001110 1000111 1001010 1001011 1010100 1000101 1010100 1001100 1001011 1001010 1001010 1010111 1000101 110100 1010010 110010 1010111 1001110 1000010 1000111 1010101 1001111 1010110 1010100 1001001 1001010 110101 1001011 1000101 1000101 110011 1000011 1001111 1010000 1001010 1010100 1011000 1001111 1010111 1010100 1001011 1001001 1010101 1011010 1010101 110100 1010010 1000011 1000010 1000111 1010110 1001000 1010110 1001111 1011010 1000100 1001011 1001010 1010101 1011010 1000101 1001101 110010 1010011 1011010 1000111 1001010 1000101 1011000 1010001 1010100 1010011 1001000 1001011 1011010 1010101 1000110 1010011 1001101 1010011 1011010 1000111 1001010 1001000 1000100 1000101 1010011 1001010 1010101 1001101 1011010 1001101 1001000 1000111 1001101 1000011 1001111 1001011 1010010 1001011 1011000 1010101 1010100 1010100 110010 1001110 1000010 1010101 1000101 110010 1010101 1001010 1000110 1000111 1001110 1000011 1000011 1001011 1001101 110010 1000101
将以上二进制串转换成字符
得到
LJWVCMSONJGXSTSHKUZGERCRGJMWU2DMJ5CFM2SNGJKTETLKJJWE4R2WNBGUOVTIJ5KEE3COPJTXOWTKIUZU4RCBGVHVOZDKJUZEM2SZGJEXQTSHKZUFSMSZGJHDESJUMZMHGMCOKRKXUTT2NBUE2UJFGNCCKM2E
看起来像base编码
base64试了发现不是,试了下base32,看起来没问题
ZmQ2NjMyNGU2bDQ2YjhlODVjM2U2MjJlNGVhMGVhOTBlNzgwZjE3NDA5OWdjM2FjY2IxNGVhY2Y2N2I4fXs0NTUzNzhhMQ%3D%3D
后面的%3D%3D是url编码,解码后就是==,这下能看出来了,就是base64,接下来都很明显了,直接再解一下,得到
fd66324e6l46b8e85c3e622e4ea0ea90e780f174099gc3accb14eacf67b8}{455378a1
一看就是栅栏密码,一对{},也有flag字母,试了几次,发现栏数是5,得到flag
以下是在CyberChef解码过程

flag{c04d6e34aab689c5c0e68eb51753c843e032efa7c16427f8642ee07ab946e981}
Web
ezjs
打开网站是个跳跳乐,小游戏类,F12打开,查看源码js,发现main.js中有一段
game._addSuccessFn(function (scoreNow) {
current_score.innerHTML = scoreNow
if (scoreNow === 100000000000) {
fetch('getflag.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'score=' + scoreNow
})
.then(response => response.text())
.then(data => {
alert("恭喜你!flag是:" + data);
})
.catch(error => {
console.error('错误:', error);
});
}
})
解法一
就想到直接在控制台修改score
game.score = 100000000000;
发现不行,再去查看game.js,发现还需要触发这个回调函数

所以直接控制台输入,弹窗得到flag
game.successCallback(100000000000);
解法二
直接在控制台发生fetch请求,将fetch内的body修改即可
fetch('getflag.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'score=100000000000'
})
.then(response => response.text())
.then(data => alert(data))
弹窗得到flag
ezssrf1.0
题目说是ssrf,打开后显示
<?php
error_reporting(0);
highlight_file(__FILE__);
$url = $_GET['url'];
if ($url == null)
die("Try to add ?url=xxxx.");
$x = parse_url($url);
if (!$x)
die("(;_;)");
if ($x['host'] === null && $x['scheme'] === 'http') {
echo ('Well, Going to ' . $url);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
echo ($result);
} else
echo "(^-_-^)";
Try to add ?url=xxxx.
代码审计
让我们传入一个url参数
$x = parse_url($url);
这句使用 parse_url() 函数解析 $url,将其拆分为 scheme、host、path 等部分,结果保存在数组 $x 中
主要关注这句
if ($x['host'] === null && $x['scheme'] === 'http')
判断解析后的 URL 是否满足两个条件:
没有 host(即主机名或 IP 地址)
协议是 http
当parse_url遇到格式不完整的URL时,可能无法正确解析host字段,导致其返回null,而curl等请求工具仍能正常处理该URL。
所以我们只需要构造一个特殊的url绕过
?url=http:/@127.0.0.1/flag.php
单斜杠或特殊符号可能导致host字段被忽略

得到路径,修改payload
http://27.25.151.26:30143/?url=http:/@127.0.0.1/FFFFF11111AAAAAggggg.php
得到flag

2542

被折叠的 条评论
为什么被折叠?



