LIEF icon indicating copy to clipboard operation
LIEF copied to clipboard

Heap-buffer-overflow in LIEF::DEX::Parser::parse_prototypes at DEX/Parser.tcc:292

Open bladchan opened this issue 1 year ago • 0 comments

Describe the bug A bad DEX file which can lead LIEF::DEX::Parser::parse to a heap-buffer-overflow(read) issue.

Poc here: dex_buffer_overflow_3.zip

To Reproduce

  1. Build the whole project with ASAN
  2. Drive program (compile it with ASAN too):
// read_dex.c
#include <LIEF/LIEF.hpp>

int main(int argc, char** argv){
	
	if(argc != 2) return 0;
	
	// DEX
	try {
	    std::unique_ptr<LIEF::DEX::File> dex = LIEF::DEX::Parser::parse(argv[1]);
	    if(dex) std::cout << *dex << std::endl;
	} catch (const LIEF::exception& err) {
	    std::cerr << err.what() << std::endl;
	}

	return 0;
}
  1. Run Poc:
$ ./read_dex ./dex_buffer_overflow_3.bin

Expected behavior The code snippet where the issue happened should avoid the out-bounds read operation.

Environment (please complete the following information):

  • System and Version : Ubuntu 20.04 + gcc 9.4.0
  • Target format : DEX
  • LIEF commit version: https://github.com/lief-project/LIEF/commit/24935f654f6df700a9a062298258b9485f584502

Additional context ASAN says:

$ ./read_dex dex_buffer_overflow_3.bin
Unknown type: ''
String index for class name is corrupted
String index for class name is corrupted
Type #13312 out of bound (1)
=================================================================
==30285==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000000d8 at pc 0x5559555c966a bp 0x7ffea4243010 sp 0x7ffea4243000
READ of size 8 at 0x6020000000d8 thread T0
    #0 0x5559555c9669 in std::__uniq_ptr_impl<LIEF::DEX::Type, std::default_delete<LIEF::DEX::Type> >::_M_ptr() const /usr/include/c++/9/bits/unique_ptr.h:154
    #1 0x5559555b25cd in std::unique_ptr<LIEF::DEX::Type, std::default_delete<LIEF::DEX::Type> >::get() const /usr/include/c++/9/bits/unique_ptr.h:361
    #2 0x555955586e8c in void LIEF::DEX::Parser::parse_prototypes<LIEF::DEX::details::DEX35>() /home/ubuntu/test/LIEF/src/DEX/Parser.tcc:292
    #3 0x55595557b7c7 in void LIEF::DEX::Parser::parse_file<LIEF::DEX::details::DEX35>() /home/ubuntu/test/LIEF/src/DEX/Parser.tcc:43
    #4 0x555955571dad in LIEF::DEX::Parser::init(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int) /home/ubuntu/test/LIEF/src/DEX/Parser.cpp:78
    #5 0x555955571197 in LIEF::DEX::Parser::parse(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/ubuntu/test/LIEF/src/DEX/Parser.cpp:40
    #6 0x5559553da856 in main /home/ubuntu/test/LIEF/fuzz/read_dex.c:9
    #7 0x7f66d8179082 in __libc_start_main ../csu/libc-start.c:308
    #8 0x5559553da55d in _start (/home/ubuntu/test/LIEF/fuzz/read_dex+0x33055d)

0x6020000000d8 is located 0 bytes to the right of 8-byte region [0x6020000000d0,0x6020000000d8)
allocated by thread T0 here:
    #0 0x7f66d87a2587 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cc:104
    #1 0x55595560eee8 in __gnu_cxx::new_allocator<std::unique_ptr<LIEF::DEX::Type, std::default_delete<LIEF::DEX::Type> > >::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
    #2 0xfffd4848617  (<unknown module>)
    #3 0x55595699a027  (/home/ubuntu/test/LIEF/fuzz/read_dex+0x18f0027)

SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/include/c++/9/bits/unique_ptr.h:154 in std::__uniq_ptr_impl<LIEF::DEX::Type, std::default_delete<LIEF::DEX::Type> >::_M_ptr() const
Shadow bytes around the buggy address:
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff8000: fa fa 00 00 fa fa fd fa fa fa 00 00 fa fa 00 fa
=>0x0c047fff8010: fa fa fd fa fa fa 00 fa fa fa 00[fa]fa fa 00 fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==30285==ABORTING

bladchan avatar Sep 16 '22 15:09 bladchan