hugsy / gef

GEF (GDB Enhanced Features) - a modern experience for GDB with advanced debugging capabilities for exploit devs & reverse engineers on Linux
https://hugsy.github.io/gef
MIT License
6.82k stars 721 forks source link

Possible caching issue when reading heap metadata #386

Closed ghost closed 5 years ago

ghost commented 5 years ago

Your issue will be closed unless you confirm the following:

Step 1: Describe your environment

:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.5 LTS"

:~$ uname -a
Linux sxs101 3.19.0-80-generic #88~14.04.1-Ubuntu SMP Fri Jan 13 14:55:00 UTC 2017 i686 i686 i686 GNU/Linux

:~$ ldd --version
ldd (Ubuntu EGLIBC 2.19-0ubuntu6.14) 2.19

GDB 7.7.1 using Python engine 3.4

Step 2: Describe your problem

I observed this issue while doing the house_of_lore exercise from how2heap

After the call to free() at main+633 I see the following:

    0x80487ec <main+625>       dec    DWORD PTR [ebx-0x76e3dbbc]
    0x80487f2 <main+631>       add    al, 0x24
    0x80487f4 <main+633>       call   0x80483d0 <free@plt>
 →  0x80487f9 <main+638>       mov    eax, ds:0x804b038
    0x80487fe <main+643>       mov    DWORD PTR [esp+0xc], eax
    0x8048802 <main+647>       mov    DWORD PTR [esp+0x8], 0x3e
    0x804880a <main+655>       mov    DWORD PTR [esp+0x4], 0x1
    0x8048812 <main+663>       mov    DWORD PTR [esp], 0x8048f70
    0x8048819 <main+670>       call   0x80483f0 <fwrite@plt>
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "house_of_lore", stopped, reason: BREAKPOINT
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x80487f9 → main()
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  heap bins
[+] No Tcache in this version of libc
─────────────────────────────────────────────────────────────────────────────── Fastbins for arena 0xb7fbf420 ───────────────────────────────────────────────────────────────────────────────
Fastbins[idx=0, size=0x8] 0x00
Fastbins[idx=1, size=0x10] 0x00
Fastbins[idx=2, size=0x18] 0x00
Fastbins[idx=3, size=0x20] 0x00
Fastbins[idx=4, size=0x28] 0x00
Fastbins[idx=5, size=0x30] 0x00
Fastbins[idx=6, size=0x38] 0x00
──────────────────────────────────────────────────────────────────────────── Unsorted Bin for arena 'main_arena' ────────────────────────────────────────────────────────────────────────────
[+] unsorted_bins[0]: fw=0x804c000, bk=0x804c000
 →   Chunk(addr=0x804c008, size=0x68, flags=PREV_INUSE)
[+] Found 1 chunks in unsorted bin.
───────────────────────────────────────────────────────────────────────────── Small Bins for arena 'main_arena' ─────────────────────────────────────────────────────────────────────────────
[+] Found 0 chunks in 0 small non-empty bins.
───────────────────────────────────────────────────────────────────────────── Large Bins for arena 'main_arena' ─────────────────────────────────────────────────────────────────────────────
[+] Found 0 chunks in 0 large non-empty bins.
gef➤  x/16xw 0x804c000
0x804c000:      0x00000000      0x00000069      0xb7fbf450      0xb7fbf450
0x804c010:      0x00000000      0x00000000      0x00000000      0x00000000
0x804c020:      0x00000000      0x00000000      0x00000000      0x00000000
0x804c030:      0x00000000      0x00000000      0x00000000      0x00000000
gef➤  x/xw 0xb7fbf450
0xb7fbf450 <main_arena+48>:     0x0804c458

There is one freed chunk at 0x804c008 with fd and bk pointers pointing to the top of the heap at 0x804c000

However, when dumping the memory at this address, I see the fd and bk pointers showing 0xb7fbf450

Upon examining this address, I see it derefs to 0x0804c458

@Grazfather suggested this might be a caching problem and for me to open this issue.

Grazfather commented 5 years ago

Which version of how to heap, which version of libc? Why is it compiled for 32 bit?

ghost commented 5 years ago
  1. The source code to the binary: https://raw.githubusercontent.com/shellphish/how2heap/master/glibc_2.26/house_of_lore.c

  2. glibc version is 2.19

  3. The binary was compiled for a 32-bit environment because the source code indicates it was tested in a 32-bit environment:

  fprintf(stderr, "This is tested against Ubuntu 14.04.4 - 32bit - glibc-2.23\n\n");
Grazfather commented 5 years ago

Hi @bin4ryD3struct0r

That fd and bk is not from the chunk, but from the bin.

gef➤  p main_arena.bins[0]
$3 = (mchunkptr) 0x804c000
gef➤  heap chunk 0x804c008
Chunk(addr=0x804c008, size=0x68, flags=PREV_INUSE)
Chunk size: 104 (0x68)
Usable size: 100 (0x64)
Previous chunk size: 0 (0x0)
PREV_INUSE flag: On
IS_MMAPPED flag: Off
NON_MAIN_ARENA flag: Off

Forward pointer: 0xf7fc77b0
Backward pointer: 0xf7fc77b0

gef➤  x/4wx 0x804c000
0x804c000:      0x00000000      0x00000069      0xf7fc77b0      0xf7fc77b0
gef➤  p main_arena.bins
$20 = {0x804c000, 0x804c000, 0xf7fc77b8 <main_arena+56>, ...

So you were mistaking a chunk for a bin slot, which is just an array of pointers to malloc chunks.