Skip to content

Instantly share code, notes, and snippets.

@thedroidgeek
Last active May 31, 2024 13:12
Show Gist options
  • Save thedroidgeek/80c379aa43b71015d71da130f85a435a to your computer and use it in GitHub Desktop.
Save thedroidgeek/80c379aa43b71015d71da130f85a435a to your computer and use it in GitHub Desktop.
Nokia/Alcatel-Lucent router backup configuration tool
#!/usr/bin/env python3
#
# Nokia/Alcatel-Lucent router backup configuration tool
#
# Features:
# - Unpack/repack .cfg files generated from the backup and restore functionnality
# in order to modify the full router configuration
# - Decrypt/encrypt the passwords/secret values present in the configuration
#
# Blog post: https://0x41.cf/reversing/2019/10/08/unlocking-nokia-g240wa.html
#
# Released under the MIT License (http://opensource.org/licenses/MIT)
# Copyright (c) Sami Alaoui Kendil (thedroidgeek)
#
import sys
import zlib
import struct
import base64
import binascii
import datetime
big_endian = True
encrypted_cfg = False
def u32(val):
return struct.unpack('>I' if big_endian else '<I', val)[0]
def p32(val):
return struct.pack('>I' if big_endian else '<I', val)
def checkendian(cfg):
if (cfg[0:4] == b'\x00\x12\x31\x23'):
return True
elif (cfg[0:4] == b'\x23\x31\x12\x00'):
return False
else:
return None
class RouterCrypto:
def __init__(self):
from Crypto.Cipher import AES
# key and IV for AES
key = '3D A3 73 D7 DC 82 2E 2A 47 0D EC 37 89 6E 80 D7 2C 49 B3 16 29 DD C9 97 35 4B 84 03 91 77 9E A4'
iv = 'D0 E6 DC CD A7 4A 00 DF 76 0F C0 85 11 CB 05 EA'
# create AES-128-CBC cipher
self.cipher = AES.new(bytes(bytearray.fromhex(key)), AES.MODE_CBC, bytes(bytearray.fromhex(iv)))
def decrypt(self, data):
output = self.cipher.decrypt(data)
# remove PKCS#7 padding
return output[:-ord(output[-1:])]
def encrypt(self, data):
# add PKCS#7 padding for 128-bit AES
pad_num = (16 - (len(data) % 16))
data += chr(pad_num).encode() * pad_num
return self.cipher.encrypt(data)
#
# unpack xml from cfg
#
if (len(sys.argv) == 3 and sys.argv[1] == '-u'):
# line feed
print('')
# read the cfg file
cf = open(sys.argv[2], 'rb')
cfg_data = cf.read()
# check cfg file magic (0x123123) and determine endianness
big_endian = checkendian(cfg_data)
if big_endian == None:
# check if config is encrypted
decrypted = None
try:
# decrypt and check validity
decrypted = RouterCrypto().decrypt(cfg_data)
big_endian = checkendian(decrypted)
except ValueError:
pass
# if decryption failed, or still invalid, bail out
if big_endian == None:
print('invalid cfg file/magic :(\n')
exit()
# set decrypted cfg buffer and encryption flag
print('-> encrypted cfg detected')
cfg_data = decrypted
encrypted_cfg = True
# log endianness
if big_endian:
print('-> big endian CPU detected')
else:
print('-> little endian CPU detected')
# get fw_magic (unknown, could be fw version/compile time, hw serial number, etc.)
fw_magic = u32(cfg_data[0x10:0x14])
print('-> fw_magic = ' + hex(fw_magic))
# get the size of the compressed data
data_size = u32(cfg_data[4:8])
# get the compressed data
compressed = cfg_data[0x14 : 0x14 + data_size]
# get the checksum of the compressed data
checksum = u32(cfg_data[8:12])
# verify the checksum
if (binascii.crc32(compressed) & 0xFFFFFFFF != checksum):
print('\nCRC32 checksum failed :(\n')
exit()
# unpack the config
xml_data = zlib.decompress(compressed)
# output the xml file
out_filename = 'config-%s.xml' % datetime.datetime.now().strftime('%d%m%Y-%H%M%S')
of = open(out_filename, 'wb')
of.write(xml_data)
print('\nunpacked as: ' + out_filename)
print('\n# repack with:')
print('%s %s %s %s\n' % (sys.argv[0], ('-pb' if big_endian else '-pl') + ('e' if encrypted_cfg else ''), out_filename, hex(fw_magic)))
cf.close()
of.close()
#
# generate cfg from xml
#
elif (len(sys.argv) == 4 and (sys.argv[1][:3] == '-pb' or sys.argv[1][:3] == '-pl')):
fw_magic = 0
try:
# parse hex string
fw_magic = int(sys.argv[3], 16)
# 32-bit check
p32(fw_magic)
except:
print('\ninvalid magic value specified (32-bit hex)\n')
exit()
big_endian = sys.argv[1][:3] == '-pb'
encrypted_cfg = sys.argv[1][3:] == 'e'
out_filename = 'config-%s.cfg' % datetime.datetime.now().strftime('%d%m%Y-%H%M%S')
# read the xml file
xf = open(sys.argv[2], 'rb')
xml_data = xf.read()
xf.close()
# compress using default zlib compression
compressed = zlib.compress(xml_data)
## construct the header ##
# magic
cfg_data = p32(0x123123)
# size of compressed data
cfg_data += p32(len(compressed))
# crc32 checksum
cfg_data += p32(binascii.crc32(compressed) & 0xFFFFFFFF)
# size of xml file
cfg_data += p32(len(xml_data) + 1)
# fw_magic
cfg_data += p32(fw_magic)
# add the compressed xml
cfg_data += compressed
# encrypt if necessary
if encrypted_cfg:
cfg_data = RouterCrypto().encrypt(cfg_data)
# write the cfg file
of = open(out_filename, 'wb')
of.write(cfg_data)
of.close()
print('\npacked as: ' + out_filename + '\n')
#
# decrypt/encrypt secret value
#
elif (len(sys.argv) == 3 and (sys.argv[1] == '-d' or sys.argv[1] == '-e')):
decrypt_mode = sys.argv[1] == '-d'
if decrypt_mode:
# base64 decode + AES decrypt
print('\ndecrypted: ' + RouterCrypto().decrypt(base64.b64decode(sys.argv[2])).decode('UTF-8') + '\n')
else:
# AES encrypt + base64 encode
print('\nencrypted: ' + base64.b64encode(RouterCrypto().encrypt(sys.argv[2].encode())).decode('UTF-8') + '\n')
else:
print('\n#\n# Nokia/Alcatel-Lucent router backup configuration tool\n#\n')
print('# unpack (cfg to xml)\n')
print(sys.argv[0] + ' -u config.cfg\n')
print('# pack (xml to cfg)\n')
print(sys.argv[0] + ' -pb config.xml 0x13377331 # big endian, no encryption, fw_magic = 0x13377331')
print(sys.argv[0] + ' -pl config.xml 0x13377331 # little endian, ...')
print(sys.argv[0] + ' -pbe config.xml 0x13377331 # big endian, with encryption, ...')
print(sys.argv[0] + ' -ple config.xml 0x13377331 # ...\n')
print('# decrypt/encrypt secret values within xml (ealgo="ab")\n')
print(sys.argv[0] + ' -d OYdLWUVDdKQTPaCIeTqniA==')
print(sys.argv[0] + ' -e admin\n')
@Padke9
Copy link

Padke9 commented May 15, 2024

Here is hash password
root:$1$GTMUOzhf$mjhy6wET5re92IB4KHqXz.
pass:-LA(ImvZx%8

@Heaven-Is-Myth-Nepal-Is-Real
Copy link

$5$ml5m3FS4jai3Ic1Q$1rU3UrvBt8Zu39I/jmM3rwFI86AJCjXbuom3LlBWYl6
this is the Wordlink new password in hash format cracked this one
too
$5$UqWsQaG1XwNyGz/5$YZRmV5KRnhziJpQuB4mVCA4gn5hwhQOJZ8/vKx3YVYB Possible algorithms: sha256crypt $5$, SHA256 (Unix)

@Padke9
Copy link

Padke9 commented May 20, 2024

how could i decrypt these

<DebugDyPass. n="DyPass" t="staticObject">
<Enable rw="RW" t="boolean" v="false"/>
<PriKey ml="256" rw="R" t="string" v="/9dZA08iJtpdxQwLEN/PXRuvp/W8vthrcznIfPpvWl1bW71HTLPxGcvLgXbMSCT80n0uIV8m4a7D73M2jManOPCJHIGQ/oFNQAEY794iUXOMacgsEJKWycVv59paSz/8SJsjdjMHx4JooJIDXScEWRpxQ2MDCfKOFneBr37u3gtVsWbCwF333Jo=" ealgo="sab" kn="key11" ckn="key3"/>



<UserName ml="64" rw="RW" t="string" v="superadmin"/>
<Password ml="64" rw="RW" t="string" v="/9Iyf1nuW9Jvqbpt0rKmF14mMp9S6stqWg==" ealgo="sab" kn="key11" ckn="key3"/>
<PresetPassword ml="64" rw="RW" t="string" v="/+7bmhokKmku68N3wd0D7q1lQhQzGyBm/w==" ealgo="sab" kn="key11" ckn="key3"/>



<UserName ml="64" rw="RW" t="string" v="superuser"/>
<Password ml="64" rw="RW" t="string" v="/+FSdhRkyEVTdqnlACIuZqb+JEOjo2W9AQ==" ealgo="sab" kn="key11" ckn="key3"/>



<Username ml="256" rw="RW" t="string" v="hgw"/>
<Password ml="256" rw="RW" t="string" v="//buUg3QO21FJsSkPuSqUO+IAeZqYNQbpA==" ealgo="sab" kn="key11" ckn="key3"/>


<ServerPort dv="1813" max="65535" min="1" rw="RW" t="unsignedInt" v="1813"/>
<SecondaryServerPort dv="1813" max="65535" min="1" rw="RW" t="unsignedInt" v="1813"/>
<Secret dv="/wUulBnBDCo+gskG5zJ6oBSZkt1BuY3XKA==" ml="128" rw="RW" t="string" v="/2ctMVcrsk94G9fTQV0aZb5Uj8+CfA+a5Q==" ealgo="sab" kn="key11" ckn="key3"/>
<SecondarySecret dv="/8Lc9Ew+5WA61Wch0ChNpc73lgZkV3Dyzg==" ml="128" rw="RW" t="string" v="/wzcD2XHnlc4ohWWh22hMn3RD3TuSDXc3A==" ealgo="sab" kn="key11" ckn="key3"/>


@Padke9
Copy link

Padke9 commented May 20, 2024

$5$ml5m3FS4jai3Ic1Q$1rU3UrvBt8Zu39I/jmM3rwFI86AJCjXbuom3LlBWYl6
this is the Wordlink new password in hash format cracked this one
too
$5$UqWsQaG1XwNyGz/5$YZRmV5KRnhziJpQuB4mVCA4gn5hwhQOJZ8/vKx3YVYB Possible algorithms: sha256crypt 5, SHA256 (Unix)

hashcat -a 0 -m 7400 ck2.txt honeypot.txt

Session..........: hashcat
Status...........: Exhausted
Hash.Mode........: 7400 (sha256crypt $5$, SHA256 (Unix))
Hash.Target......: ck2.txt
Time.Started.....: Tue May 21 00:20:50 2024 (2 mins, 55 secs)
Time.Estimated...: Tue May 21 00:23:45 2024 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (honeypot.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 524 H/s (9.85ms) @ Accel:32 Loops:256 Thr:1 Vec:8
Recovered........: 0/2 (0.00%) Digests (total), 0/2 (0.00%) Digests (new), 0/2 (0.00%) Salts
Progress.........: 92016/92016 (100.00%)
Rejected.........: 0/92016 (0.00%)
Restore.Point....: 46008/46008 (100.00%)
Restore.Sub.#1...: Salt:1 Amplifier:0-1 Iteration:4864-5000
Candidate.Engine.: Device Generator
Candidates.#1....: lea -> LiaoNingLT
Hardware.Mon.#1..: Temp: 69c Util: 93%

have tried but seems my list does not have the password

I have Full Dump of firmware but cannot extract Ubi volume
i acn access only root volume and header volume of squash filesystem

@Padke9
Copy link

Padke9 commented May 20, 2024

ECIMAL HEXADECIMAL DESCRIPTION

1563908 0x17DD04 MySQL ISAM index file Version 8
6553634 0x640022 PGP RSA encrypted session key - keyid: 801000 1F RSA (Encrypt or Sign) 1024b
7794784 0x76F060 Linux kernel version 3.18.2
7809714 0x772AB2 bix header, header size: 64 bytes, header CRC: 0x0, created: 1970-01-01 00:04:16, image size: 21747 bytes, Data Address: 0x83800000, Entry Point: 0x645F, data CRC: 0x6D617465, image name: "ise_unique"
7986672 0x79DDF0 DES SP2, little endian
7987184 0x79DFF0 DES SP1, little endian
8071596 0x7B29AC AES S-Box
8072396 0x7B2CCC AES Inverse S-Box
8073780 0x7B3234 SHA256 hash constants, little endian
8117971 0x7BDED3 Neighborly text, "NeighborReqrRep"
8118027 0x7BDF0B Neighborly text, "NeighborRepsureReq"
8118376 0x7BE068 Neighborly text, "NeighborReqActionction"
8123135 0x7BF2FF Neighborly text, "NeighborRequestHandle_ActionHandle"
8123167 0x7BF31F Neighborly text, "NeighborResponseHandlexPacketBuffer"
8779148 0x85F58C xz compressed data
8796308 0x863894 Unix path: /lib/firmware/updates/3.18.21
9056436 0x8A30B4 Unix path: /etc/Wireless/RT2860AP_AC/RT30xxEEPROM.bin
9078888 0x8A8868 Unix path: /etc/Wireless/RT2860STA/RT2860STA.dat
9079048 0x8A8908 Unix path: /etc/wireless/l1profile.dat
9157740 0x8BBC6C XML document, version: "1.0"
9166472 0x8BDE88 Neighborly text, "Neighbor RSP02x:%02x:%02x:%02x:%02x:%02x), MeasureReqToken=%d"
9166932 0x8BE054 Neighborly text, "neighbor report frame"
9168375 0x8BE5F7 Neighborly text, "neighbor report response is meaninglessd "
9168581 0x8BE6C5 Neighborly text, "neighbor report frame failed"
9171197 0x8BF0FD Neighborly text, "NeighborAdvert: nextheader=0x%x, %d, %d"
9191449 0x8C4019 Neighborly text, "Neighbor Request from Peer IP = %d.%d.%d.%d, SSID = %stkd> Neighbor Response from Peer IP = %d.%d.%d.%d"
9191517 0x8C405D Neighborly text, "Neighbor Response from Peer IP = %d.%d.%d.%dcate type %d"
9193468 0x8C47FC Unix path: /etc/Wireless/RT2860STA/e2p.bin
9244612 0x8D0FC4 Unix path: /sys/firmware/devicetree/base
9257260 0x8D412C Unix path: /opt/upt/apps/info/reboot_info
9257400 0x8D41B8 Unix path: /opt/upt/apps/info/reboot_source
9288484 0x8DBB24 Neighborly text, "NeighborSolicits6InDatagrams"
9288504 0x8DBB38 Neighborly text, "NeighborAdvertisementsorts"
9293838 0x8DD00E Neighborly text, "neighbor %.2x%.2x.%pM lost rename link %s to %s"
9491392 0x90D3C0 CRC32 polynomial table, little endian
9643904 0x932780 AES S-Box
9649600 0x933DC0 CRC32 polynomial table, little endian
9668858 0x9388FA Unix path: /etc/Wireless/RT2860/RT2860.dat
9669264 0x938A90 Unix path: /etc/Wireless/iNIC/iNIC_ap.dat
9669676 0x938C2C Unix path: /etc/Wireless/WIFI3/RT2870AP.dat
9670092 0x938DCC Unix path: /etc/Wireless/RT2860/RT2860_2G.dat;/etc/Wireless/RT2860/RT2860_5G.dat
9670564 0x938FA4 Unix path: /etc/Wireless/MT7615A_B0_5G.dat;/etc/Wireless/MT7615A_B1_5G.dat
9671029 0x939175 Unix path: /etc/wireless/mt7663e/mt7663e.1.dat
9671442 0x939312 Unix path: /etc/wireless/mt7663e/mt7663e.2.dat
9671838 0x93949E Unix path: /etc/Wireless/RT2860AP_AC/RT2860AP.dat
10966144 0xA75480 Flattened device tree, size: 831 bytes, version: 17

@muzammilshaik
Copy link

Hello Forks! Could someone guide me in unlocking the new version

Details:
Device Name G-2425G-A
Vendor Nokia
Serial Number ALCLB2A6079B
Hardware Version 3FE48299DEAA
Boot Version U-Boot-Dec-31-2016--12:00:00
Software Version 3FE49362JJIJ54

tried with the script mentioned in the forum getting the same error

Error:
image

@Banaune
Copy link

Banaune commented May 23, 2024

@Padke9 Which device are you using? Router or Beacon?

@SymenDruid
Copy link

SymenDruid commented May 28, 2024

Hi!

Thanks for your work, it's awesome!!

I've got two devices: an I-240W-A, and a G-240W-B.

I got ssh access on the G-one! But it logs me out immediately:

`[tulio@TulainasV5 G-240W-B]$ ssh -vvv admin@192.168.1.253 OpenSSH_8.4p1, OpenSSL 1.1.1i 8 Dec 2020 debug1: Reading configuration data /etc/ssh/ssh_config debug2: resolve_canonicalize: hostname 192.168.1.253 is address debug3: expanded UserKnownHostsFile '/.ssh/known_hosts' -> '/home/tulio/.ssh/known_hosts' debug3: expanded UserKnownHostsFile '/.ssh/known_hosts2' -> '/home/tulio/.ssh/known_hosts2' debug2: ssh_connect_direct debug1: Connecting to 192.168.1.253 [192.168.1.253] port 22. debug1: Connection established. debug1: identity file /home/tulio/.ssh/id_rsa type -1 debug1: identity file /home/tulio/.ssh/id_rsa-cert type -1 debug1: identity file /home/tulio/.ssh/id_dsa type -1 debug1: identity file /home/tulio/.ssh/id_dsa-cert type -1 debug1: identity file /home/tulio/.ssh/id_ecdsa type -1 debug1: identity file /home/tulio/.ssh/id_ecdsa-cert type -1 debug1: identity file /home/tulio/.ssh/id_ecdsa_sk type -1 debug1: identity file /home/tulio/.ssh/id_ecdsa_sk-cert type -1 debug1: identity file /home/tulio/.ssh/id_ed25519 type -1 debug1: identity file /home/tulio/.ssh/id_ed25519-cert type -1 debug1: identity file /home/tulio/.ssh/id_ed25519_sk type -1 debug1: identity file /home/tulio/.ssh/id_ed25519_sk-cert type -1 debug1: identity file /home/tulio/.ssh/id_xmss type -1 debug1: identity file /home/tulio/.ssh/id_xmss-cert type -1 debug1: Local version string SSH-2.0-OpenSSH_8.4 debug1: Remote protocol version 2.0, remote software version dropbear_2016.74 debug1: no match: dropbear_2016.74 debug2: fd 3 setting O_NONBLOCK debug1: Authenticating to 192.168.1.253:22 as 'admin' debug3: hostkeys_foreach: reading file "/home/tulio/.ssh/known_hosts" debug3: record_hostkey: found key type ECDSA in file /home/tulio/.ssh/known_hosts:41 debug3: load_hostkeys: loaded 1 keys from 192.168.1.253 debug3: order_hostkeyalgs: have matching best-preference key type ecdsa-sha2-nistp256-cert-v01@openssh.com, using HostkeyAlgorithms verbatim debug3: send packet: type 20 debug1: SSH2_MSG_KEXINIT sent debug3: receive packet: type 20 debug1: SSH2_MSG_KEXINIT received debug2: local client KEXINIT proposal debug2: KEX algorithms: curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,ext-info-c debug2: host key algorithms: ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,[sk-ecdsa-sha2-.....................

Can you tell me how you managed to get the backup and restore page in the router's webUI? I have a G-240W-B as well but I can't get the cfg file. Tried changing the url, attempted all the different username/password combinations mentioned here, and even intercepted the login.cgi post request and didn't find anyway to unlock that page in the webUI.

I managed to get the root access on my G-140W-F and would like to do the same with this one. Any help is appreciated :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment