Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multiple memory reading issue #206

Closed
math1as opened this issue May 17, 2018 · 6 comments
Closed

multiple memory reading issue #206

math1as opened this issue May 17, 2018 · 6 comments

Comments

@math1as
Copy link

math1as commented May 17, 2018

./upx.out --version
upx 3.95-git-614c86fb7d7b+
this time is the devel branch , everything up-to-date

result

the call stack for POC1

#0 0x00000000006647f8 in get_le32 (p=0x30) at bele.h:164
#1 N_BELE_RTP::LEPolicy::get32 (this=0x9b63c0 <N_BELE_RTP::le_policy>, p=0x30) at bele_policy.h:192

the poc.zip , contains POC1 & POC2

poc.zip

@jreiser
Copy link
Collaborator

jreiser commented May 18, 2018

Fixed on devel branch which will be pushed shortly.
upx.out: poc1: CantPackException: bad PT_DYNAMIC phdr[4]
upx.out: poc2: CantPackException: DT_STRTAB above stub

Note: bugs in decompression (upx -d or upx -t) are more significant that bugs in compression. If upx fails to compress then the workaround is just to forgo the reduction in space. If upx fails to decompress, then that's a mild security risk because it limits the ability of a malware scanner to see the entire original contents.

jreiser added a commit that referenced this issue May 18, 2018
@jreiser jreiser closed this as completed Jun 16, 2018
@DestyNova
Copy link

DestyNova commented Jul 28, 2018

@jreiser Could you explain more about the bad PT_DYNAMIC phdr[4] error message? I'm seeing it when trying to compress a simple program produced by the ponyc compiler on Ubuntu 64-bit (on the devel branch; the latest stable version produces a packed file which segfaults, but can be successfully decompressed with upx -d).

@jreiser
Copy link
Collaborator

jreiser commented Jul 28, 2018

$ readelf --segments --sections poc1
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [22] .dynamic          DYNAMIC          0000000000600e28  00000e28
       00000000000001d0  0000000000000010  WA       6     0     8

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R E    0x8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000000069c 0x000000000000069c  R E    0x200000
  LOAD           0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
                 0x0000000000000220 0x0000000000000228  RW     0x200000
  DYNAMIC        0x0000000000000f28 0x0000000000600e28 0x0000000000600e28
                 0x00000000000001d0 0x00000000000001d0  RW     0x8
readelf: poc1: Warning: the .dynamic section is not contained within the dynamic segment

Look at phdr[4]: PT_DYNAMIC. It has a file Offset of 0xf28 and VirtAddr/PhysAddr of 0x600e28; but the Offset is not congruent to the Addr modulo the Align of 0x200000 for phdr[3] PT_LOAD which is mapped into memory and supposedly contains the PT_DYNAMIC. So one of Offset or Addr is wrong.

Looking at

$ od -Ax -tx8 -j 0xe18 poc1 | sed 5q
000e18 0000000000400490 0000000000000000
000e28 0000000000000001 0000000000000001
000e38 000000000000000c 0000000000400390
000e48 000000000000000d 0000000000400564
000e58 0000000000000019 0000000000600e10

we see that the PT_DYNAMIC actually begins at offset 0xe28. So the program that wrote poc1 must fix its bug of the wrong value in Elf64_Phdr[4].p_offset.

[The "excessive checking" is to protect upx against malware which tries to cause SIGSEGV or bad output by overwriting the ELF headers. Anti-malware scanners rely on upx -d to remove compression and reveal the code which will be executed, so that the scanner can analyze it.]

@DestyNova
Copy link

Thanks @jreiser, that's very informative, although I didn't fully understand the alignment part nor how to determine whether which of Offset or Addr is correct. I checked both locations with od and they don't look quite like this. From what I can tell, the file is produced by the llvm C compiler. I could open a separate issue and share a test file and readelf / od output, if you'd be willing to take a quick look?

@DestyNova
Copy link

DestyNova commented Jul 29, 2018

Ah, I see one cause of the exception now. I added some debugging prints to p_lx_elf.cpp and in PackLinuxElf64::check_pt_dynamic(...), the following failure check evaluates to a nonzero result:

(-1+ page_size) & (t ^ vaddr)

(for this file, s: 121472, t: 121456, file_size: 156624, filesz: 608, memsz: 608, page_size: 65536, vaddr: 125552, Elf64_Dyn size: 8)
=>  (-1 + 65536) & (121456 ^ 125552)
=> 12288

Probably should have printed them in hex, come to think of it. Is this the congruence check you mentioned?

@jreiser
Copy link
Collaborator

jreiser commented Jul 29, 2018

Yes, the congruence check. .p_offset and .p_vaddr must be at the same position on a page. rust (probably llvm) has had problems setting the right .p_offset. In this case 0xf28 should be 0xe28 instead.
If the new test file is somewhat small then I'll look at it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants