.braindump – RE and stuff

September 6, 2011

Reverse engineering an obfuscated firmware image E01 – unpacking

Filed under: Uncategorized — Stefan @ 10:38 am
Tags: , , , ,

When reverse engineering Linux-based firmware images the following methodology usually works pretty well:

  1. use Binwalk to identify different parts of a firmware image by their magic signatures
  2. use dd to split the firmware image apart
  3. unpack parts / mount/extract the filesystem(s)
  4. find interesting config files/binaries
  5. load ELF binaries into your favorite disassembler
  6. start looking at beautiful MIPS/ARM/PPC ASM

This approach unfortunately didn’t work when I looked at firmware images for a broadband router called ‘EasyBox 803’ distributed by Vodafone Germany (formerly Arcor). Apart from two LZMA-packed segments containing information irrelevant for my research didn’t find anything useful in the firmware image at first.
As I had to confirm a major vulnerability (default WPA keys based on ESSID/BSSID [1][2]) I didn’t give up at this point. But let’s start right at the beginning …

I obtained a firmware update file for the EasyBox 803 from Vodafone’s support page. A Google search reveals the following:

  • the device is manufactured by Astoria Networks, which is the German subsidiary of the Taiwanese company Arcadyan
  • there are tools available for unpacking Arcadyan firmware (SP700EX, arcadyan_dec)
  • Arcadyan uses obfuscation (xor, swapping bits/bytes/blocks) to thwart analysis of their firmware files
  • Arcadyan devices don’t run Linux, instead they have their own proprietary OS
  • MIPS big endian is their preferred architecture

I tried to unpack the firmware file with the tools I found, but although they can deobfuscate the firmware of other Arcadyan devices, they could not do the same for mine. Nevertheless the tools helped me in understanding the layout of my firmware image. It basically consists of several sections which are concatenated. From a high-level view a section looks like this:

arcadyan section layout info

(relevant words marked with '||')
beginning of section:
00000000h:|32 54 76 98|11 AF 99 D3 AC FF EA 6C 43 62 39 C8 ; 2Tv˜.¯™Ó¬ÿêlCb9È
...
end of data:
001e83a0h: 0C D8 A3 4A|CD AB 89 67|EE 50 66 2C 53 00 15 93 ; .Ø£JÍ«‰gîPf,S..“
...
end of section:
001e83e0h: 0A 01 EF 8A 73 58 DE 85 00 00 00 00|FF FF FF FF|; ..ïŠsXÞ…....ÿÿÿÿ
001e83f0h:|FF FF FF FF|A4 83 1E 00|78 56 34 12|5E E2 53 5F|; ÿÿÿÿ¤ƒ..xV4.^âS_
beginning of next section:
001e8400h:|32 54 76 98|82 FF 4D 9D CF 6A 95 5E B0 5C 96 7F ; 2Tv˜‚ÿMÏj•^°\–
...

After I miserably failed at recognizing the obfuscation method just by looking at the hexdump I had to move on. I suspected that the deobfuscation is handled by the bootloader itself, so that was the next thing I wanted to look at. Luckily Vodafone had to update the bootloader for Easybox 802 (predecessor to EasyBox 803) to enable some random functionality and kindly provided a copy, otherwise dumping the flash would have been necessary.

unzip_fw looks like this:

As the deobfuscation and LZMA unpacking is indeed handled by the bootloader, I reversed and reimplemented their fancy deobfuscation routine (deobfuscate_ZIP3):

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//xor chars in str with xorchar
void xor(unsigned char* bytes, int len, char xorchar) {
	int i;

	for (i = 0; i < len; i++) {
		bytes[i] = bytes[i] ^ xorchar;
	}
}

//swap high and low bits in bytes in str
//0x12345678 -> 0x21436578
void hilobswap(unsigned char* bytes, int len) {
	int i;

	for (i = 0; i < len; i++) {
		bytes[i] = (bytes[i] << 4) + (bytes[i] >> 4);
	}
}

//swap byte[i] with byte[i+1]
//0x12345678 -> 0x34127856
void wswap(unsigned char* bytes, int len) {
	int i;
	unsigned char tmp;

	for (i = 0; i < len; i += 2) {
		tmp = bytes[i];
		bytes[i] = bytes[i + 1];
		bytes[i + 1] = tmp;
	}
}

int main(int argc, char *argv[]) {
	unsigned char* buffer;
	unsigned char* tmpbuffer[0x400];
	size_t insize;
	FILE *infile, *outfile;

	if (argc != 3) {
		printf("usage: easybox_deobfuscate infile outfile.bin.lzma\n");
		return -1;
	}

	//read obfuscated file
	infile = fopen(argv[1], "rb");

	if (infile == NULL) {
		fputs("cant open infile", stderr);
		return -1;
	}

	fseek(infile, 0, SEEK_END);
	insize = ftell(infile);
	rewind(infile);

	buffer = (unsigned char*) malloc(insize);
	if (buffer == NULL) {
		fputs("memory error", stderr);
		exit(2);
	}

	printf("read \t%i bytes\n", fread(buffer, 1, insize, infile));
	fclose(infile);

	printf("descrambling file ...\n");
	//xor HITECH
	xor(buffer + 0x404, 0x400, 0x48);
	xor(buffer + 0x804, 0x400, 0x49);
	xor(buffer + 0x4, 0x400, 0x54);
	xor(buffer + 0x404, 0x400, 0x45);
	xor(buffer + 0x804, 0x400, 0x43);
	xor(buffer + 0xC04, 0x400, 0x48);

	//swap 0x4 0x404
	memcpy(tmpbuffer, buffer + 0x4, 0x400);
	memcpy(buffer + 0x4, buffer + 0x404, 0x400);
	memcpy(buffer + 0x404, tmpbuffer, 0x400);

	//xor NET
	xor(buffer + 0x4, 0x400, 0x4E);
	xor(buffer + 0x404, 0x400, 0x45);
	xor(buffer + 0x804, 0x400, 0x54);

	//swap 0x4 0x804
	memcpy(tmpbuffer, buffer + 0x4, 0x400);
	memcpy(buffer + 0x4, buffer + 0x804, 0x400);
	memcpy(buffer + 0x804, tmpbuffer, 0x400);

	//xor BRN
	xor(buffer + 0x4, 0x400, 0x42);
	xor(buffer + 0x404, 0x400, 0x52);
	xor(buffer + 0x804, 0x400, 0x4E);

	//fix header #1
	memcpy(tmpbuffer, buffer + 0x4, 0x20);
	memcpy(buffer + 0x4, buffer + 0x68, 0x20);
	memcpy(buffer + 0x68, tmpbuffer, 0x20);

	//fix header #2
	hilobswap(buffer + 0x4, 0x20);
	wswap(buffer + 0x4, 0x20);

	//write deobfuscated file
	outfile = fopen(argv[2], "wb");

	if (outfile == NULL) {
		fputs("cant open outfile", stderr);
		return -1;
	}

	printf("wrote \t%i bytes\n", fwrite(buffer + 4, 1, insize - 4, outfile));
	fclose(outfile);

	printf("all done! - use lzma to unpack");

	return 0;
}

You can see that it would have been impossible to understand how the obfuscation works without looking at the actual assembly. Luckily this routine also works for EasyBox 803.

Let’s unpack first segment, which is the biggest one and therefore most likely to contain code.

>fdd if=dsl_803_752DPW_FW_30.05.211.bin of=dsl_803_s1_obfuscated count=0x1e83a4
count   : 0x1e83a4      1999780
skip    : 0x0   0
seek    : 0x0   0
1999780+0 records in
1999780+0 records out
1999780 bytes (2.00 MB) copied, 0.009540 s, 199.90 MB/s

>easybox_deobfuscate dsl_803_s1_obfuscated dsl_803_s1.bin.lzma
read    1999780 bytes
descrambling file ...
wrote   1999776 bytes
all done! - use lzma to unpack

>xz -d dsl_803_s1.bin.lzma

>l dsl_803_s1*
-rw-r--r--+ 1 stefan None 8.3M  6. Sep 11:27 dsl_803_s1.bin
-rw-r--r--+ 1 stefan None 2.0M  6. Sep 11:25 dsl_803_s1_obfuscated

dsl_803_s1.bin:
00000000h: 40 02 60 00 3C 01 00 40 00 41 10 24 40 82 60 00 ; @.`.<..@.A.$@‚`.
00000010h: 40 80 90 00 40 80 98 00 40 1A 60 00 24 1B FF FE ; @€.@€˜.@.`.$.ÿþ
00000020h: 03 5B D0 24 40 9A 60 00 40 80 68 00 40 80 48 00 ; .[Ð$@š`.@€h.@€H.
00000030h: 40 80 58 00 00 00 00 00 04 11 00 01 00 00 00 00 ; @€X.............
00000040h: 03 E0 E0 25 8F E9 00 00 03 89 E0 20 00 00 00 00 ; .àà%é...‰à ....
00000050h: 00 00 00 00 00 00 00 00 24 04 40 00 24 05 00 10 ; ........$.@.$...
00000060h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000070h: 3C 06 80 00 00 C4 38 21 00 E5 38 23 BC C1 00 00 ; <.€..Ä8!.å8#¼Á..
00000080h: 14 C7 FF FE 00 C5 30 21 00 00 00 00 00 00 00 00 ; .Çÿþ.Å0!........
00000090h: 00 00 00 00 00 00 00 00 24 04 40 00 24 05 00 10 ; ........$.@.$...
...

Now we can load the file into IDA. This sounds easier than it is, because the unpacked firmware segment is raw code (mipsb) and data without information about segmentation, like you would have when dealing with a PE or ELF binary.

Continued in E02: Reverse engineering an obfuscated firmware image – analysis

Note: Most of this research was conducted several months ago and my findings were probably not in this particular order. – I think it just makes more sense presenting it this way.
Note²: fdd is my silly Python implementation of dd. It takes HEX-offsets and has bs=1 by default.
Note³: Make sure to comply with Vodafone’s terms of use.

39 Comments »

  1. Nice Work until here, but i like to ask something:
    What do you mean with this: “Note²: fdd is my silly Python implementation of dd. It takes HEX-offsets and has bs=1 by default (and works entirely different than dd).” and especially this part: “(and works entirely different than dd).”
    For me it looks like the same as:
    dd if=dsl_803_752DPW_FW_30.05.211.bin of=dsl_803_s1_obfuscated bs=1 count=1999780

    Thank you
    MasterQ

    Comment by MasterQ — September 24, 2011 @ 4:47 am | Reply

    • Hi MasterQ,
      By “works entirely different than dd” I mean that it does not make a syscall for each byte, instead it loads the whole binary at once.
      dd if=dsl_803_752DPW_FW_30.05.211.bin of=dsl_803_s1_obfuscated bs=1 count=1999780 would have the exactly same effect, but is a bit slower (depends on OS, of course).
      For clarity I removed the part in the brackets.

      Cheers

      Comment by Stefan — September 25, 2011 @ 12:28 pm | Reply

  2. Could you help me to replace dsl firmware from annex B to annex A? I tried with sp700ex but it splits EB803 firmware in 7 parts and program itself can join back only 5. I think that dsl firmware for annex a is this http://mirror2.openwrt.org/sources/dsl_danube_firmware_adsl_a-02.04.04.00.00.01.tar.gz
    Thanks!

    Comment by Milan — November 27, 2011 @ 11:29 pm | Reply

  3. hello, nice piece of work but i’m wondering something, did you use any other tool than your brain to reverse the MIPS function deobfuscate_ZIP3(). Did you use an automated mips decompiler?
    Regards,

    Comment by int0x13 — February 13, 2012 @ 11:09 pm | Reply

    • Thank you! The decompilation was done manually. – That’s not very hard once you’ve spent a few weeks staring at ugly MIPS assembly. 🙂
      As far as I know there is no working MIPS decompiler available.

      Cheers

      Comment by Stefan — February 14, 2012 @ 7:12 pm | Reply

      • You should look into JEB Pro, we do provide a native MIPS 32-bit decompiler in version 2.3.

        Comment by Nicolas Falliere — May 5, 2017 @ 6:54 pm

  4. Could you post source for “obfuscate_ZIP3”? Then we could obfuscate data, “fool” original bootloader and upload uboot/openwrt to device with no need for serial/UART access.
    Thx!

    Comment by angrybb — February 14, 2012 @ 7:35 pm | Reply

  5. Thank you! The decompilation was done manually.

    Comment by Nick — March 6, 2012 @ 8:16 pm | Reply

  6. by any chance …. have you also been looking into the over all checksum algo of the firmware. the checksum is stored in the last section of the firmware (located where the first “0xffffffff” long in your high-level picture is located)

    additional just for the record: your s_data_end marker is just the (s_obfuscated_start) xor 0xffffffff and the padding is just the 0xff xored deobfuscated beginning of the firmware section.

    nevertheless the only part that is still missing is the algo for the checksum…. can you by any chance give me a hand….

    cheers
    /chefchen

    Comment by Chefchen — April 21, 2012 @ 11:50 am | Reply

  7. […] to thank Stefan Viehböck for his blog .braindump in which he provides excellent information on how to descramble and unpack firmware images of Arcadyan […]

    Pingback by Extract VoIP login data from o2 Box 4421 and o2 Box 6431 | hph's blog — February 13, 2013 @ 6:06 pm | Reply

  8. I simply desired to thank you very much yet again.
    I am not sure the things I could possibly have gone through without the
    smart ideas shared by you concerning my theme. It absolutely was the traumatic problem
    in my position, however , seeing a new professional manner you
    solved it made me to jump for contentment. Now i am thankful for your help
    and then have high hopes you recognize what a great job you’re undertaking training many others thru a blog. Most likely you’ve never got to know any of us.

    Comment by gratis sexfilme — July 31, 2013 @ 12:26 am | Reply

  9. In this diet program system, the dieter is asked a set of 70 concerns, the answers to
    which will decide the food habits, attitudes
    and exercise habits of the individual.

    Comment by cellulite solutions — August 19, 2013 @ 4:06 am | Reply

  10. Thanks everyone for coming out had chatting and sharing. Pass the word, I’d love to have some other authors comment and tell us what they do

    Comment by comoobtenerelcuil.com.ar — August 25, 2013 @ 11:57 pm | Reply

  11. good post

    thank for your sharing 🙂

    Comment by nimal maula — November 26, 2013 @ 4:02 am | Reply

  12. Hello,

    I’m more or less completely new to disassembling, but I managed to follow this two blog posts and reproduce the results. What I don’t understand is how you determined 0x83000000 as ROM start address and 0x1000 as file offset for the bootloader file to be loaded in IDA in the first. Where did you get that from? From manual disassembly of the bootloader file provided by vodafone? If so, how?

    Comment by newbie — December 11, 2013 @ 11:01 am | Reply

  13. Hi,

    Can you give some details about how you managed to reverse engineer the Infeneon Boot Loader? Details such as The Rom Load Address, and General Pointer.
    I am trying to replicate your Findings but I cannot get IDA to reference the strings properly, even after using the Python scripts mentioned in episode two.

    Thanks,
    Andrew Borg

    Comment by Andrew Borg — January 3, 2014 @ 11:52 am | Reply

  14. […] firmware…’ message is particularly interesting; a bit of Googling turned up this post on reversing Arcadyan firmware obfuscation, though it appears to be different from the obfuscation […]

    Pingback by Reversing the WRT120N’s Firmware Obfuscation - /dev/ttyS0 — February 2, 2014 @ 4:06 am | Reply

  15. […] ‘Unzipping firmware…’, быстрый гуглёж привел меня к посту про деобфускацию прошивок от Arcadyan, но тут, похоже, […]

    Pingback by [Перевод] Исследуем обфускацию прошивки Linksys WRT120N | Вести3.ру — Информационный журнал — February 19, 2014 @ 5:29 pm | Reply

  16. […] ‘Unzipping firmware…’, быстрый гуглёж привел меня к посту про деобфускацию прошивок от Arcadyan, но тут, похоже, […]

    Pingback by [Перевод] Исследуем обфускацию прошивки Linksys WRT120N » CreativLabs — February 20, 2014 @ 11:53 am | Reply

  17. […] ‘Unzipping firmware…’, быстрый гуглёж привел меня к посту про деобфускацию прошивок от Arcadyan, но тут, похоже, […]

    Pingback by Исследуем обфускацию прошивки Linksys WRT120N « Домик Миа — February 23, 2014 @ 6:10 pm | Reply

  18. You post interesting posts here. Your blog deserves much more visitors.
    It can go viral if you give it initial boost,
    i know very useful tool that can help you, simply type in google: svetsern traffic tips

    Comment by Rhys — January 2, 2015 @ 6:49 pm | Reply

  19. Now I am going to do my breakfast, when having my breakfast coming again to read other news.

    Comment by Mai — January 11, 2015 @ 2:49 am | Reply

  20. hi sir i really need ur help please contact me @ ehab_jean2006@yahoo.com

    thanks in advance

    Comment by ehab — September 23, 2015 @ 8:06 am | Reply

  21. thank you for sharing this article

    Comment by iswandi — October 2, 2015 @ 7:45 am | Reply

  22. Instead, when deciding a case, the choose is duty-certain to stay
    to the info and the applicable regulation.

    Comment by Aracely — April 18, 2016 @ 2:31 am | Reply

  23. The stated carbon emissions are current in oil combustion in very high levels and are the primary culprits behind the greenhouse impact that results in global
    warming and local weather change.

    Comment by Biomass — August 12, 2016 @ 3:19 pm | Reply

  24. Guys who of you play Pokemon GO? Incredible game, yesterday
    i caught rare pokemon Hitmonlee using pokebusterbot !
    No ban so far, still using it. You should too.

    Comment by Ronda — August 24, 2016 @ 5:00 am | Reply

  25. Hello,
    Your article is really awsome. I really like that!
    I cannot download bin file you analyzed. And I really want to see deobfuscate_ZIP3() Function. Because your C code is really awsome!

    I am studying firmware reverse engineering and It must help me to analize.
    Thanks

    Comment by Robert Moon — April 11, 2017 @ 8:36 am | Reply

  26. This is really attention-grabbing, You are an excessively skilled blogger.

    I’ve joined your feed and sit up for seeking more of
    your magnificent post. Additionally, I have shared your website in my social networks

    Comment by المنورة — October 30, 2017 @ 2:19 pm | Reply

  27. best fish finder

    Reverse engineering an obfuscated firmware image E01

    Trackback by fishing equipments — October 16, 2018 @ 1:55 pm | Reply

  28. seria possivel mostrar como extrair o maincode desse arquivo
    http://www.mediafire.com/file/h13d0hcax8xl5e1/SPYDER_V01_013.rar/file

    Comment by antonio vilarinho — May 17, 2020 @ 8:53 pm | Reply

  29. it would be possible to show how to extract the maincode from that file
    http://www.mediafire.com/file/h13d0hcax8xl5e1/SPYDER_V01_013.rar/file

    Comment by antonio vilarinho — May 17, 2020 @ 9:03 pm | Reply

  30. nanwon.or.kr

    Reverse engineering an obfuscated firmware image E01 – unpacking | .braindump – RE and stuff

    Trackback by nanwon.or.kr — September 30, 2021 @ 3:38 pm | Reply

  31. http://www.allamfortrade.com

    Reverse engineering an obfuscated firmware image E01 – unpacking | .braindump – RE and stuff

    Trackback by http://www.allamfortrade.com — September 30, 2021 @ 8:09 pm | Reply

  32. simpleblog-site.c1.biz

    Reverse engineering an obfuscated firmware image E01 – unpacking | .braindump – RE and stuff

    Trackback by simpleblog-site.c1.biz — September 30, 2021 @ 8:52 pm | Reply

  33. 토토사이트 순위

    Reverse engineering an obfuscated firmware image E01 – unpacking | .braindump – RE and stuff

    Trackback by 토토사이트 순위 — July 13, 2023 @ 7:29 am | Reply

  34. 토토사이트먹튀검증

    Reverse engineering an obfuscated firmware image E01 – unpacking | .braindump – RE and stuff

    Trackback by 토토사이트먹튀검증 — July 13, 2023 @ 8:42 pm | Reply

  35. 카지노추천

    Reverse engineering an obfuscated firmware image E01 – unpacking | .braindump – RE and stuff

    Trackback by 카지노추천 — July 15, 2023 @ 11:58 am | Reply

  36. […] the ‘Unzipping firmware…’ message was particularly interesting; a bit of Googling turned up this post on reversing Arcadyan firmware obfuscation, though it appears to be different from the obfuscation […]

    Pingback by Reversing the WRT120N’s Firmware Obfuscation – /dev/ttyS0 - Calculating Infinity — January 7, 2024 @ 7:10 am | Reply


RSS feed for comments on this post. TrackBack URI

Leave a reply to simpleblog-site.c1.biz Cancel reply

Blog at WordPress.com.