Results 1 to 9 of 9

Thread: TP-LINK router config compression

  1. #1
    Administrator Shelwien's Avatar
    Join Date
    May 2008
    Location
    Kharkov, Ukraine
    Posts
    3,977
    Thanks
    296
    Thanked 1,305 Times in 741 Posts

    TP-LINK router config compression

    I've got this TL-WR840N router, but it lacks detailed wifi settings.
    So I decided to download the config from it and edit it manually - it worked before with other routers.
    But in this case the result was a random-looking binary blob.
    I googled it and found how to decrypt it: http://teknoraver.net/software/hacks/tplink/
    But after decrypting, it turned out that since then they also added some LZSS-looking obscure compression.
    I tried to write a decoder, but it wasn't so easy - had to reverse-engineer the decoder from https://www.nirsoft.net/utils/router..._recovery.html
    (this utility decodes this type of config, but there's no option to encode it back).
    So I made my own encoder for it and it seems to work all right (edited the config, uploaded it to the router and it works).

    http://nishi.dreamhosters.com/u/lztp_v1.rar (with sources)

    See decode.inc - maybe somebody can identify the method?

    struct lztp_t {
    byte hash[16];
    uint size;
    };

    uint bitbuf, bitnum;

    uint getbit( void ) {
    uint r;
    if( bitnum==0 ) {
    bitbuf = byte(get());
    bitbuf|= 256*byte(get());
    bitnum =16;
    }
    r = (bitbuf>>15)&1; bitbuf<<=1; bitnum--;
    return r;
    }

    uint getvar( void ) {
    uint r = 1; do r = 2*r + getbit(); while( getbit() );
    return r;
    }

    int decode( void ) {
    uint c,i, winptr, id, l,d;

    enum{ winlog=16, winsize=1<<winlog, winmask=winsize-1 };
    byte win[winsize];

    lztp_t hdr;
    for( i=0; i<sizeof(hdr); i++ ) if( (c=get())==-1 ) break; else ((byte*)&hdr)[i]=c;
    if( c==-1 ) return -1;

    winptr=0; bitbuf=0; bitnum=1;
    while( winptr<hdr.size ) {
    id = getbit();
    if( id==0 ) {
    // literal
    c = byte(get());
    put( win[(winptr++)&winmask]=c );
    } else {
    // match
    l = getvar()-2+4;
    d = (getvar()-2)*256;
    d+= byte(get()) + 1;
    while( l-- ) {
    c = win[(winptr-d)&winmask];
    put( win[(winptr++)&winmask]=c );
    }
    } // if id
    } // while

    return 0;
    }

  2. Thanks (3):

    arroyo (26th September 2018),encode (22nd March 2019),kaitz (8th September 2018)

  3. #2
    Member
    Join Date
    Sep 2018
    Location
    Czech Republic
    Posts
    2
    Thanks
    1
    Thanked 0 Times in 0 Posts
    First of all I would like to thank you for your great work.
    It works perfectly with WR840N.
    I tried to decrypt a config file of Archer C2v1 and it works perfectly also.
    But if I try to decrypt a config file of Archer C2v3, decryption will not pass.
    Do you have any information about some changes of the cryption key or compression metod?

  4. #3
    Administrator Shelwien's Avatar
    Join Date
    May 2008
    Location
    Kharkov, Ukraine
    Posts
    3,977
    Thanks
    296
    Thanked 1,305 Times in 741 Posts
    1. Some TP-LINK routers just don't have the compression stage. Try simply decrypting?
    2. Try https://www.nirsoft.net/utils/router..._recovery.html
    3. If nirsoft utility works, I can try finding what it does, if you'd give me a sample of encrypted config.

  5. #4
    Member
    Join Date
    Sep 2018
    Location
    Czech Republic
    Posts
    2
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Yes I tried RouterPassView and unfortunately decryption did non pass.
    I am affraid they changed decryption key.

  6. #5
    Administrator Shelwien's Avatar
    Join Date
    May 2008
    Location
    Kharkov, Ukraine
    Posts
    3,977
    Thanks
    296
    Thanked 1,305 Times in 741 Posts
    Well, you can read this: http://teknoraver.net/software/hacks/tplink/
    and try extracting httpd binary from it.

  7. #6
    Member
    Join Date
    Apr 2017
    Location
    United Kingdom
    Posts
    82
    Thanks
    64
    Thanked 33 Times in 21 Posts
    Quote Originally Posted by Shelwien View Post
    See decode.inc - maybe somebody can identify the method?
    Frankly, this looks like some sort of custom variation on hundreds of existing small platform LZSS packers.

    The fact that it uses "interlaced" Exp-Golomb-1 code suggests that this is likely to be a relatively modern scheme (for example, I never saw Exp-Golomb-1 used in packers for 8-bit platforms written in the 1990s). I am pretty sure that the use of Exp-Golomb-1 to encode match lengths is not a good idea for most kinds of data I used in the past, which makes it less likely to be an existing scheme taken from elsewhere. At the same time, the use of Exp-Golomb-1 for the top bits of offsets is likely to be pretty efficient.

  8. #7
    Administrator Shelwien's Avatar
    Join Date
    May 2008
    Location
    Kharkov, Ukraine
    Posts
    3,977
    Thanks
    296
    Thanked 1,305 Times in 741 Posts
    The question is how their original encoder was supposed to work.
    Normal LZSS (with packed literal flags) just can have a fixed-size token buffer.
    While here I had to use two passes for encoding - normal encoding with two output streams
    and 2-to-1 stream transform based on decoding (it interleaves data bytes in order of decoder access).
    It'd be much more complicated if I tried to make it single-pass - I'd have to maintain variable-length
    token queue and bit/byte streams and async decoder and encoder steps.
    I wonder if I'm missing some simple way to do this.

  9. #8
    Member
    Join Date
    Apr 2017
    Location
    United Kingdom
    Posts
    82
    Thanks
    64
    Thanked 33 Times in 21 Posts
    All compressors of this kind that I know of would typically have some kind of internal representation of the graph corresponding to the LZSS encoding. The greedy parser, lazy evaluator or some other kind of optimizer would typically try minimizing the number of bits in compressed representation (without actually generating the compressed stream). During the first pass they would choose the path through the graph; during the second pass they would actually generate the binary representation for the compressed stream.

    I suspect this is pretty much exactly what you ended up doing. I do not know of any single-pass schemes that would be applicable to the mixed bit/byte compressed data streams.

  10. #9
    Administrator Shelwien's Avatar
    Join Date
    May 2008
    Location
    Kharkov, Ukraine
    Posts
    3,977
    Thanks
    296
    Thanked 1,305 Times in 741 Posts
    Its probably something different in this case.
    Maybe memory-to-memory implementation allows to make it simple somehow (instead of my streams).
    Because what I implemented is a simple greedy parser, and it still provides better compression than original.
    (original: 5176, mine: 4319).

Similar Threads

  1. batch for vpn auto reconnect (8.1 or 10 tp)
    By necros in forum The Off-Topic Lounge
    Replies: 2
    Last Post: 22nd November 2014, 04:40
  2. Replies: 3
    Last Post: 23rd February 2011, 20:32
  3. Web Chat Link
    By encode in forum The Off-Topic Lounge
    Replies: 0
    Last Post: 30th October 2010, 17:57

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •