giovedì 26 marzo 2020

Tp-Link CPE-510/520 "new" Config.bin structure: Decryption, modify, re-encryption



So far, seems nobody has yet relased a tool to decrypt such kind of config structure.
By doing only static analysis we'll take a look how to figure out the new TP-Link CPE-510/520  (probably also TP-Link CPE-210/2200 and others) config.bin structure by using Ghidra.
I neither have the CPE :)



Index:
0 - Hardware overview and firmware extracting
1 - uclited ELF static analysis with Ghidra
  1.1 - config.bin file structure
  1.2 - Extracting decryption key
  1.3 - TP-Link MD5 config signature tricky calculation
2 - config.bin decryption script
3 - Re-creation of a new modified config.bin
4 - Login md5 trick



0 - Hardware overview and firmware extracting

OpenWrt wiki provide us many hardware details:
CPE-510 is based on tipically mips_24kc instruction set, the bootloader is not the well known Uboot, because TP-Link has used their SafeLoader. This will be important later.

Let's download the TP-Link CPE-510 rev 3.0 firmware and examine it with binwalk:


We're interested in the squashfs partition, so let's quickly extract the image by using -e paramenter on binwalk and take a look on what the router once turned on by looking at the rcS script:
Before the httpd, a lower software surface, uclited , is executed.

1 - uclited ELF static analysis with Ghidra

I'm not a Ghidra big fan, but sometimes it's powerfull, expecially when I have a missing decompiler on IDA Pro. lol.
So, load the ELF on Ghidra and start having fun!


1.1 - config.bin file structure
Before proceeding and examining in ghidra we have to take a look on how the encrypted config.bin looks like:
In the file header there are just a few words in plaintext and at 0x94 (keep it in mind) we have undeadable informations. From my experience, this may be where the encrypted stuff starts.

1.2 - Extracting decryption key

There are several approaches to finding the routine we are interested in.
I'll skip how to find the routine (it's too long to write here), so go straight at the routine labled as
usrconf_load @ 0x004272d0 which is the decryption config.bin routine.




The routine is almost self explanatory, anyway let's go over the highlights copared to the config.bin hex:

In the image above:
From 0x0 to 0x3 bytes are the file size. (4 bytes)
Next 0x10 bytes are the MD5 file hash. (0x10 bytes)
From 0x4 to 0x94 are the file header (device info, rev info, and other things). (0x90 bytes)
From 0x94 to EOF is the DES Encrypted data




The DES - ECB  routine  des_min_do(__src + 0x90,size - 0x90,__ptr,0x20000,(const_DES_cblock *)desConfigKey,0); act an encrytion with last paramenter as int 1 or decryption if set 0.

desConfigKey is the pointer to the key: 47 8d a5 0b f9 e3 d2 cf 
We can assume "__src + 0x90"  as our file pointer which is moved 4 bytes forward (the bytes of the file size at the beginning of the file)

We have now all the informations we need to decrypt the file.

1.3 - TP-Link MD5 config signature tricky calculation 
 





In the previous paragraph I deliberately highlighted the MD5 in blue for a specific reason, I do not understand why, but TP-Link do a particular thing in the calculation of the MD5 which will be:
Understanding those steps are esential to recreate the modified file:
1 step: the routine saves the 0x10 bytes readen from file offset 0x4 to 0x14. This is the final md5 that will be compared
2 step: the routine replaces 0x10 bytes with "47 8d a5 0b f9 e3 d2 cf 88 19 83 9d 4c 06 14 45"
3rd step: the routine calculates the md5 from 0x4 to EOF with the first 0x10 bytes shortly before replaced
4 step: the md5 result is compared to the one readen in the original file (saved during the step 1)

2 - config.bin decryption script



dd bs=1 skip=148 if=config.bin of=config_cut.bin 
openssl enc -d -des-ecb -nopad -K 478DA50BF9E3D2CF -in config_cut.bin >compressed.bin 
zlib-flate -uncompress  config.json
 
where 148=0x94 do you remember?... 
the config.json contains all the router informations including the login ones.


3 - Re-creation of a new modified config.bin

You can do it by yourself. Having all the informations you need, you can just recompress the modified .json, encrypt it again with openss, calculate back the new md5 as seen in the 1.3 paragraph and add the current file size + 0x4 and replace the first 4 bytes with the calculated value.

4 - Login md5 trick 
 If you forgot your router login password, in the config you'll have no plaintext password but the md5(password).
Do you need to brute the plaintext password which generates the corresponding MD5?

Considering that the browser, in local javascript, calculates and send the MD5 to the router, you dont need to waste your time.
A firefox Web console is enough to inject the md5 and get the login.



Cheers,

RE-Solver

2 commenti:

  1. This also works on the EAP series (tested on my EAP245), same key and everything.

    And thanks for saving me the work! Knew searching the symbols would help!

    RispondiElimina
  2. New in 2022

    ============================================
    Ralink UBoot Version: 5.0.0.0
    --------------------------------------------
    ASIC 7628_MP (Port5<->None)
    DRAM component: 512 Mbits DDR, width 16
    DRAM bus: 16 bit
    Total memory: 64 MBytes
    Flash component: SPI Flash
    Date:Nov 13 2018 Time:09:24:31
    ============================================
    icache: sets:512, ways:4, linesz:32 ,total:65536
    dcache: sets:256, ways:4, linesz:32 ,total:32768

    ##### The CPU freq = 580 MHZ ####
    estimate memory size =64 Mbytes
    RESET MT7628 PHY!!!!!!

    Please choose the operation:
    1: Load system code to SDRAM via TFTP.
    2: Load system code then write to Flash via TFTP.
    3: Boot system code via Flash (default).
    4: Entr boot command line interface.
    7: Load Boot Loader code then write to Flash via Serial.
    9: Load Boot Loader code then write to Flash via TFTP.
    default: 3 0

    3: System Boot system code via Flash.
    gpioMode1 Reg: 0x571504c4
    gpioMode2 Reg: 0x5550555
    tplink_turn_off_led
    ## Booting image at bc020000 ...

    root@OpenWrt:/usr/share# sh


    BusyBox v1.22.1 (2018-11-13 10:04:17 CST) built-in shell (ash)
    Enter 'help' for a list of built-in commands.

    root@OpenWrt:/usr/share# exit
    root@OpenWrt:/usr/share# help
    Built-in commands:
    ------------------
    . : [ [[ alias bg break cd chdir command continue echo eval exec
    exit export false fg getopts hash help history jobs kill let
    local printf pwd read readonly return set shift source test times
    trap true type ulimit umask unalias unset wait

    root@OpenWrt:/usr/share# exit
    Please press Enter to activate this console.



    BusyBox v1.22.1 (2018-11-13 10:04:17 CST) built-in shell (ash)
    Enter 'help' for a list of built-in commands.

    MM NM MMMMMMM M M
    $MMMMM MMMMM MMMMMMMMMMM MMM MMM
    MMMMMMMM MM MMMMM. MMMMM:MMMMMM: MMMM MMMMM
    MMMM= MMMMMM MMM MMMM MMMMM MMMM MMMMMM MMMM MMMMM'
    MMMM= MMMMM MMMM MM MMMMM MMMM MMMM MMMMNMMMMM
    MMMM= MMMM MMMMM MMMMM MMMM MMMM MMMMMMMM
    MMMM= MMMM MMMMMM MMMMM MMMM MMMM MMMMMMMMM
    MMMM= MMMM MMMMM, NMMMMMMMM MMMM MMMM MMMMMMMMMMM
    MMMM= MMMM MMMMMM MMMMMMMM MMMM MMMM MMMM MMMMMM
    MMMM= MMMM MM MMMM MMMM MMMM MMMM MMMM MMMM
    MMMM$ ,MMMMM MMMMM MMMM MMM MMMM MMMMM MMMM MMMM
    MMMMMMM: MMMMMMM M MMMMMMMMMMMM MMMMMMM MMMMMMM
    MMMMMM MMMMN M MMMMMMMMM MMMM MMMM
    MMMM M MMMMMMM M M
    M
    ---------------------------------------------------------------
    For those about to rock... (Attitude Adjustment, unknown)
    ---------------------------------------------------------------
    root@OpenWrt:/#

    Bye

    RispondiElimina