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, 2018 at 2:25
  • can you help again? I had tryed to decompress a similar file But i get error -201 XML info: >SOURCE-START-ADDRESS: 00000000 SOURCE-END-ADDRESS: 000142E3 TARGET-START-ADDRESS: 80040000 TARGET-END-ADDRESS: 8007E6FF Header: >00E955434CFF011A 00000000 2B 01 0003E6FF 0003E6FF 000142E3 mega.nz/folder/rDBAHIRL#GbXBFYwyaM7DREFi7PDC3g
    – woodwarth
    Aug 4, 2022 at 14:30

2 Answers 2


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, 2018 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, 2018 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, 2018 at 21:54
  • i tried to replicate the same NRV decompresion, but failed with error: uclpack: Method: 0x2b Level: 0x1 Block Size: 0x40000 uclpack: allocate buffer 0x48100 uclpack: read uncompressed size 0x3e024 uclpack: compressed data violation: error -203 (0x2b: in_len: 0x19bf8 / out_len0: x3e024 / new_len: 0x3e022 ) maybe any hints there to dig up? it is same files people used in uper posts, header is quite clear, but still does not want to decompress. thanks for any info. Jul 2, 2023 at 20:18

I found this tool written in Rust by a BMW engineer which probably should decompress their binaries:


From the code, it seems to be using ucl_nrv2b_decompress_safe_8 function.

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