CVE-2018-14016: Out-of-bounds Read (CWE-125)
value: The r_bin_mdmp_init_directory_entry function in mdmp.c in radare2 2.7.0 allows remote attackers to cause a denial of service (heap-based buffer over-read and application crash) via a crafted Mini Crash Dump file.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 5.5
Published: 2018-07-12T20:29Z
Repository: https://github.com/radareorg/radare2
Language: C
Files changed: libr/bin/format/mdmp/mdmp.c
Commit date: 2018-07-09 13:55:45 +0200
Commit message: Fix #10464 - oobread crash in mdmp (#10683)


Diff: diff --git a/libr/bin/format/mdmp/mdmp.c b/libr/bin/format/mdmp/mdmp.c
index c3d66dd85f..d23cabf85b 100644
--- a/libr/bin/format/mdmp/mdmp.c
+++ b/libr/bin/format/mdmp/mdmp.c
@@ -360,11 +360,11 @@ static bool r_bin_mdmp_init_directory_entry(struct r_bin_mdmp_obj *obj, struct m
 	struct minidump_unloaded_module *unloaded_modules;
 
 	/* We could confirm data sizes but a malcious MDMP will always get around
 	** this! But we can ensure that the data is not outside of the file */
 	if (entry->location.rva + entry->location.data_size > obj->b->length) {
-		eprintf("[ERROR] Size Mismatch - Stream data is larger than file size!\n");
+		eprintf ("[ERROR] Size Mismatch - Stream data is larger than file size!\n");
 		return false;
 	}
 
 	switch (entry->stream_type) {
 	case THREAD_LIST_STREAM:
@@ -644,25 +644,26 @@ static bool r_bin_mdmp_init_directory_entry(struct r_bin_mdmp_obj *obj, struct m
 	return true;
 }
 
 static bool r_bin_mdmp_init_directory(struct r_bin_mdmp_obj *obj) {
 	int i;
-	ut8 *directory_base;
-	struct minidump_directory *entry;
-
-	directory_base = obj->b->buf + obj->hdr->stream_directory_rva;
+	struct minidump_directory entry;
 
 	sdb_num_set (obj->kv, "mdmp_directory.offset",
 			obj->hdr->stream_directory_rva, 0);
 	sdb_set (obj->kv, "mdmp_directory.format", "[4]E? "
 			"(mdmp_stream_type)StreamType "
 			"(mdmp_location_descriptor)Location", 0);
 
 	/* Parse each entry in the directory */
+	ut64 rvadir = obj->hdr->stream_directory_rva;
 	for (i = 0; i < (int)obj->hdr->number_of_streams; i++) {
-		entry = (struct minidump_directory *)(directory_base + (i * sizeof (struct minidump_directory)));
-		r_bin_mdmp_init_directory_entry (obj, entry);
+		ut32 delta = i * sizeof (struct minidump_directory);
+		int r = r_buf_read_at (obj->b, rvadir + delta, (ut8*) &entry, sizeof (struct minidump_directory));
+		if (r) {
+			r_bin_mdmp_init_directory_entry (obj, &entry);
+		}
 	}
 
 	return true;
 }
 

Vulnerable code: 		eprintf("[ERROR] Size Mismatch - Stream data is larger than file size!\n");
	ut8 *directory_base;
	struct minidump_directory *entry;

	directory_base = obj->b->buf + obj->hdr->stream_directory_rva;
		entry = (struct minidump_directory *)(directory_base + (i * sizeof (struct minidump_directory)));
		r_bin_mdmp_init_directory_entry (obj, entry);
Fixed code: 		eprintf ("[ERROR] Size Mismatch - Stream data is larger than file size!\n");
	struct minidump_directory entry;
	ut64 rvadir = obj->hdr->stream_directory_rva;
		ut32 delta = i * sizeof (struct minidump_directory);
		int r = r_buf_read_at (obj->b, rvadir + delta, (ut8*) &entry, sizeof (struct minidump_directory));
		if (r) {
			r_bin_mdmp_init_directory_entry (obj, &entry);
		}