Skip to content

Commit

Permalink
Fix DoS in PE/QNX/DYLDCACHE/PSX parsers ##crash
Browse files Browse the repository at this point in the history
* Reported by lazymio
* Reproducer: AAA4AAAAAB4=
  • Loading branch information
radare authored and trufae committed Feb 24, 2022
1 parent 333e991 commit 634b886
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 24 deletions.
18 changes: 8 additions & 10 deletions libr/bin/format/pe/pe.c
@@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2008-2021 nibble, pancake, inisider */
/* radare - LGPL - Copyright 2008-2022 nibble, pancake, inisider */

#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -278,15 +278,13 @@ struct r_bin_pe_addr_t *PE_(check_msvcseh)(RBinPEObj *pe) {
}

struct r_bin_pe_addr_t *PE_(check_mingw)(RBinPEObj *pe) {
struct r_bin_pe_addr_t* entry;
bool sw = false;
ut8 b[1024];
ut8 b[1024] = {0};
size_t n = 0;
if (!pe || !pe->b) {
return 0LL;
}
entry = PE_(r_bin_pe_get_entrypoint) (pe);
ZERO_FILL (b);
struct r_bin_pe_addr_t* entry = PE_(r_bin_pe_get_entrypoint) (pe);
if (r_buf_read_at (pe->b, entry->paddr, b, sizeof (b)) < 0) {
pe_printf ("Warning: Cannot read entry at 0x%08"PFMT64x "\n", entry->paddr);
free (entry);
Expand Down Expand Up @@ -339,11 +337,11 @@ struct r_bin_pe_addr_t *PE_(check_unknow)(RBinPEObj *pe) {
if (!pe || !pe->b) {
return 0LL;
}
ut8 b[512];
ut8 b[512] = {0};
ZERO_FILL (b);
entry = PE_ (r_bin_pe_get_entrypoint) (pe);
// option2: /x 8bff558bec83ec20
if (r_buf_read_at (pe->b, entry->paddr, b, 512) < 1) {
if (r_buf_read_at (pe->b, entry->paddr, b, sizeof (b)) != sizeof (b)) {
pe_printf ("Warning: Cannot read entry at 0x%08"PFMT64x"\n", entry->paddr);
free (entry);
return NULL;
Expand Down Expand Up @@ -537,7 +535,8 @@ static int bin_pe_parse_imports(RBinPEObj* pe,
if (len < 1) {
pe_printf ("Warning: read (import name)\n");
goto error;
} else if (!*name) {
}
if (!*name) {
break;
}
name[PE_NAME_LENGTH] = '\0';
Expand Down Expand Up @@ -1258,7 +1257,6 @@ static bool bin_pe_init_metadata_hdr(RBinPEObj* pe) {
// read the header after the string
rr = r_buf_fread_at (pe->b, metadata_directory + 16 + metadata->VersionStringLength,
(ut8*) (&metadata->Flags), pe->big_endian? "2S": "2s", 1);

if (rr < 1) {
goto fail;
}
Expand Down Expand Up @@ -1820,7 +1818,7 @@ static Var* Pe_r_bin_pe_parse_var(RBinPEObj* pe, PE_DWord* curAddr) {
free_Var (var);
return NULL;
}
if (r_buf_read_at (pe->b, *curAddr, (ut8*) var->szKey, TRANSLATION_UTF_16_LEN) < 1) {
if (r_buf_read_at (pe->b, *curAddr, (ut8*) var->szKey, TRANSLATION_UTF_16_LEN) != TRANSLATION_UTF_16_LEN) {
pe_printf ("Warning: read (Var szKey)\n");
free_Var (var);
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion libr/bin/p/bin_dyldcache.c
Expand Up @@ -587,7 +587,7 @@ static ut64 estimate_slide(RBinFile *bf, RDyldCache *cache, ut64 value_mask, ut6
int n_classes = classlist_sample_size / 8;
ut64 sect_offset = sections[classlist_idx].offset + bin->hdr_offset;

if (r_buf_fread_at (cache->buf, sect_offset, (ut8*) classlist, "l", n_classes) < classlist_sample_size) {
if (r_buf_fread_at (cache->buf, sect_offset, (ut8*) classlist, "l", n_classes) != classlist_sample_size) {
goto next_bin;
}

Expand Down
4 changes: 2 additions & 2 deletions libr/bin/p/bin_psxexe.c
Expand Up @@ -57,7 +57,7 @@ static RList* sections(RBinFile* bf) {
return NULL;
}

if (r_buf_fread_at (bf->buf, 0, (ut8*)&psxheader, "8c17i", 1) < sizeof (psxexe_header)) {
if (r_buf_fread_at (bf->buf, 0, (ut8*)&psxheader, "8c17i", 1) != sizeof (psxexe_header)) {
eprintf ("Truncated Header\n");
free (sect);
r_list_free (ret);
Expand Down Expand Up @@ -93,7 +93,7 @@ static RList* entries(RBinFile* bf) {
return NULL;
}

if (r_buf_fread_at (bf->buf, 0, (ut8*)&psxheader, "8c17i", 1) < sizeof (psxexe_header)) {
if (r_buf_fread_at (bf->buf, 0, (ut8*)&psxheader, "8c17i", 1) != sizeof (psxexe_header)) {
eprintf ("PSXEXE Header truncated\n");
r_list_free (ret);
free (addr);
Expand Down
14 changes: 7 additions & 7 deletions libr/bin/p/bin_qnx.c
Expand Up @@ -7,7 +7,7 @@ static int lmf_header_load(lmf_header *lmfh, RBuffer *buf, Sdb *db) {
if (r_buf_size (buf) < sizeof (lmf_header)) {
return false;
}
if (r_buf_fread_at (buf, QNX_HEADER_ADDR, (ut8 *) lmfh, "iiiiiiiicccciiiicc", 1) < QNX_HDR_SIZE) {
if (r_buf_fread_at (buf, QNX_HEADER_ADDR, (ut8 *) lmfh, "iiiiiiiicccciiiicc", 1) != QNX_HDR_SIZE) {
return false;
}
r_strf_buffer (32);
Expand Down Expand Up @@ -64,15 +64,15 @@ static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadadd
goto beach;
}
// Read the first record
if (r_buf_fread_at (bf->buf, 0, (ut8 *)&lrec, "ccss", 1) < QNX_RECORD_SIZE) {
if (r_buf_fread_at (bf->buf, 0, (ut8 *)&lrec, "ccss", 1) != QNX_RECORD_SIZE) {
goto beach;
}
// Load the header
lmf_header_load (&qo->lmfh, bf->buf, qo->kv);
offset += lrec.data_nbytes;

for (;;) {
if (r_buf_fread_at (bf->buf, offset, (ut8 *)&lrec, "ccss", 1) < QNX_RECORD_SIZE) {
if (r_buf_fread_at (bf->buf, offset, (ut8 *)&lrec, "ccss", 1) != QNX_RECORD_SIZE) {
goto beach;
}
offset += sizeof (lmf_record);
Expand All @@ -84,7 +84,7 @@ static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadadd
if (!ptr) {
goto beach;
}
if (r_buf_fread_at (bf->buf, offset, (ut8 *)&lres, "ssss", 1) < sizeof (lmf_resource)) {
if (r_buf_fread_at (bf->buf, offset, (ut8 *)&lres, "ssss", 1) != sizeof (lmf_resource)) {
goto beach;
}
ptr->name = strdup ("LMF_RESOURCE");
Expand All @@ -95,7 +95,7 @@ static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadadd
r_list_append (sections, ptr);
} else if (lrec.rec_type == LMF_LOAD_REC) {
RBinSection *ptr = R_NEW0 (RBinSection);
if (r_buf_fread_at (bf->buf, offset, (ut8 *)&ldata, "si", 1) < sizeof (lmf_data)) {
if (r_buf_fread_at (bf->buf, offset, (ut8 *)&ldata, "si", 1) != sizeof (lmf_data)) {
goto beach;
}
if (!ptr) {
Expand All @@ -110,15 +110,15 @@ static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadadd
r_list_append (sections, ptr);
} else if (lrec.rec_type == LMF_FIXUP_REC) {
RBinReloc *ptr = R_NEW0 (RBinReloc);
if (!ptr || r_buf_fread_at (bf->buf, offset, (ut8 *)&ldata, "si", 1) < sizeof (lmf_data)) {
if (!ptr || r_buf_fread_at (bf->buf, offset, (ut8 *)&ldata, "si", 1) != sizeof (lmf_data)) {
goto beach;
}
ptr->vaddr = ptr->paddr = ldata.offset;
ptr->type = 'f'; // "LMF_FIXUP";
r_list_append (fixups, ptr);
} else if (lrec.rec_type == LMF_8087_FIXUP_REC) {
RBinReloc *ptr = R_NEW0 (RBinReloc);
if (!ptr || r_buf_fread_at (bf->buf, offset, (ut8 *)&ldata, "si", 1) < sizeof (lmf_data)) {
if (!ptr || r_buf_fread_at (bf->buf, offset, (ut8 *)&ldata, "si", 1) != sizeof (lmf_data)) {
goto beach;
}
ptr->vaddr = ptr->paddr = ldata.offset;
Expand Down
6 changes: 2 additions & 4 deletions libr/util/buf.c
Expand Up @@ -516,10 +516,9 @@ static st64 buf_format(RBuffer *dst, RBuffer *src, const char *fmt, int n) {
ut32 d3;
ut64 d4;
st64 r = r_buf_read (src, tmp, tsize);
if (r < tsize) {
if (r != tsize) {
return -1;
}

switch (tsize) {
case 1:
d1 = r_read_ble8 (tmp);
Expand Down Expand Up @@ -566,7 +565,7 @@ R_API st64 r_buf_fread_at(RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int
return r;
}
r = r_buf_fread (b, buf, fmt, n);
r_buf_seek (b, o_addr, R_BUF_SET);
(void)r_buf_seek (b, o_addr, R_BUF_SET);
return r;
}

Expand Down Expand Up @@ -598,7 +597,6 @@ R_API st64 r_buf_read_at(RBuffer *b, ut64 addr, ut8 *buf, ut64 len) {
if (r < 0) {
return r;
}

r = r_buf_read (b, buf, len);
r_buf_seek (b, o_addr, R_BUF_SET);
return r;
Expand Down

0 comments on commit 634b886

Please sign in to comment.