4

I have been trying to wrap my head round this stuff so bear with me.

I have a Tp-Link TX-VG1530. From the gui you can download the config file however the file is encrypted, I include a portion of the conf.bin file below

q=4‡|&YFË#Tùð¶¿Ä/1Þl^àh[Ú‹³lÙ€ÍÁ.©-&ÚdŠDT•°ôy®jò3R7B®5#B5m¨)½=Q›Î\òï-ÏÇëÄ+®‡h•Y‡Í@Ý úò%×ýÛâçó›Ð0&rŸØë÷vj[ñÛx¹Úm‡z†äí}Ös•qêQRsÆðèÍŽ’|Û˜’²³€¬#ìŸ4œä³½nÛÿl„¯~‚,•RÁgÏ;öÏËÀw‡§„,W‰×Jî <§x}ôžZñˆgFPdB§êÁ×gˆÑ=‰»uËžÏHžâKE¢¾.â˜/×3 Åæç±WÔ™ŒiõÁÕƒS\%*
Õ^çý­<w±ø”ð’´<ØmÎF1ˆÀqû§‘¥ðÛAÈÎ-ÿ1z”­9]ã7”…b«Yå[ö„*i'{ü'NŒÀç‘4ÑáÐm¹ü´B·U^wª½IÙ‚8û]³#)Lû-Diž

Using firmware modification kit I am able to extract the file system and looking at the upload page for the conf file (/web/main/backNRestore.htm) I can see the following

formObj.target = "up_frame";
formObj.action = "/cgi/confup";
formObj.submit();

Doing a quick grep I can see that /cgi/confup appears in /usr/bin/httpd. looking at this with IDA pro

enter image description here

From the following post I believe I should be able to retrieve the encryption method but I cannot seem to see anything relating to keys etc

http://teknoraver.net Decrypting TP-Link conf file

I include a link to the file here

httpd file link

Using the strings command on the file I see nothing that relates to aes, des, md5, key, dec, enc etc.

There are some tools such as tlrecode.sh which appear to decode the file slightly (this script seems to utilise the same key found in the teknoraver post), the decrypted file is not 100% though

×<?xml version="1.0"?>
<DslCpeConfig>
  <InternetGatewayDevice
  <Summa¯ry val=".:1.1[](Baseli`ne:1, EthVLA`N:1)"

Can anyone suggest the next steps to take

2
  • /cgi/confup seems to be registered to the function at 0x015744 which appears to parse the POST data for the file and then calls rdp_updateFirmware (imported function) and then reboots. I would look for the library where rdp_updateFirmware is defined.
    – cimarron
    Commented Nov 9, 2017 at 18:10
  • @cimarron many thanks for the tip. I will dig a bit deeper using this info. Commented Nov 10, 2017 at 8:04

2 Answers 2

4

It seems they also added compression there.
This utility seems to decode it:
https://www.nirsoft.net/utils/router_password_recovery.html
Also, I'd just written my own decoder and encoder for it:
https://encode.su/threads/3005-TP-LINK-router-config-compression

Decrypting:
openssl enc -d -des-ecb -K 478DA50BF9E3D2CF -nopad -in conf.bin -out conf.lztp

Unpacking:

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;
}

Compression algorithm is similar to LZSS - has interleaved streams of bits and bytes, rather than a single bit stream like eg. deflate. But unlike LZSS, also uses bit stream/bitcode for length and distance values.

3
  • Hi and welcome to RE.SE. Could you please include relevant algorithm for decryption, if possible (for your own tool!). Basically, if that linked hoster goes down or the forum closes down, your answer will be worthless. Thanks!
    – 0xC0000022L
    Commented Sep 5, 2018 at 12:43
  • Sure, didn't think of it.
    – Shelwien
    Commented Sep 5, 2018 at 15:43
  • @Shelwien great work, I have checked the tool myself and it works a treat. If you notice it has the serial in the config file which explains why when I upload the file to another device it changes the serial number of that device. I played around with tr69 with this unit but as the serial changes to the one in the config file I ended up with 10 devices all reporting under the same serial rendering it useless, good old TP-Link. Commented Sep 6, 2018 at 7:34
0

Adapted code Shelwien for linux/gcc

#define uint int
#define byte char
#define put(c) putchar(c)
#define get() getchar()
#include <stdio.h>


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

uint bitbuf, bitnum;

uint getbit( void ) {
  uint r;
  if( bitnum==0 ) {
    bitbuf = get();
    bitbuf|= 256*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 main( void ) {
  uint c,i, winptr, id, l,d;

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

  struct 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 = get();
      put( win[(winptr++)&winmask]=c );
    } else {
      // match
      l = getvar()-2+4;
      d = (getvar()-2)*256;
      d+= get() + 1;
      while( l-- ) {
        c = win[(winptr-d)&winmask];
        put( win[(winptr++)&winmask]=c );
      }
    } // if id
  } // while

  return 0;
}
1
  • Can you give an example of how to use this. I would also like to reencrypt after. Commented Aug 27, 2019 at 12:42

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.