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.


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

Popular posts from this blog

cpanel exam CPSP Answers

How to install zimbra collaboration suite 8.8.11 on CentOS 7

awstats installation