LIEF
LIEF copied to clipboard
Heap-buffer-overflow in LIEF::DEX::Parser::parse_prototypes at DEX/Parser.tcc:292
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
- Build the whole project with ASAN
- 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;
}
- 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