Created attachment 8814 [details] exploit input file for objdump and nm Hi, We find an memory crush bug of objdump and nm at least before binuitls-2.24,and This bug is caused by missing check of read variable "parsed_size" in archive.c:481(The following description use binutils-2.23 as an example). Also we find that this bug still exists in versions after binutils-2.23 by reviewing the source code, but it doesn't crash in our test in Ubuntu 14.04 as for the dynamic allocation area is all flushed by zero (00 00 00 00). We create a trigger input file for this bug and we make it as an attachment. object -t option and default option and nm default e.g #objdump -t exploit_file #objdump exploit_file #nm exploit_file In line archive.c:481, parsed_size is assigned by the hdr.ar_size(in function:_bfd_generic_read_ar_hdr_mag). 481: scan = sscanf (hdr.ar_size, "%" BFD_VMA_FMT "u", &parsed_size); Thus if we construct "30 00 00 00 00 00 00 00 00 00" for hdr.ar_size, then we get a "0"string(30 is the ASCII number of zero),and the parsed_size will then become zero. In line 562 the parse_size is assigned to ared->parsed_size: 562 ared->parsed_size = parsed_size; The struct pointer ared is returned and assigned to mapdata in line 883 in function _bfd_generic_read_ar_hdr: 883: mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); In line 886, mapdata->parsed_size is assigned to parsed_size(note that we are in function _bfd_generic_read_ar_hdr now): 886: parsed_size = mapdata->parsed_size; In line 889, parsed_size is used as the length to apply for dynamic memory. 889: raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size); As parsed_size is zero so pointer raw_armap is not NULL and points to some padding bytes. It passed the following check as the parsed_size is zero now and the condition is false. 893: if (bfd_bread (raw_armap, parsed_size, abfd) != parsed_size) In line 902, ardata->symdef_count is assigned by the former applied dynamic padding bytes.The expanded macro H_GET_32 will call bfd_getl32 to convert the four bytes to integer. 902: ardata->symdef_count = H_GET_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE; 903: 904: if (ardata->symdef_count * BSD_SYMDEF_SIZE > 905: parsed_size - BSD_SYMDEF_COUNT_SIZE) BSD_SYMDEF_SIZE expanded to 8. The following error check doesn't work as "parsed_size-BSD_SYMDEF_COUNT_SIZE" will be a very large unsigned number 0xfffffffc. The following for statement in 922 then use ardata->symdef_count as the loop bound, thus cause a memory overread crush in line 927. 922: for (counter = 0, set = ardata->symdefs; 923: counter < ardata->symdef_count; 924: counter++, set++, rbase += BSD_SYMDEF_SIZE) 925: { 926: set->name = H_GET_32 (abfd, rbase) + stringbase; 927: set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); 928: } Here paste the gdb crash stack: Program received signal SIGSEGV, Segmentation fault. bfd_getl32 (p=0x811b000) at libbfd.c:623 623 v |= (unsigned long) addr[1] << 8; (gdb) bt #0 bfd_getl32 (p=0x811b000) at libbfd.c:623 #1 0x0804d5cd in do_slurp_bsd_armap (abfd=abfd@entry=0x80faa50) at archive.c:927 #2 0x0804e877 in bfd_slurp_armap (abfd=0x80faa50) at archive.c:1119 #3 0x0804e5cb in bfd_generic_archive_p (abfd=0x80faa50) at archive.c:809 #4 0x08056720 in bfd_check_format_matches (abfd=abfd@entry=0x80faa50, format=format@entry=bfd_archive, matching=matching@entry=0x0) at format.c:215 #5 0x08056a8f in bfd_check_format (abfd=abfd@entry=0x80faa50, format=format@entry=bfd_archive) at format.c:95 #6 0x0804bf81 in display_file (filename=0xbfffeabe "exploit_file") at nm.c:1210 #7 0x0804a115 in main (argc=2, argv=0xbfffe814) at nm.c:1688 The attacker may create more sophisticated exploit to cause a memory leak, thus access privileged information nearby and other unknown effect. Sincerely, Ke Yang,Institute of Software Chinese Academy of Sciences Hengtai Ma,Institute of Software Chinese Academy of Sciences Xuefei Wang,Institute of Software Chinese Academy of Sciences
Forgot to say our test platform: Ubuntu14.04i386 #uname -a #Linux ubuntu 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:12 UTC 2014 i686 i686 i686 GNU/Linux We think this is a critical problem because it may cause the leak of critical information.
Hi Guys, Thanks very much for reporting this problem. > We find an memory crush bug of objdump and nm at least before > binuitls-2.24,and You are correct - this bug exists in 2.24 and earlier versions of the binutils. Fortunately however the bug has been fixed in the 2.25 release and the forthcoming 2.26 release, so it is only a problem for legacy installations. At this point I think that it is up to distribution maintainers to decide if and how they want to patch this bug - assuming of course that they are using the 2.24 (or earlier) sources. Cheers Nick PS. This problem, and others like it, were reported in PR 17512. *** This bug has been marked as a duplicate of bug 17512 ***
Thanks for your attention! Wow, it's a really hot comment list. Regards, Ke Yang