LIEF icon indicating copy to clipboard operation
LIEF copied to clipboard

SEGV in LIEF::DEX::Parser::parse_methods at DEX/Parser.tcc:335

Open bladchan opened this issue 1 year ago • 0 comments

Describe the bug A bad DEX/VDEX file which can lead LIEF::DEX::Parser::parse()/LIEF::VDEX::Parser::parse() to segmentation fault.

Poc here : For DEX : dex_segv_2.zip For VDEX : vdex_segv_2.zip

To Reproduce

  1. Build the whole project with ASAN
  2. Drive programs (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;
}
// read_vdex.c
#include <LIEF/LIEF.hpp>

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

	return 0;
}
  1. Run Poc:
$ ./read_dex ./dex_segv_2.bin
$ ./read_vdex ./vdex_segv_2.bin

Expected behavior Parse the DEX/VDEX file without segmentation fault because segmentation fault can cause a Denial of Service (Dos).

Environment (please complete the following information):

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

Additional context For DEX poc, ASAN says:

$ ./read_dex ./dex_segv_2.bin
Different values for string offset between map and header
Different values for string size between map and header
...
Type Corrupted
String index for source filename corrupted
AddressSanitizer:DEADLYSIGNAL
=================================================================
==31462==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x557f7ba744b4 bp 0x0fffb35fc98a sp 0x7ffd9afe4bc0 T0)
==31462==The signal is caused by a READ memory access.
==31462==Hint: address points to the zero page.
    #0 0x557f7ba744b3 in std::__uniq_ptr_impl<LIEF::DEX::Method, std::default_delete<LIEF::DEX::Method> >::_M_ptr() const /usr/include/c++/9/bits/unique_ptr.h:154
    #1 0x557f7ba5a9e5 in std::unique_ptr<LIEF::DEX::Method, std::default_delete<LIEF::DEX::Method> >::get() const /usr/include/c++/9/bits/unique_ptr.h:361
    #2 0x557f7ba5a935 in std::unique_ptr<LIEF::DEX::Method, std::default_delete<LIEF::DEX::Method> >::operator->() const /usr/include/c++/9/bits/unique_ptr.h:355
    #3 0x557f7ba7a78d in void LIEF::DEX::Parser::parse_method<LIEF::DEX::details::DEX39>(unsigned long, LIEF::DEX::Class&, bool) /home/ubuntu/test/LIEF/src/DEX/Parser.tcc:620
    #4 0x557f7ba630a1 in void LIEF::DEX::Parser::parse_class_data<LIEF::DEX::details::DEX39>(unsigned int, LIEF::DEX::Class&) /home/ubuntu/test/LIEF/src/DEX/Parser.tcc:551
    #5 0x557f7ba4b91b in void LIEF::DEX::Parser::parse_classes<LIEF::DEX::details::DEX39>() /home/ubuntu/test/LIEF/src/DEX/Parser.tcc:463
    #6 0x557f7ba20b59 in void LIEF::DEX::Parser::parse_file<LIEF::DEX::details::DEX39>() /home/ubuntu/test/LIEF/src/DEX/Parser.tcc:45
    #7 0x557f7ba16e64 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:90
    #8 0x557f7ba16197 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
    #9 0x557f7b87f856 in main /home/ubuntu/test/LIEF/fuzz/read_dex.c:9
    #10 0x7f045b4be082 in __libc_start_main ../csu/libc-start.c:308
    #11 0x557f7b87f55d in _start (/home/ubuntu/test/LIEF/fuzz/read_dex+0x33055d)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /usr/include/c++/9/bits/unique_ptr.h:154 in std::__uniq_ptr_impl<LIEF::DEX::Method, std::default_delete<LIEF::DEX::Method> >::_M_ptr() const
==31462==ABORTING

For VDEX poc, ASAN says:

./read_vdex vdex_segv_2.bin 
String index for class name is corrupted
String index for class name is corrupted
...
String index for class name is corrupted
String index for class name is corrupted
AddressSanitizer:DEADLYSIGNAL
=================================================================
==31506==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f494cc9bc08 bp 0x0fffd79c1f7e sp 0x7ffebce0fbb8 T0)
==31506==The signal is caused by a READ memory access.
==31506==Hint: address points to the zero page.
    #0 0x7f494cc9bc07 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (/lib/x86_64-linux-gnu/libstdc++.so.6+0x145c07)
    #1 0x5585b22bff97 in void LIEF::DEX::Parser::parse_methods<LIEF::DEX::details::DEX37>() /home/ubuntu/test/LIEF/src/DEX/Parser.tcc:335
    #2 0x5585b22ad414 in void LIEF::DEX::Parser::parse_file<LIEF::DEX::details::DEX37>() /home/ubuntu/test/LIEF/src/DEX/Parser.tcc:44
    #3 0x5585b22a8e80 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:82
    #4 0x5585b22a856d in LIEF::DEX::Parser::parse(std::vector<unsigned char, std::allocator<unsigned char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/ubuntu/test/LIEF/src/DEX/Parser.cpp:52
    #5 0x5585b1f22f9d in void LIEF::VDEX::Parser::parse_dex_files<LIEF::VDEX::details::VDEX10>() /home/ubuntu/test/LIEF/src/VDEX/Parser.tcc:89
    #6 0x5585b1f18ebb in void LIEF::VDEX::Parser::parse_file<LIEF::VDEX::details::VDEX10>() (/home/ubuntu/test/LIEF/fuzz/read_vdex+0x4d5ebb)
    #7 0x5585b1f0eb28 in LIEF::VDEX::Parser::init(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int) /home/ubuntu/test/LIEF/src/VDEX/Parser.cpp:87
    #8 0x5585b1f0e78a in LIEF::VDEX::Parser::Parser(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/ubuntu/test/LIEF/src/VDEX/Parser.cpp:75
    #9 0x5585b1f0dab1 in LIEF::VDEX::Parser::parse(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/ubuntu/test/LIEF/src/VDEX/Parser.cpp:35
    #10 0x5585b1d73856 in main /home/ubuntu/test/LIEF/fuzz/read_vdex.c:10
    #11 0x7f494c81e082 in __libc_start_main ../csu/libc-start.c:308
    #12 0x5585b1d7355d in _start (/home/ubuntu/test/LIEF/fuzz/read_vdex+0x33055d)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libstdc++.so.6+0x145c07) in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
==31506==ABORTING

bladchan avatar Sep 16 '22 16:09 bladchan