I want to analyze an embedded firmware (car's ecu). My problem is, the file is compressed.

The firmware comes with a description xml file, which states that it is divided into sections and that those sections are individually compressed, using the NRV algorithm.

I did some searching, and none of the usual suspects (magic strings) are in the firmware.

The program that actually flashes the firmware over CAN is written in Java, so I tried decompiling it. That worked, but there are just definitions of functions, there is no flow, who the program is running, which values are passed to the functions, etc.

If it were usual assembler code, I'd just attach a debugger to the running program and had a look at the calls. But I do not know if this is possible in Java.

So my question is, how would I start to decompress the firmware?

I uploaded both firmware and respective xml, maybe some can nudge me in the right direction.


There are a lot of those NRV compressed files, for various ecus with different processors and architectures. So the decompression has to take place on the computer that flashes the firmware.

  • Josh, can you share complied version of UCL, I'm fighting with compilation without success :( – innova Sep 12 '18 at 2:25

NRV is a compressor-decompressor, highly optimized for size and speed, by Markus F.X.J. Oberhumer (www.oberhumer.com). Fortunately, it is available in an Open Source version, downloadable at his site http://www.oberhumer.com/opensource/ucl/#download. It comes in several flavors, the one I have been using is called UCL1.03.

With this software and your xml description file, I was able to decompress your binary. I did it in the following way:

  1. Build an executable from the provided sources (in my download, there was no binary). There is a bat file for various platforms, the one for Windows is called vc.bat. However, it did not work for me, presumably because my environment vars are not set in the proper way for the bat to run. Therefore I made a VStudio solution (VS2013, VS2015 gave some errors), which produced an exe being able to read and decompress the file. This VS project contains the following files (all from the download):
    • All .c files from the "src" direcory
    • The file uclpack.c, residing in the "examples" directory, and containing the "main".
    • The necessary header files, they are all in the "include" or in the "examples" directories.

In the Project Settings make sure that the include directory is set correctly (as usual in VS).

  1. Add the correct header to your binary file.

The header consists of the following parts: enter image description here

  • "Magic" Prefix: see picture
  • Flags: Mostly unclear, LSByte controls the generation of a CRC-32 (different from the one in your xml file).
  • Decompression Method: 2B, 2D, 2E are available, only 2B works with your file.
  • Level: Unclear, but must not be zero.
  • Block Size: Memory for the decompressor. Must have at least the size of the uncompressed block.
  • Uncompressed Size: As read from your xml file
  • Compressed Size:As read from your xml file.

All numbers in the header are Big-Endian (i.e. MSB first). Please note that the software expects a header after each compression block, thus it is best to split your file into three separate files. Only the first one is of some interest, the other two contain only a constant. The contents of the header could easily be found by stepping through the program. The decompressor returns with 0 in the error-free case.

For your comparison, here is a string present in the decompressed file, at file offset 0x6a56:

Incomming message not handled
  • Glad it worked for you! I did not use the -F parameter, but did it in the debugger and stopped after the first file. Maybe that's the reason. Nice question btw, never heard about NRV before! – josh May 28 '18 at 20:14
  • How did you know that NRV is still a part of UPX/UCL from Oberhumer? And how did you come up with the header, from the sources? – PhreakShow May 28 '18 at 21:32
  • No magic at all: Q1: Oberhumer writes it on his website oberhumer.com/opensource/ucl: "UCL is an OpenSource re-implementation of some NRV compression algorithms." Q2: Without any header, running in the debugger leads you to a point where the program tries to read the header and exits with an error. Analysing the source, you insert the header in the way as to avoid that error. You iterate this way until all "header" errors have been satisfied. Straightforward. – josh May 28 '18 at 21:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.