X-POST FROM unix.stackexchange.com

I'm currently trying to make modifications to a router firmware: Swisscom Centro Grande - aka Pirelli Vx226N1, firmware version: 60200.

I've decompiled it successfully with FMK v0.99 and got the header.img, the rootfs.img and the footer.img image parts.

This is the binwalk of rootfs.img:

Squashfs filesystem, little endian, non-standard signature, version 4.0, compression:gzip, size: 2764423 bytes, 1145 inodes, blocksize: 65536 bytes, created: Fri Mar 15 00:33:08 2013

I decompiled the rootfs.img with unsquashfs succesfully and got the system folders. I made some changes (enabled a shell on telnet) and tried to repack everything with the tools provided (the ./build-firmware.sh command).

The final firmware size was bigger than the original one. Tried to falsh, nothing happened. I analyzed the firmware and especially the upgrade method to learn how to properly build the firmware.

I found the update.sh file which handles the upgrade process (analyzes the file provided by the user and flashes only if everything is correct, in order to prevent brick)

Here is the link to the pastebin of that file

I'm pretty sure that the original firmware files are parsed through the parse_yaps_image() function, so I tried adapting on my own to check the files but I noticed that there was an external check with a binary file called sig_verify

If the files doesn't exists another function is invoked, the problem is that the function provided isn't correct (it return a wrong validation token error even with original firmwares!)

My goal is to analyze the sig_verify file and look for the algorithm, in order to understand the composition method and in order to flash my router in the proper way and finally get the root shell (and make modification on everything I want)

I uploaded all files on a Mega folder so the interesed guys who wanna help me could access any file needed.

I included in the folder 60208 the two scripts I used to check the files.

The result of the script I wrote (it's just the adaptation of the script in the router) is this:

denys@denys-pc:~/Documents/router/Vx226N1/images/modified/60208$ ./check_upgrade_yaps.sh 
Parsing YAPS format...
16+0 records in
16+0 records out
16 bytes (16 B) copied, 0.000843843 s, 19.0 kB/s
Error: wrong validation token (5b445d3b251d59753031c9d7a94ba4ab, 7d98668859855f1b9459256257fc3262)

And here is the binwalk of sig_verify file.

denys@denys-pc:~/Documents/router/Vx226N1/images/modified/60208$ binwalk sig_verify 

0           0x0         ELF 32-bit MSB executable, MIPS, version 1
1921        0x781       LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 16777472 bytes

As you can notice it's a MIPS executable. I tried to run it under a MIPS envirronment (virtual machine, qemu-system-mips) without any success.

qemu-system-mips -M mips -kernel ./vmlinux-2.6.18-6-qemu -initrd ./initrd.gz -hda hda.img -append "root=/dev/ram console=ttyS0" -nographic

The kernel and the initrd were downloaded by http://archive.debian.org/debian/dists/etch/main/installer-mips/current/images/qemu/netboot/

Any help would be appreciated. If someting isn't clear just let me know :)

--- EDIT ---

Decompiled... Anyone that could translate machine language into human-comprehensible code?

  • Your decompilation is an attempt to transform the ELF header of a MIPS binary into 32-bit 80x86 assembly. Unfortunately, the result doesn't make sense. I've uploaded my IDA disassembly to Mega. You might try if you can load the .idb into the trial version of IDA, or you can check the (editable) asm or (more readable) html file. Even if you don't know Mips assembler, function names and printed strings tell you a lot about what the binary does. Jan 21, 2015 at 17:13
  • I took a look at the code, I still don't understand it (except for the function names). As you said probably there is a private key that I need to crack / discover. Can you suggest me any way? As I said my only goal is to compile a custom firmware, and I still don't know if the else of if [ -x /usr/sbin/sig_verify ]; then is really valid (line 156 to 164 of update.sh) Jan 21, 2015 at 19:23
  • Seems to me like there was an old way to validate the file, and a new way. The old way is the else part, and it assumes the checksum is at bytes 240-255 of the file. The generator sets them to 0, generates the MD5sum of the file, then stores the MD5sum into those bytes. The validator extracts them, sets them to 0, computes the MD5sum, and checks if they match. But all this is only done if sig_verify doesn't exists, or isn't executable. Jan 21, 2015 at 21:33
  • If sig_verify exists and is executable, then it's used instead of the "old" way. This will execute the sig_verify binary, which does something similar, but it will also use asymmetric encryption on the checksum. To replicate this, you'd need the private key, but you only have the public one from the disassembly. Getting that private key is about as feasible as getting the secret from an ssh or a https server - there's no real way to do this. Jan 21, 2015 at 21:37
  • I understood the code, but I didn't understand why is there the alternative since the firmware is packed and the file couldn't disappear. Even if the file isn't available the firmware should be verified and return a positive value, but it isn't. I mean, with the adaptation code I made if I pass the firmware it returns a verification check error ( "Error: wrong validation token ($token, $hash)") There should be a way of flashing a custom firmware without actually JTAG the router no? Is there any method instead of "trying to crack" the private key? Jan 21, 2015 at 22:44

1 Answer 1


Interestingly, both the online disassembler and retargetable decompiler choke on your sig_verify program, and objdump says it has a corrupted section header, while Ida can read it without any problems.

From a quick glance, there's only 3 interesting functions in it, that i called main, generate_hash and verify_key. Both generate_hash and verify_key use various functions of the gcrypt library (which it links dynamically). main opens a file from argv, uses generate_hash to calculate a checksum over the file, then calls verify_key. verify_key uses, among some other stuff, gcry_pk_verify, which verifies a public key. If verify_key succeeds, main truncates the last few bytes from the file (which, i assume, contain the key to verify against).

It seems to me that the vendor uses some private key to sign the firmware file, and has the flash process check the file against the corresponding public key, which would make it very hard to create a valid replacement firmware. HOWEVER, i only looked at the function names and strings and didn't try to understand every byte of the functions, so i might be wrong.

I don't know if my IDA license allows me to make the disassembly public, but i'll check this and, if you're interested and it's ok with the license, upload the disassembly somewhere so you can investigate further.

  • Awesome work, I'm still working on it, I have two of these router. One with shell activated (older version of firmware which unfortunatly isn't flashable anymore) and the other one with the newest version. I'm testing the binaries right in the old-firmware router to see what I can get Jan 20, 2015 at 21:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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