[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug binutils/21440] New: Malicious PE with invalid extended relocation
From: |
jgj212 at gmail dot com |
Subject: |
[Bug binutils/21440] New: Malicious PE with invalid extended relocation can cause binutils/objdumo 2.28 to allocate any-size big memory |
Date: |
Thu, 27 Apr 2017 06:10:21 +0000 |
https://sourceware.org/bugzilla/show_bug.cgi?id=21440
Bug ID: 21440
Summary: Malicious PE with invalid extended relocation can
cause binutils/objdumo 2.28 to allocate any-size big
memory
Product: binutils
Version: 2.28
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: binutils
Assignee: unassigned at sourceware dot org
Reporter: jgj212 at gmail dot com
Target Milestone: ---
Created attachment 10029
--> https://sourceware.org/bugzilla/attachment.cgi?id=10029&action=edit
Malicious PE with invalid extended relocation sample
-----------------------
$objdump -x $FILE
-----------------------
With x option, objdump will allocate memory to store relocation data, this is
done in the following function:
static void
dump_relocs_in_section (bfd *abfd,
asection *section,
void *dummy ATTRIBUTE_UNUSED)
{
….
relsize = bfd_get_reloc_upper_bound (abfd, section); //can be
controlled
…
relpp = (arelent **) xmalloc (relsize); //allocate memory
relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); //read
reloc data
…
}
the relsize is computed as :
(asect->reloc_count + 1) * sizeof (arelent *) //
coff_get_reloc_upper_bound(…)
In the coff standard, reoc_count is WORD, which is 16bit wide. sizeof (arelent
*) is constant and small. So normally, the result is small. But when PE section
contain extended relocation, everything will go bad.
PE section header is inited in the following function:
static void
coff_set_alignment_hook (bfd * abfd ATTRIBUTE_UNUSED,
asection * section,
void * scnhdr)
{
…
/* Check for extended relocs. */
if (hdr->s_flags & IMAGE_SCN_LNK_NRELOC_OVFL)
{
struct external_reloc dst;
struct internal_reloc n;
file_ptr oldpos = bfd_tell (abfd);
bfd_size_type relsz = bfd_coff_relsz (abfd);
if (bfd_seek (abfd, (file_ptr) hdr->s_relptr, 0) != 0) //seek to the
first reloc data
return;
if (bfd_bread (& dst, relsz, abfd) != relsz) //read the first reloc data
return;
coff_swap_reloc_in (abfd, &dst, &n);//fill struct
if (bfd_seek (abfd, oldpos, 0) != 0)
return;
section->reloc_count = hdr->s_nreloc = n.r_vaddr - 1; //can be
controlled
section->rel_filepos += relsz;
}
…
}
>From the above, when pe section contain extended relocation, reloc_count is
assigned from n.r_vaddr. n is a instance of struct internal_reloc as follow:
struct internal_reloc
{
bfd_vma r_vaddr; /* Virtual address of reference */
long r_symndx; /* Index into symbol table */
unsigned short r_type; /* Relocation type */
unsigned char r_size; /* Used by RS/6000 and ECOFF */
unsigned char r_extern; /* Used by ECOFF */
unsigned long r_offset; /* Used by Alpha ECOFF, SPARC, others */
};
r_vaddr's type is unsigned long, it can be 32bit and 64bit, according to the
os-archive. it is from the dst, which is a instance of struct external_reloc as
follow:
struct external_reloc
{
char r_vaddr[4];
char r_symndx[4];
char r_type[2];
};
So n.r_vaddr is really 32bit wide, section->reloc_count is also 32bit wide.
(asect->reloc_count + 1) * sizeof (arelent *) can be very large.
To control the memory size, it just need to modify the r_vaddr field of first
reloc data, if can be from 0 to 0Xffffffff.
This could cause memory exhaustion to dos.
--
You are receiving this mail because:
You are on the CC list for the bug.
- [Bug binutils/21440] New: Malicious PE with invalid extended relocation can cause binutils/objdumo 2.28 to allocate any-size big memory,
jgj212 at gmail dot com <=