3

I have zero knowledge of how the ELF format works or how to access its headers and data via code, however I need to check whether an ELF binary has been compressed (packed?) with UPX for Linux.

Checking the binary with strings I saw the string UPX! so I guess I can use that. Hexediting the binary shows the string and for the position in the binary I can assume it's part of one of ELF's headers (please correct me if I am wrong). This is a dump of that:

00000000    .ELF........................4...
00000020    ........4. ...(.................
00000040    ........................@...@...
00000060    @.....................[.UPX!....
00000080    ............T............?d..ELF

I don't know if this looks good, sorry.

Does anyone know how to detect UPX on Linux? If not, how to access the headers and get that UPX! string (name of the header?)?

I did look into the UPX source code but everything is C++, I am looking to code this in C, and it's really hard to follow.

Thank, any help is welcomed.

EDIT: About the bounty. They answer must give a solid example that works since I've tried different approaches and they not always work, like the sample below.
Thank you

Jessica
  • 2,005
  • 4
  • 28
  • 44

2 Answers2

4

These are the tests to detect an UPX compressed file:

>>>>(0x3c.l+0xf8)   string      UPX0 \b, UPX compressed
>>>>(0x3c.l+0xf8)   search/0x140    UPX2
>>>(&0x7c.l+0x26)   string      UPX \b, UPX compressed
>>>&0x26    string      UPX \b, UPX compressed
>>85    string      UPX     \b, UPX compressed

use

man 5 magic

to see how the offsets inside the file are specified.

For example in you program you should:

  1. open the file under test for reading
  2. skip to one of these offsets
  3. check if the expected string is there
  4. repeat until no more offsets

Interestingly enough, in my ubuntu 64bit, UPX compressed files are not detected because this test is missing from /usr/share/misc/magic:

>>180   string      UPX!        UPX compressed (64-bit)
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
  • Thank you. I am totally confused tho. `magic` is the file that has all the references for `file`? How do I call this from my code? – Jessica Feb 03 '11 at 17:32
  • You can use system() or read the values at the same offsets as file uses and compare them. – Diego Torres Milano Feb 03 '11 at 18:37
  • OK, I really appreciate your help, but I do not understand what you are trying to tell me. Read the offsets of the magic file? do a `seek' at a certain position? in any case, let's say I read the magic file, I still don't know how to read the headers of the ELF. Any chance you can post a snippet? – Jessica Feb 03 '11 at 18:47
  • so in this particular case, if I undertood correctly from the man page, I should seek 180 bytes, read into a buffer and compare to `UPX!`? If not, what's the difference between >, >>, >>>>, etc? – Jessica Feb 03 '11 at 21:43
  • The number of '>' indicates a kind of relationship with previous tests. In you case probably you don't need anything else, just skip 180 bytes and read, but before check the content of a sample file with 'xxd' to verify that 180 is correct. – Diego Torres Milano Feb 03 '11 at 23:17
  • I am 1000 bytes off the beginning of the file and I can't get it to read anything. I compare the buffer read as a plain string, the char to char and hex to hex. Nothing. I am getting a bit frustrated. There's something I am missing. I ask again, would it be possible to post a small snippet? Thank you, I appreciate it. – Jessica Feb 04 '11 at 15:30
2

In the source code to UPX, there's a function int PackW32Pe::canUnpack() which is first ran as a test right when you do a upx -d <file> (unpack executable). It shows which offsets are to be tested to detect if a file was packed with UPX. I found the code clear and easy to follow. I recommend an editor with syntax highlighting.

You can download the source code for UPX on the project site.