Loading presentation...

Present Remotely

Send the link below via email or IM


Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.


Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

Linux Heap Exploiting Revisited (EN)

No description

Albert López

on 13 March 2013

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of Linux Heap Exploiting Revisited (EN)

Albert López
newlog@overflowedminds.net About the state of the art Heap exploiting Function pointers are stored in the heap Even more... ¿Why exploit the heap? Some theory... Data structures Memory area used for dynamic memory allocation. ¿What is the heap? Unlink - Back to the 90's Useful things you can find in the paper Linux Heap Exploiting Revisited Future ¿Why? The static analysis of binaries is more complex Malloc Des-Maleficarum (2009) Reviewing techniques from: Malloc Maleficarum (2005) Actual glibc version: 2.16 Maximum glibc version affected by those techniques 2.8 heap_info Arena Bins Memory chunks typedef struct _heap_info {
mstate ar_ptr; /* Arena for this heap. */
struct _heap_info *prev; /* Previous heap. */
size_t size; /* Current size in bytes. */
size_t mprotect_size; /* Size in bytes that has been mprotected
/* Make sure the following data is properly aligned, particularly
that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
char pad[-6 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info; File - arena.c:59 struct malloc_state {
/* Serialize access. */
mutex_t mutex;

/* Flags (formerly in max_fast). */
int flags;

/* Statistics for locking. Only used if
THREAD_STATS is defined. */
long stat_lock_direct, stat_lock_loop, stat_lock_wait;

/* Fastbins */
mfastbinptr fastbinsY[NFASTBINS];

/* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top;

/* The remainder from the most recent split of a small request */
mchunkptr last_remainder;

/* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2];

/* Bitmap of bins */
unsigned int binmap[BINMAPSIZE];

/* Linked list */
struct malloc_state *next;

/* Linked list for free arenas. */
struct malloc_state *next_free;

/* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
}; File - malloc.c:2362 struct malloc_chunk {
/* Size of previous chunk (if free). */
INTERNAL_SIZE_T prev_size;
/* Size in bytes, including overhead. */

/* double links -- used only if free. */
struct malloc_chunk* fd;
struct malloc_chunk* bk;

/* Only used for large blocks: pointer to next
larger size. */
/* double links -- used only if free. */
struct malloc_chunk* fd_nextsize;
struct malloc_chunk* bk_nextsize;
}; File - malloc.c:1809 Vulnerabilities These heap vulnerabilities are based on: 1 - A buffer overflow. 2 - Taking advantage of the algorithm used
when freeing a memory chunk. Malloc Maleficarum
House of Mind ¿What is unlink? ¿When is the unlink macro executed? Unlink is a macro used, in some cases, when a memory chunk is being freed. /* Take a chunk off a bin list */
#define unlink(P, BK, FD) { \
FD = P->fd; \
BK = P->bk; \
FD->bk = BK; \
BK->fd = FD; \
} File - malloc.c:1975 It takes out a memory chunk from the double linked list of bins. ( . . . )

/* consolidate backward */
if (!prev_inuse(p)) {
prevsize = p->prev_size;
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
unlink(p, bck, fwd);

if (nextchunk != av->top) {
/* get and clear inuse bit */
nextinuse = inuse_bit_at_offset(nextchunk, nextsize);

/* consolidate forward */
if (!nextinuse) {
unlink(nextchunk, bck, fwd);
size += nextsize;
} else
clear_inuse_bit_at_offset(nextchunk, 0);

( . . . ) File - malloc.c:4649 A picture is worth a thousand words Typical explanation, almost useless Let's propose a more 'real' case /* Take a chunk off a bin list */
#define unlink(P, BK, FD) { \
FD = P->fd; \
BK = P->bk; \
FD->bk = BK; \
BK->fd = FD; \
} Exploiting unlink p->prevsize equivalent to *p + 0 bytes
p->size equivalent to *p + 4 bytes
p->fd equivalent to *p + 8 bytes
p->bk equivalent to *p + 12 bytes FD = P->fd; equivalent to FD = *P + 8
BK = P->bk; equivalent to BK = *P + 12
FD->bk = BK; equivalent to FD + 12 = BK
BK->fd = FD; equivalent to BK + 8 = FD /* Take a chunk off a bin list */
#define unlink(P, BK, FD) { \
FD = P->fd; \
BK = P->bk; \
FD->bk = BK; \
BK->fd = FD; \
} ¿What if we could modify fd and bk pointers?
FD->bk = BK; /* Take a chunk off a bin list */
#define unlink(P, BK, FD) { \
FD = P->fd; \
BK = P->bk; \
FD->bk = BK; \
BK->fd = FD; \
} struct malloc_chunk {

INTERNAL_SIZE_T prev_size;

struct malloc_chunk* fd;
struct malloc_chunk* bk;
}; 1.- FD would point to a 'x' address. 2.- The 'x' + 12 address would be written with the address where BK is pointing. ¿Where will we make bk point? To the code we want to execute.
(A.K.A., shellcode) ¿How do we modify the pointers? As we have said, with a buffer overflow. With our payload we have to achieve: Demonstration Time to patch /* Take a chunk off a bin list */
#define unlink(P, BK, FD) { \
FD = P->fd; \
BK = P->bk; \
if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
malloc_printerr (check_action, "corrupted double-linked list", P); \
else { \
FD->bk = BK; \
BK->fd = FD; \
} \
} Satisfies the condition Doesn't satisfy the condition Timeline 1999,
unlink technique releases 2004,
unlink technique patched 2005,
Malloc Maleficarum released 2009,
patch for some Malloc Maleficarum techniques 5 years for the patch 4 years for the patch Summing up... bck = unsorted_chunks(av);
fwd = bck->fd;
p->bk = bck;
p->fd = fwd;
bck->fd = p;
fwd->bk = p; File - malloc.c:4338 /* The otherwise unindexable 1-bin is used to hold unsorted chunks. */
#define unsorted_chunks(M) (bin_at(M, 1)) General idea It returns the address of the first bin of the arena 'av' If we were able to control the contents of the arena, we would be able to control the address returned by unsorted_chunks() ¿How can we achieve it? bck->fd = p Standing on the shoulders of giants ¿How can we place heap_info structure in 0x08100000? If chunk p has the bit NON_MAIN_ARENA to 1: #define arena_for_chunk(ptr) \
(chunk_non_main_arena(ptr) ? heap_for_ptr(ptr)->ar_ptr : &main_arena) #define heap_for_ptr(ptr) \
((heap_info *)((unsigned long)(ptr) & ~(HEAP_MAX_SIZE-1))) ~( HEAP_MAX_SIZE - 1 ) = 111...11100000000000000000000 20 zeroes p Interesting data Patch for The House of Mind in glibc version 2.11 Patch bck = unsorted_chunks(av);
fwd = bck->fd;
if (__builtin_expect (fwd->bk != bck, 0))
errstr = "malloc(): corrupted unsorted chunks";
goto errout;
} Requirements for The House of Mind It must exist a buffer overflow.
Control content of two or more memory chunks.
Control the content of a memory chunk placed in address 0x08100000 (to store the fake heap_info structure).
Freeing a memory chunk placed in an address as 0x081xxxxx.
Knowing the address of a memory chunk P of which we could control its content. ¿But then... ? /* Take a chunk off a bin list */
#define unlink(P, BK, FD) { \
FD = P->fd; \
BK = P->bk; \
if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
malloc_printerr (check_action, "corrupted double-linked list", P); \
else { \
FD->bk = BK; \
BK->fd = FD; \
} \
} So knowing the address of P, ¿wouldn't it be possible to bypass unlink patch? Patch ¿Where does FD->bk point? To .dtors section ¿Can we control its contents? ¡Yes! ¿Where does BK->fd point? To the start of our shellcode + 8 bytes ¿Can we control its contents? ¡Yes! Demonstration Back to Unlink Development of an updated theoretical framework. Development of a method to bypass unlink patch Theoretical development of a bypass to the House of Mind patch. Development of two new payloads not previously published for the unlink exploitation. Some conclusions The security measures implemented in the algorithm are not enough. The problem is that control data and user data are adjacent. The security in the heap is based on external security measures such as ASLR. The End Thanks for your attention
¿Questions? ¿What is this about? malloc(), realloc() or free() interact with the heap. Used when the size of data is unknown. Future work Apply the methodologies used to bypass ASLR in order to exploit heap vulnerabilities. Search new attack vectors. Overwriting .dtors section in 2013 __do_global_dtors_aux() function
fortified It doesn't matter what readelf says, .dtors section is read only. Function pointers in .dtors section are not executed unless they are declared as destructors in source code. RELRO
(RELocation Read-Only) Thanks to In special to Wadalbertia In general to vlan7 y TuXeD And obviously to blackngel y Phantasmal Phantasmagoria See you in www.overflowedminds.net
Full transcript