Nokia G-2425G-g - Unlock/Root ~ Step by Step detailed guide
Disclaimer : I'm not responsible if you brick your router in-between the process.
1. Open 192.168.1.1 in any browser
default username password both is admin
2. Go to Maintenance->backup and restore->export config file on your desktop
it will be saved as config.cfg
3. Download & install python on your pc
also download this file(python script) on your desktop
#!/usr/bin/env python3
#
# Nokia/Alcatel-Lucent router backup configuration tool
# G2425 support added by rajkosto on 20/11/2022
#
# 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
#
# Original author 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)
# Copyright (c) Rajko Stojadinovic (rajkosto)
#
import io
import sys
import zlib
import struct
import base64
import binascii
import datetime
import hashlib
import secrets
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)
# verify and remove PKCS#7 padding
padLen = ord(output[-1:])
if padLen <= 0 or padLen > 16: #cannot be 0 or > blocksize
return None
padBytes = output[-padLen:]
validPad = all(padByte == padLen for padByte in padBytes)
if validPad:
return output[:-padLen]
else:
return None
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)
class PKCSPassCrypto(RouterCrypto):
def __init__(self, pkcsPass, pkcsSalt):
from Crypto.Cipher import AES
from hashlib import pbkdf2_hmac
keyLen = 32 #AES-256
ivLen = 16 #AES blocksize
if not isinstance(pkcsPass, bytes):
pkcsPass = pkcsPass.encode()
pkcs = pbkdf2_hmac('sha256', pkcsPass, pkcsSalt, 10, dklen=keyLen+ivLen)
keyBytes = pkcs[:keyLen]
ivBytes = pkcs[keyLen:]
self.cipher = AES.new(keyBytes, AES.MODE_CBC, ivBytes)
#G2425 pkcs password
PKCSPasswords = ["S23l7nZm47XyMGs6y6oJpN9CR4nbfIZHJ4VRwp7HcdV6o2YvUmeNYFlz08Otwz78"]
#
# 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 = None
try:
xml_data = zlib.decompress(compressed)
pkcsPass = None
except zlib.error:
encData = None
pkcsSalt = None
tryPasswords = []
if compressed[0] == 0xFF: #pkcs encrypted payload
tryPasswords = PKCSPasswords
with io.BytesIO(compressed) as payload:
payload.seek(1)
pkcsSalt = payload.read(8)
encData = payload.read()
for currPass in tryPasswords:
decryptor = PKCSPassCrypto(currPass,pkcsSalt)
compressed = decryptor.decrypt(encData)
if compressed is None: #pkcs padding verification failed, key is wrong
continue
try:
xml_data = zlib.decompress(compressed)
pkcsPass = currPass
except zlib.error:
pass
if xml_data is None:
if len(tryPasswords):
raise RuntimeError('Exhausted all known encryption passwords')
else:
raise
# 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)
recompInfo = ('-pb' if big_endian else '-pl')
if encrypted_cfg or pkcsPass:
recompInfo += 'e'
if pkcsPass:
recompInfo += pkcsPass
print('\n# repack with:')
print('%s %s %s %s\n' % (sys.argv[0], recompInfo, 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:4] == 'e'
pkcsPass = None
if encrypted_cfg and len(sys.argv[1]) > 4:
pkcsPass = sys.argv[1][4:]
encrypted_cfg = False
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)
# pkcs encrypt the inner data if needed
extraDecompLen = 1 #non pkcs encrypted configs have +1 to decomp len
if pkcsPass is not None:
extraDecompLen = 0
with io.BytesIO() as payload:
payload.write(b'\xFF')
pkcsSalt = secrets.token_bytes(8)
payload.write(pkcsSalt)
cryptor = PKCSPassCrypto(pkcsPass,pkcsSalt)
payload.write(cryptor.encrypt(compressed))
compressed = payload.getvalue()
## 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) + extraDecompLen)
# fw_magic
cfg_data += p32(fw_magic)
# add the compressed xml
cfg_data += compressed
# encrypt overall file 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')Keep in mind that in order to restore a config to G2425, the file MUST be named
config.cfg or it will just do nothing with it.4. Open cmd
type
python C:\Users\XXXXX\Desktop\Nokia-router-cfg-tool.py (replace xxxxx with your windows user)
(4b) now lets decrypt your cfg file first
type
python nokia-router-cfg-tool.py -d OYdLWUVDdKQTPaCIeTqniA==
(4c) now unpack you cfg file to xml
type
python nokia-router-cfg-tool.py -u config.cfg
5. A new file is created on your desktop .xml format
right click & select edit.
(5a) press control+f and type TelnetSshAccount in searchbox then hit enter
now change the values same as below
<TelnetSshAccount. n="TelnetSshAccount" t="staticObject">
<Enable rw="RW" t="boolean" v="True"></Enable>
<UserName ml="64" rw="RW" t="string" v="admin"></UserName>
<Password ml="64" rw="RW" t="string" v="OYdLWUVDdKQTPaCIeTqniA==" ealgo="ab"></Password>
press control s to save the file & close it
6. Go back to cmd & check for repack command to encrypt the edited xml file back to cfg
it will look like this something like this :
type
python nokia-router-cfg-tool.py -ple config-XXXXXXX-XXXXXX.xml 0x4924ea42
(6a) a new cfg file will be created on your desktop.
7. Now go back to router login page 192.168.1.1
(7a) go to Maintenance->backup and restore & click "select" then browse newly created cfg file from your desktop then click import
wait for the router to reboot itself.
8. Now login again 192.168.1.1
Go to Security->Access control and allow both telent & ssh(Wan & Lan)
9. Download MobaXterm_Portable_v21.5 link below
10. Open Mobaxterm & click on Start local terminal
type
telnet 192.168.1.1
user: admin
password: admin
11. After that lets first copy this in your clipboard: '; /bin/sh; #
(11a) go back to mobaxterm
type
enable
type
shell
it will ask for password2, press shift+insert button on your keyboard and hit enter
BOOM now you've root access
(11b) to take the current backup of airtel settings
type
cfgcli dump
type
ritool dump
& save the file by going terminal->save terminal text.
(11c) now to unlock settings
type
ritool set OperatorID ALCL
12. Go back your router login on your browser 192.168.1.1 and BOOOOOOM everything is unlocked, you'll see changes right away
Important : If you plan to stick with everything unlocked using airtel fiber then let it as it is.
Important: If you plan to use this router with any other fiber connection just do a factory reset.
Doing a factory reset will erase, reset & unlock everything. The default router login address will change to 192.168.1.254 with username AdminGPON and password as ALC#FGU
I've personally myself tested this whole process & successfully unlocked 3 routers.
I wish you all good health.
type
python C:\Users\XXXXX\Desktop\Nokia-router-cfg-tool.py (replace xxxxx with your windows user)
(4b) now lets decrypt your cfg file first
type
python nokia-router-cfg-tool.py -d OYdLWUVDdKQTPaCIeTqniA==
(4c) now unpack you cfg file to xml
type
python nokia-router-cfg-tool.py -u config.cfg
5. A new file is created on your desktop .xml format
right click & select edit.
(5a) press control+f and type TelnetSshAccount in searchbox then hit enter
now change the values same as below
<TelnetSshAccount. n="TelnetSshAccount" t="staticObject">
<Enable rw="RW" t="boolean" v="True"></Enable>
<UserName ml="64" rw="RW" t="string" v="admin"></UserName>
<Password ml="64" rw="RW" t="string" v="OYdLWUVDdKQTPaCIeTqniA==" ealgo="ab"></Password>
press control s to save the file & close it
6. Go back to cmd & check for repack command to encrypt the edited xml file back to cfg
it will look like this something like this :
type
python nokia-router-cfg-tool.py -ple config-XXXXXXX-XXXXXX.xml 0x4924ea42
(6a) a new cfg file will be created on your desktop.
7. Now go back to router login page 192.168.1.1
(7a) go to Maintenance->backup and restore & click "select" then browse newly created cfg file from your desktop then click import
wait for the router to reboot itself.
8. Now login again 192.168.1.1
Go to Security->Access control and allow both telent & ssh(Wan & Lan)
9. Download MobaXterm_Portable_v21.5 link below
10. Open Mobaxterm & click on Start local terminal
type
telnet 192.168.1.1
user: admin
password: admin
11. After that lets first copy this in your clipboard: '; /bin/sh; #
(11a) go back to mobaxterm
type
enable
type
shell
it will ask for password2, press shift+insert button on your keyboard and hit enter
BOOM now you've root access
(11b) to take the current backup of airtel settings
type
cfgcli dump
type
ritool dump
& save the file by going terminal->save terminal text.
(11c) now to unlock settings
type
ritool set OperatorID ALCL
12. Go back your router login on your browser 192.168.1.1 and BOOOOOOM everything is unlocked, you'll see changes right away
Important : If you plan to stick with everything unlocked using airtel fiber then let it as it is.
Important: If you plan to use this router with any other fiber connection just do a factory reset.
Doing a factory reset will erase, reset & unlock everything. The default router login address will change to 192.168.1.254 with username AdminGPON and password as ALC#FGU
I've personally myself tested this whole process & successfully unlocked 3 routers.
I wish you all good health.
Status>Overview
G-2425G-A
ImportError: No module named Crypto
pip3 install pycryptodome
add python keyword
nokia-router-cfg-tool.py -pleS23l7nZm47XyMGs6y6oJpN9CR4nbfIZHJ4VRwp7HcdV6o2YvUmeNYFlz08Otwz78 config-28112022-155759.xml 0xffffffff
when resoter name must be config only
https://gist.github.com/thedroidgeek/80c379aa43b71015d71da130f85a435a
--------------------
worked
config2 did not worked invalid cf only config worked
After reboot
Enable ssh and telnet access on lan side
Open putty or any other ssh client
ONTUSER
admin
Got root ?
Yes
If u factory reset
You need to do this again
First run
ritool dump
Copy all the data
cfgcli dump
ritool set OperatorID ALCL
Unlock done bro thanks a lot
When trying to create new profile any solution
error set xpon_struct
Factory reset
http://192.168.1.254
AdminGPON
ALC#FGU
Comments
Post a Comment