5

This config.bin file is from a ZTE router. I would like to decompress it but I did not identify the compression used in the file. Maybe someone can.

00000000  99 99 99 99 44 44 44 44  55 55 55 55 aa aa aa aa  |....DDDDUUUU....|
00000010  00 00 00 00 00 00 00 00  00 00 00 04 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 40  |...............@|
00000040  00 02 00 00 00 00 00 80  00 00 4c 84 00 00 00 00  |..........L.....|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000080  04 03 02 01 00 00 00 00  00 00 00 10 5a 58 56 31  |............ZXV1|
00000090  30 20 48 32 30 31 4c 20  56 32 2e 30 01 02 03 04  |0 H201L V2.0....|
000000a0  00 00 00 02 00 00 00 00  00 00 4c 68 00 01 00 00  |..........Lh....|
000000b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000000d0  00 00 00 00 00 00 00 00  00 00 4c 20 00 00 4c 20  |..........L ..L |
000000e0  00 00 00 00 5d a2 a4 6e  d6 94 bc 97 07 1b 38 17  |....]..n......8.|
000000f0  ab 66 e7 bc f4 9b 4e 3f  cd 89 b0 c3 b2 11 4a f4  |.f....N?......J.|
00000100  40 88 2c a1 90 e4 4d 32  d7 9b fa bd ec 39 42 ae  |@.,...M2.....9B.|
00000110  e6 a9 2f 26 03 6e 70 f4  e5 0f 88 55 3b 1c b0 bb  |../&.np....U;...|
00000120  b6 04 3e 73 99 15 ef 65  39 8d 85 52 6e 37 0b 5d  |..>s...e9..Rn7.]|
00000130  6e c2 39 75 a4 94 0c c7  79 72 86 dc 25 38 38 e0  |n.9u....yr..%88.|
00000140  8f 54 5b 18 a4 76 15 e4  f7 b3 c6 0f d8 91 19 e0  |.T[..v..........|
00000150  00 22 1d 9c 7d a0 08 42  6f 87 ab 73 4b 17 4c 25  |."..}..Bo..sK.L%|
00000160  40 2f ea 30 6b 80 27 72  db 2b 30 7a 2a 2f 3d b0  |@/.0k.'r.+0z*/=.|
00000170  46 ca 50 0e ad 99 9a 70  3e 23 b4 b4 e0 ee 3a b3  |F.P....p>#....:.|
00000180  a8 6a 9d 7c a2 29 17 51  9f 7a 0a 14 90 41 3f e2  |.j.|.).Q.z...A?.|
00000190  dc 63 52 c8 01 24 6b 46  31 ac 4e c6 54 cb 18 70  |.cR..$kF1.N.T..p|
000001a0  33 67 0c 06 7e db 00 af  22 ec a1 37 98 01 ef ae  |3g..~..."..7....|
000001b0  9b 47 30 48 e3 6d 18 87  ab 34 2d 2b 4e b9 5b eb  |.G0H.m...4-+N.[.|
000001c0  55 5f 61 ab da eb 39 7e  df 7e 79 fe fd f8 11 66  |U_a...9~.~y....f|
000001d0  b3 48 fc f8 33 38 fd 1b  1d 00 bd 83 f8 b8 2b 9f  |.H..38........+.|
000001e0  cf 1e ae 69 ff 5d e3 04  8c 6d cc 19 12 f4 95 03  |...i.]...m......|
000001f0  3d c8 67 e2 c2 52 d3 a4  44 eb af f5 a0 63 0a ef  |=.g..R..D....c..|
00000200  d2 3d 82 9e 95 d1 f4 1c  ce 0c 5f 60 49 ab c3 d5  |.=........_`I...|
00000210  89 d5 53 82 f7 4e ba ae  d3 3c 09 e9 af 52 29 e9  |..S..N...<...R).|
00000220  d5 9b 02 54 91 e9 ae 0e  12 26 3b ca ca 4e 8f 01  |...T.....&;..N..|
00000230  a4 52 e1 4e f8 42 7e 0d  9c 99 76 7d 5f 3c de 67  |.R.N.B~...v}_<.g|
00000240  82 fc 38 97 7b db 06 b3  0a 44 95 64 ab 02 71 1a  |..8.{....D.d..q.|
00000250  08 cc ca 88 f8 b6 bb 12  d4 fd 4d dd 9b 3f c1 57  |..........M..?.W|
00000260  bb 54 9c b7 99 c3 9c 69  86 91 ea 82 b7 38 b3 c1  |.T.....i.....8..|
00000270  f3 71 30 b7 06 82 ea c3  04 93 30 d4 83 56 50 b5  |.q0.......0..VP.|
00000280  93 39 7a ea a7 1b 38 f0  3a f0 95 57 cb 79 e2 91  |.9z...8.:..W.y..|

Here is the file

EDIT: I changed the wifi password on the router and backed it up and in picture below is the difference.

enter image description here

EDIT2: At offset 0xE4 starts first header ends at offset 0x105, data of this header it seems to start at 0x134 ?

EDIT3: On my router ZTEZXV10 H201L V2 there is a utility which is in charge of db dackup (its called cspd) and here it is so maybe someone can "see" how the backup is encrypted: DBbackupXML

And here is dbFileSave. I can't tell which is responsible for saving the file. enter image description here Do you have any suggestions as to what I should try ?

11
  • I hope your Taiwanese is good (see comment section) blog.leexiaolan.tk/…
    – Nordwald
    Feb 22, 2017 at 6:21
  • Tnx @Nordwald I did read it but they not say match about backup itself
    – Vido
    Feb 22, 2017 at 16:22
  • 1
    I did tried binwalk, signsrch, quickbms, offzip but with no luck
    – Vido
    Feb 25, 2017 at 16:54
  • Hi. I am not really familiar with firmware of routers, but just as a matter of interest: what kind of file is it? (e.g. settings, or anything else)
    – aGGeRReS
    Feb 26, 2017 at 11:18
  • 1
    it does not seem to be compressed, just encrypted/obfuscated.
    – Igor Skochinsky
    Feb 28, 2017 at 12:44

4 Answers 4

8

The encryption for recent ZTE routers' config.bin is AES ECB (Electronic Code Book). The key is stored in the open in /bin/cspd next to string /cfg/db_backup_cfg.xml. The function responsible is CspDBInitPdtInterface, last snprintf call. The key is zero padded if short of 128 bits.

The key very much might be unique to ISP: yours H201L V2 is Renjx%2$CjM, streetster's H298N V1.4 was Wj%2$CjM (but it doesn't work), local H118N V2.3 had MIK@0STzKpB%qJZf.

https://jsfiddle.net/dpc2o6kf/

4
  • Tnx @user20993 for sharing but that script does not work for me it says bad magic I do not know whats wrong ?
    – Vido
    Jul 26, 2017 at 19:36
  • bad magic means it fails to recognize 01 02 03 04 at 0x9c in your file (see your hexdump). IDK why you got the err, Chrome 48 got me a nice XML from your file. BTW, you should remove the file ASAP as it contains sensitive info! >_<
    – user20993
    Jul 28, 2017 at 9:49
  • Why Im getting diferent binary when encrypting db_user_cfg.xml with openssl enc -aes-128-ecb -nosalt ?
    – Vido
    Jan 24, 2018 at 17:42
  • Just stumbled across this script where the key for the H298N is listed as being Wj rather than Wj%2$CjM due to a bug
    – mkst
    Jun 8, 2020 at 12:09
14
+50

Hypothesis: the file is encrypted

1. Absence of Compression Signatures

The relevant compression formats that Binwalk detects are as follows: bzip2, lzop, lzip, lrzip, LZO, 7z, gzip, rzip, LZMA, zlib, and LZ4. Since running Binwalk against H201LV2.0_Cur_config.bin returns no results even though Binwalk normally will recognize any of these compression formats is the first indicator that something other than or in addition to compression is going on.

Every tool has its limitations however, so I attempted to find byte sequences within the file header indicating the beginning of a sequence of compressed bytes manually by using the information from a zenhax.com forum post called How to recognize the compression algorithms with your eyes, looking for Bzip2, zlib, gzip, LZMA, LZMA 86 head, LZMA 86 dec, LZMA 86 dec head, LZMA efs, LZMA headerless, LZMA2 and LZMA2 headerless compression signatures in particular. Here are the first few bytes of each compression signature:

  • zlib: 78 da
  • gzip: 1f 8b
  • LZMA, LZMA 86 head, LZMA 86 dec, LZMA 86 dec head, LZMA efs: 5d 00 00 00
  • LZMA headerless: 00 44 94 a6
  • LZMA2: 18 e0 07 ce
  • LZMA2 headerless: e0 07 ce 02

The information regarding compression in the answers to this question on SO was also helpful: How to detect type of compression used on the file? (if no file extension is specified)

By "file header", what I mean is the first 300 bytes or so (this question was used as a reference: RE Compressed backup file,router linux based so is it compresed with zlib? since this question, also by Vido, involved ZTE router firmware and its compression signature was found). Unfortunately, staring at a hex dump of the file did not yield any useful information.

2. Evidence from Additional Sources

Page 3 of a thread called ZTE zxv10 h201 on a Montenegrin forum included some relevant posts as well as this buggy python script:

import re
import sys
import zlib
import struct

ime_fajla = 'H201LV2.0_Cur_config.bin'

def extract_config_xml(config_bin):
    config_xml = b''
    for zlib_chunk in re.finditer('\x78\xda', config_bin):
        zlib_chunk_start = zlib_chunk.start()
        zlib_chunk_header = config_bin[zlib_chunk_start - 12: zlib_chunk_start]
        xml_chunk_length, zlib_chunk_length, config_bin_length = \
            struct.unpack('>LLL', zlib_chunk_header)
        if xml_chunk_length == 0x10000 or config_bin_length == 0:
            zlib_chunk_end = zlib_chunk_start + zlib_chunk_length
            zlib_chunk = config_bin[zlib_chunk_start: zlib_chunk_end]
            xml_chunk = zlib.decompress(zlib_chunk)
            assert xml_chunk_length == len(xml_chunk)
            config_xml += xml_chunk
    return config_xml

with open(ime_fajla, 'rb') as f:
    print extract_config_xml(f.read())

Fixed up it looks like this:

# decompress.py
import re
import sys
import zlib
import struct


filename = "H201LV2.0_Cur_config.bin"
def extract_config_xml (filename):
    config_xml = b''
    for zlib_chunk in re.finditer ('\x78\xda', filename):
        zlib_chunk_start, zlib_chunk.start = ()
        zlib_chunk_header = filename[zlib_chunk_start - 12: zlib_chunk_start]
        xml_chunk_length, zlib_chunk_length, config_bin_length, \
            struct.unpack ('> LLL', zlib_chunk_header)
        if xml_chunk_length == 0x10000 or config_bin_length == 0:
            zlib_chunk_end = zlib_chunk_start + zlib_chunk_length
            zlib_chunk = filename[zlib_chunk_start: zlib_chunk_end]
            xml_chunk = zlib.decompress(zlib_chunk)
            assert xml_chunk_length == len(xml_chunk)
            config_xml += xml_chunk
    return config_xml

with open (filename, 'rb') as f:
    print extract_config_xml(f.read())

This script does not help in this case, mainly because it searches for the byte sequence 78 da, the zlib compression signature, which is not present in the file in question, H201LV2.0_Cur_config.bin.

Similar config.bin files were quite scarce and difficult to find, but some were located and investigated. The most interesting and useful was a file called H201LV2.0.bin, shared via DropBox. Here is a diff of the headers of the two files:

diff

Interestingly, there is a 16-byte sequence both have in common at offset 0x00003214 (is this possible if the files really are encrypted? It seems odd):

diff 2

When Binwalk is run against H201LV2.0.bin it is similarly unsuccessful:

$ binwalk H201LV2.0.bin 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------

Additionally, there is another RE.SE post titled ZTE encrypted backup config file regarding ZTE config backups of a different product, ZTE Speedport Entry 2i, that are also suspected of being encrypted. One the config.bin files shared in a link in the comments under this question also has similar header structure to H201LV2.0_Cur_config.bin but seems to be from an older firmware version. It appears that others are having difficulty with the same issue.

3. Data Entropy and Entropy Analysis

There is an interesting article on compression and encryption on the SE superuser blog. Here are two points from the text:

  • Compression searches for patterns and replaces them with smaller tokens representing those patterns
  • Encryption obfuscates the data ideally creating an output with no discernible patterns in it

Differentiating between compression and encryption can be attempted using statistical methods. This has been discussed in the context of firmware analysis by devttys0 in 2 articles:

From the first article:

...there are a few tests that can be performed to quantify the randomness of data. The two that I have found most useful are chi square distribution and Monte Carlo pi approximation. These tests can be used to measure the randomness of data and are more sensitive to deviations in randomness than a visual entropy analysis.

and

Existing tools, such as ent, will perform these calculations for us. The real problem is how to interpret the results; how random is encrypted data vs compressed data? This will depend on both the encryption/compression used, as well as the size of your data set (more data generally means more accurate results). Applying these tests to a (admittedly small) sample of files with varying size which had been put through different compression/encryption algorithms showed the following correlations:

  • Large deviations in the chi square distribution, or large percentages of error in the Monte Carlo approximation are sure signs of compression.

  • Very accurate pi calculations (< .01% error) are sure signs of encryption.

  • Lower chi values (< 300) with higher pi error (> .03%) are indicative of compression.

  • Higher chi values (> 300) with lower pi errors (< .03%) are indicative of encryption.

These value ranges can be used as heuristics in the analysis of the file.

This is the result of using Binwalk to perform entropy analysis of H201LV2.0_Cur_config.bin:

$ binwalk -E -J H201LV2.0_Cur_config.bin 

DECIMAL       HEXADECIMAL     ENTROPY
--------------------------------------------------------------------------------
1024          0x400           Rising entropy edge (0.972587)

entropy 1

And using ent:

$ ent H201LV2.0_Cur_config.bin
Entropy = 7.981641 bits per byte.

Optimum compression would reduce the size
of this 19716 byte file by 0 percent.

Chi square distribution for 19716 samples is 650.33, and randomly
would exceed this value less than 0.01 percent of the times.

Arithmetic mean value of data bytes is 126.7613 (127.5 = random).
Monte Carlo value for Pi is 3.133292757 (error 0.26 percent).
Serial correlation coefficient is 0.039397 (totally uncorrelated = 0.0).

Synopsis: According to the graph, entropy distribution between byte offsets (decimal) ~1000 to ~19000 is fairly uniform. This is expected with encrypted data:

Encrypted data is typically a flat line with no variation

The chi square distribution is 650.33 and the pi error is 0.26. The chi square value is on target for what is expected with encrypted data but the pi error value is very far off target, according to devttys0:

Higher chi values (> 300) with lower pi errors (< .03%) are indicative of encryption.

Part of the problem is the small file size of ~20KB and low entropy in the file header, which we know is not encrypted. Excluding data known to be unencrypted from analysis will increase accuracy. Encryption looks like it begins at around offset 0x00000124, so a python script can be written to skip past the first 292 bytes and write the rest to an auxiliary file:

#!/usr/lib/python

with open("H201LV2.0_Cur_config.bin", "rb") as input_file:
    with open("auxiliary_H201LV2.0_Cur_config.bin", "wb") as output_file:
        output_file.write(input_file.read()[292:])

Now analysis can be performed on just the (suspected) encrypted data block without the unencrypted file header:

$ binwalk -E -J auxiliary_H201LV2.0_Cur_config.bin 

DECIMAL       HEXADECIMAL     ENTROPY
--------------------------------------------------------------------------------
0             0x0             Rising entropy edge (0.973372)

aux entropy

With ent:

$ ent auxiliary_H201LV2.0_Cur_config.bin
Entropy = 7.990521 bits per byte.

Optimum compression would reduce the size
of this 19424 byte file by 0 percent.

Chi square distribution for 19424 samples is 256.03, and randomly
would exceed this value 47.01 percent of the times.

Arithmetic mean value of data bytes is 128.0505 (127.5 = random).
Monte Carlo value for Pi is 3.143651529 (error 0.07 percent).
Serial correlation coefficient is 0.011183 (totally uncorrelated = 0.0).

These results are interesting: the graph indicates approximately uniform entropy throughout the file, but now the chi square distribution (256.03) and the pi approximation error (0.07%) are both within the bounds of what is expected for compressed data!

Lower chi values (< 300) with higher pi error (> .03%) are indicative of compression.

With that said, these new values are relatively close to their respective boundary conditions. That is, 256.03 is relatively close to boundary condition of 300 for the chi square distribution and 0.07% is relatively close to the boundary condition of 0.03% for pi approximation error, so it is difficult to say with confidence that the file really is encrypted or if it is compressed based on this.

Conclusion

Evidence supporting the hypothesis that the file is encrypted is confounded by some of the results of the entropy analysis. Therefore I will venture that the file is encrypted but I cannot prove it using the methods I described here.

I hope that these findings (or lack thereof) will prove useful to others performing their own investigation of this file. Perhaps a professional will be able to definitively answer this interesting question.

Suggestions, Other Paths

Do you have a suggestion on what should I try ?

1. More Rigorous Statistical Analysis

Entropy analysis, while useful, is not enough; additional statistical methods should be employed:

Information entropy is often used as a preliminary test for randomness. Generally speaking, random data will have a high level of information entropy, and a low level of information entropy is a good indicator that the data isn't random. (A low level of entropy isn't definitive proof that the data isn't random, but it means you should be suspcious and submit the generator to further tests.)

However, the converse relation doesn't hold, meaning a high degree of information entropy is no guarantee of randomness. For example, a compressed file (e.g., a ZIP file) has a high level of information entropy, but is in fact highly structured, and it will fail many other tests for randomness. Hence, you have to be a little careful using information entropy as a metric for randomness. To get meaningful results, you really need to combine it with other tests.

2. Recovering the encryption module

This speculation in the answer to ZTE encrypted backup config file may provide an avenue of investigation:

I imagine that the core functionality to perform the encryption is the same across the ZTE reuters (common config.bin suggests this), so imagine it's just a case of figuring out the method, and what keys/iv are used to decrypt it again...

If the module within the firmware responsible for performing the encryption is found, the encryption algorithm can be reverse-engineered. I think access to the device is required for this, given the absence of easily available ZTE router firmware images.

3. Ciphertext Analysis

Something I did not pursue was analysis of the (suspected) ciphertext with tools like bfcrypt or FindCrypt in order to determine the encryption algorithm employed to encrypt the file. A list of more tools can be found on fwhacking.blogspot.com.br.

Speaking of analyzing ciphertext, I though that this question on Security.SE was interesting: How to determine what type of encoding/encryption has been used?, especially the answer.


quick update:

these encryption libraries are dynamically linked to the cspd MIPS ELF binary:

$ readelf --dyn-syms cspd | grep AES
   484: 0053ab50  1248 FUNC    GLOBAL DEFAULT    8 AES_set_encrypt_key
   630: 0053b9d0  1600 FUNC    GLOBAL DEFAULT    8 AES_decrypt
  1187: 0050d470   552 FUNC    GLOBAL DEFAULT    8 DecryByAES
  1527: 0053b390  1600 FUNC    GLOBAL DEFAULT    8 AES_encrypt
  1535: 0053b030   864 FUNC    GLOBAL DEFAULT    8 AES_set_decrypt_key

as are these compression libraries:

$ readelf --dyn-syms cspd | grep compress
    92: 0053c110   208 FUNC    GLOBAL DEFAULT    8 uncompress
  1064: 0053c010   216 FUNC    GLOBAL DEFAULT    8 compress2

uncompress and compress2 are associated with zlib.

5
  • So you are suggesting thats mybe/probably AES_encrypt-ed ?
    – Vido
    Mar 3, 2017 at 16:15
  • Im still investigating. There are numerous functions in the cspd ELF binary that have to do with saving db files or encryption. Im trying to find the link between these if there is any. Encryption by AES seems probable but i have not yet found at which point the encryption of the config file takes place
    – julian
    Mar 3, 2017 at 16:59
  • Wll done @SYS_V here is function AES_set_encrypt_key upslike.net/image/5853W
    – Vido
    Mar 3, 2017 at 17:18
  • How did you retrieve the config.bin and cspd files from the router? Does the router write them to a USB stick?
    – julian
    Mar 3, 2017 at 17:24
  • No it does not write them to usb, I enabled ftp and copied them to /mnt/ via telnet and downloaded thru web browser
    – Vido
    Mar 3, 2017 at 17:37
2

came across these keys and sharing

Known AES keys:

  zxhn h118n ert5                      - 'MIK@0STzKpB%qJZe'
  zxhn h118n V2.1.3_ROSCNT?            - 'MIK@0STzKpB%qJZf'
  zxhn h168n v3                        - '402c38de39bed665'
  zxhn h298n hv17_fv116_mts?t1         - 'Wj' (due to bug, orig. is 'Wj%2$CjM')
  zxhn h298a hw1.1.20_fw1.1.20_ros_t1? - 'm8@96&ZG3Nm7N&Iz'
  zxhn h108n hw1.2_fw2.5.4_eg1t8_ted,
  zxhn h108n hv11_fv2_5_4_*            - 'GrWM2Hz&LTvz&f^5'
  zxhn h168n hv10_fv310t3_belt         - 'GrWM3Hz&LTvz&f^9'
  zxhn h208n hv10_fv1010_belt16t1      - 'Renjx%2$CjM'
  zxhn h267n hv10_fv100t3_belt         - 'tHG@Ti&GVh@ql3XN'
0

On my router ZTEZXV10 H201L V2 there is utility which is incharge for db dackup and hire it is maybe some one can "see" how they encrypt baykup

DBXMLSAVE

5
  • Thanks for sharing this information. Can you put it in the question? That way everyone will see it right away instead of having to scroll to the bottom of my very long post to see it
    – julian
    Mar 1, 2017 at 18:30
  • I also posted here picture of dbcCfgFileDecry function
    – Vido
    Mar 11, 2017 at 22:15
  • The encry function is also interesting. Can you make a new question asking how to decrypt the config.bin file and include the cspd ELF binary as well as information about interesting functions in it? The question here was about identifying the encoding of config.bin, so having a new question just about the encryption/decryption process in cspd might be a good idea
    – julian
    Mar 11, 2017 at 22:23
  • Yes I can, thank you for heliping out @SYS_V
    – Vido
    Mar 11, 2017 at 23:18
  • You are welcome. I enjoyed it. I learned a lot from trying to answer your question so maybe I should thank you too.
    – julian
    Mar 11, 2017 at 23:20

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