├── requirements.txt ├── README.md └── main.py /requirements.txt: -------------------------------------------------------------------------------- 1 | cffi==1.15.0 2 | cryptography==3.3.2 3 | gitdb==4.0.2 4 | GitPython==3.1.0 5 | pycparser==2.19 6 | pygit==0.1 7 | six==1.14.0 8 | smmap==3.0.1 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Repo for Technicolor gateway firmware extracted 2 | 3 | # Navigate in deatached branches named as the extracted pushed firmware 4 | 5 | 6 | ### master branch cointain the `python` script used to extract these firmware ([thanks](https://repository.ilpuntotecnico.com/files/Ansuel/Script%20Decrypt%20Firmware%20RBI/)): 7 | 8 | What the script do: 9 | - Search for .rbi files in the same folder 10 | - Decrypt using hardcoded keys 11 | - Unpack using binwalk 12 | - create a git deatached branch 13 | - push all extracted files to the hardcoded repo 14 | - delete all, including .rbi file 15 | 16 | ## Setup virtual env 17 | ``` 18 | virtualenv venv 19 | source venv/bin/activate 20 | pip install -r requirements.txt 21 | git clone https://github.com/ReFirmLabs/binwalk.git 22 | cd binwalk 23 | sudo python setup.py install 24 | ``` 25 | ## Run 26 | ```python 27 | python main.py 28 | ``` 29 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys, struct, zlib 5 | from git import Repo 6 | import glob, os, shutil 7 | from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes 8 | from cryptography.hazmat.backends import default_backend 9 | import binwalk 10 | 11 | try: 12 | assert sys.version_info >= (3,0) 13 | except AssertionError: 14 | print("Questo script necessita di python 3.x per funzionare") 15 | sys.exit(1) 16 | 17 | osck_list = { 18 | "DANT-7":b'\xA5\x68\xCB\xE5\x70\x60\xA8\xF6\xE5\xEC\xA4\xE5\xC8\xCB\x7C\xEB\x09\xFC\xE0\xA0\xD1\x20\x20\xF4\xB2\x58\x40\x4B\x04\x92\x70\x53', 19 | "GANT-1":b'\x03\x73\x85\x33\x14\xB4\x86\xE3\x35\xE4\x64\xB3\x87\x2E\x56\x39\x66\x34\xDF\xD5\xB6\xDB\x9B\xD0\x3A\x3D\xFA\xDE\x0E\x37\x14\x6D', 20 | "VANT-6":b'\x54\x62\x59\xAF\xD4\xE8\x5A\xA6\xFF\xCE\x35\x8C\xE0\xA9\x34\x52\xE2\x5A\x84\x81\x38\xA6\x7C\x14\x2E\x42\xFE\xC7\x9F\x4F\x37\x84', 21 | "VANT-9":b'\x89\xBC\xC0\x9E\xAB\xE2\x1F\xA7\x38\xE6\x2E\x6D\x91\x1F\xA8\x0C\xAF\x09\x12\x33\xEC\xCF\xF8\x84\x42\xFA\xA5\xD7\xAF\x65\x1A\x30', 22 | "VANT-F":b'\x7F\xA2\xFD\xF4\xD4\xDC\x31\xBF\x66\xF9\x1D\xDA\x9A\x3E\x87\x77\xB7\xD7\xD2\xEC\x6E\x8D\xB1\x92\x6C\x08\x31\xCA\x2A\x27\x9F\xDB', 23 | "VANT-R":b'\x39\x5A\x2C\x3E\x26\x18\xCF\x47\x7A\xA9\xAD\x68\x6F\xB0\x01\xF8\x6B\x06\xFC\x34\x75\xFA\x7F\x28\x35\x89\x01\x7D\x70\xDB\xA0\xBE', 24 | "VANT-W":b'\x44\x63\xC4\xC3\x3F\xE7\x88\xB3\xCD\x2B\xD4\x08\x70\x6B\xDF\x07\x79\x9D\x48\x73\xA7\xD5\x0D\x65\xDB\x20\x5C\xF6\x5E\x34\xF8\x7E', 25 | "VANT-Y":b'\x8E\x07\x11\x1F\x18\x86\x41\x94\x8E\x84\x50\x6D\xB6\x52\x70\xBD\x26\x59\x5A\xD4\x13\x27\x23\x5A\x53\x99\x8D\xB0\x68\xDC\x38\x33', 26 | "VBNT-1":b'\xC6\x16\x69\xDB\x31\x7E\x14\xBB\x28\xF1\x80\xE8\xB2\xB2\xF7\x8E\xD4\xF6\x54\xDE\x4D\x2E\x53\x06\x9C\x87\xB5\x5C\xED\x84\x0A\x16', 27 | "VBNT-F":b'\xFC\xD9\xBE\x1D\x6D\x8E\xA6\x59\x68\xE7\x7A\x89\xB8\xAF\xCA\x98\xA1\x46\x7F\xEE\xE8\x7A\x87\xBD\x27\x6C\x91\xDD\x94\xD4\x1D\x59', 28 | "VBNT-H":b'\x7E\xA0\xFF\xCC\xE7\xB0\x79\xAC\x08\x79\x2A\x7C\x78\x99\xAE\xC9\x0D\x01\x3B\xA2\x57\x4A\x41\x46\x55\x02\xE6\x2B\x9E\xBD\x55\x88', 29 | "VBNT-J":b'\x22\x2C\x4D\xC4\xA9\xDF\x95\x2B\x02\xD5\xA4\x89\xA1\x12\xCF\x5E\x29\xAA\xED\xF8\x6A\xDB\x63\x44\x10\xD6\x72\x1F\x15\xF4\x51\xE4', 30 | "VBNT-K":b'\xFF\xD5\x6A\x4E\x3A\x21\x40\x1B\xF1\x79\x8B\x3C\xD8\xAD\x54\xD2\x38\xBA\x80\x03\x96\x23\xBB\xA0\x8B\x6D\x50\xB8\xEC\x73\xF7\xB4', 31 | "VBNT-L":b'\xA4\x84\x24\x5C\xCF\xBE\x25\x41\xB0\xC5\xC5\xE9\x23\xBE\x67\xA7\xDE\xB9\xA8\x23\xDD\x5C\xBA\xB9\x2C\xC6\x19\xDE\xA1\x39\x1A\x42', 32 | "VBNT-O":b'\x91\x6A\xEB\x56\x9D\x8C\xBF\x8C\xFA\xF0\x60\xAE\xC5\x33\xD4\x3A\x9E\xF0\xAC\xB3\x13\x8F\x83\x51\xC4\x11\x26\x74\x21\x29\x75\xA5', 33 | "VBNT-S":b'\x0E\xF3\x4D\x97\x29\x45\x86\x9E\xF4\x0F\x89\x87\x3F\xED\x30\x26\x90\x20\xE1\x07\x68\x5C\x09\x77\x51\xBE\xF9\x47\x9D\x75\xD6\x20', 34 | "VBNT-V":b'\x7B\xFF\xB7\xEB\xBE\x41\x6D\x38\x07\x87\x12\xEC\x5A\xC5\xDE\xF6\xE4\xE5\x0E\xE5\x88\x48\xD6\xF2\xC0\x72\xDF\x6E\x0C\x6C\xEF\xE7', 35 | "VBNT-Z":b'\xBA\x6B\x79\xCA\xAC\xF7\xA7\x40\xAC\xF3\x66\xAB\x11\xDA\xAA\x3E\x48\x25\x2B\xD9\x72\x05\xAC\x6D\x07\xC5\x58\xCD\xDA\x5E\xD7\xCC', 36 | "VCNT-A":b'\xAD\x8A\x87\xE2\x9B\xE6\xB6\xED\x72\xF5\x75\xC1\xC8\x0B\xBD\x63\x8E\x7C\xE9\x5E\x5B\xF9\x82\x41\x45\xFD\x7D\x04\x2C\xDA\x2D\x79', 37 | "VDNT-O":b'\x7C\xDC\x61\x99\x3A\x2F\xAE\xF6\x40\x33\x70\x55\x15\xAF\xE8\xB1\x52\xFB\x4B\x1A\xF0\xB1\x29\xF7\xE9\x1C\x63\xC5\xD3\xFE\xB6\x99', 38 | "VDNT-W":b'\xAA\x72\x20\xBC\x88\x32\x9A\xCF\x74\xA0\x42\xB4\xD4\x5B\x07\xB1\x65\x61\x5B\x10\x91\x6C\xF4\x0B\x0B\xCC\x86\x08\xBE\x9E\x1D\x60', 39 | "VCNT-3":b'\xAF\xE6\xA9\x28\xEF\xD1\xD5\x82\x4C\xCA\x03\xCF\x6F\x9C\xD7\x79\x6F\xCB\xE9\xA7\x46\xAA\x71\x20\x79\x2B\x66\x6F\xC2\xC3\xEB\xB6', 40 | "GCNT-N":b'\xC4\x41\x70\x5B\xCE\x53\x9C\x13\x00\x16\xE8\xF9\x7B\x6A\x95\xE6\x27\xB9\x48\x76\x0A\x4A\x3E\x5F\x1C\xC3\xF3\x52\x39\x2B\x38\x9A', 41 | "GBNT-2":b'\xF1\xC7\xF7\x09\xC3\xD8\x94\x30\x2C\x2F\x84\x54\x55\x3E\x44\x8D\xF4\x2A\xDC\x99\x98\x1E\x59\x3B\xBF\x4D\xB3\xB8\x7C\xAF\x9F\x5B', 42 | } 43 | 44 | def decrypt( file ): 45 | try: 46 | datafile = open( file, "rb") 47 | globalheader = datafile.read(0x144) 48 | board_name = struct.unpack_from(">6s", globalheader, 0x13c)[0].decode('ascii') 49 | if board_name in osck_list: 50 | osck=osck_list[board_name] 51 | else: 52 | print("No OSCK for board: "+board_name) 53 | exit(1) 54 | payloadstart = struct.unpack_from(">H", globalheader, 0x2A)[0] 55 | datafile.seek(payloadstart) 56 | data = datafile.read() 57 | 58 | while True: 59 | payloadtype = data[0] 60 | if payloadtype == 0xB0: # in chiaro 61 | data = data[1+4+1:] 62 | break 63 | elif payloadtype == 0xB8: # sha256 64 | data = data[1+4+1+4+32:] 65 | elif payloadtype == 0xB4: # zip 66 | data = zlib.decompress(data[1+4+1+4:]) 67 | elif payloadtype == 0xB7: # aes256 68 | data = data[1+4+1+4:] 69 | iv = data[:16] 70 | keydata = data[16:64] 71 | backend = default_backend() 72 | cipher = Cipher(algorithms.AES(osck), modes.CBC(iv), backend=backend) 73 | decryptor = cipher.decryptor() 74 | keydata = decryptor.update(keydata) + decryptor.finalize() 75 | key = keydata[:-keydata[-1]] 76 | iv = data[64:80] 77 | cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend) 78 | decryptor = cipher.decryptor() 79 | data = decryptor.update(data[80:]) + decryptor.finalize() 80 | data = data[:-data[-1]] 81 | 82 | output_name = file[:(file.find("rbi"))]+"bin" #rimuove estensione rbi 83 | output_file = open(output_name,"w+b") #crea il bin 84 | output_file.write(data) #Scrive i dati 85 | 86 | print("Decrypted:",output_name) 87 | return output_name 88 | except Exception as e: 89 | print("Decrypting Failed: "+str(e)) 90 | 91 | 92 | os.chdir("./") 93 | for file in glob.glob("*.rbi"): 94 | print("Decrypting %s..."%file) 95 | dec_filename=decrypt(file) 96 | if not dec_filename: 97 | continue 98 | print("Binwalking %s..."%dec_filename) 99 | path_to_push='' 100 | for module in binwalk.scan('--preserve-symlinks', dec_filename, signature=True, extract=True, quiet=True): 101 | for result in module.results: 102 | if result.file.path in module.extractor.output: 103 | if result.offset in module.extractor.output[result.file.path].extracted: 104 | if 'root' in module.extractor.output[result.file.path].extracted[result.offset].files[0]: 105 | path_to_push=module.extractor.output[result.file.path].extracted[result.offset].files[0] 106 | print("Found rootfs %s"%path_to_push) 107 | #print("Extracted %d files from offset 0x%X to '%s' using '%s'" % (len(module.extractor.output[result.file.path].extracted[result.offset].files),result.offset,module.extractor.output[result.file.path].extracted[result.offset].files[0],module.extractor.output[result.file.path].extracted[result.offset].command)) 108 | if path_to_push != '': 109 | print("Pushing to github...") 110 | repo = Repo.init(path_to_push) #create repo object of the other repository 111 | repo.create_remote('origin', 'https://github.com/FrancYescO/tch_firmware_extracted') 112 | repo.remotes[0].fetch() 113 | branch_name=dec_filename[:(dec_filename.find(".bin"))] 114 | repo.git.checkout('-b', branch_name) 115 | repo.git.add('.') # same as git add file 116 | repo.git.commit(m = branch_name) # same as git commit -m "commit message" 117 | repo.git.push('origin', branch_name) # git push remote_to_push HEAD:master 118 | print("Cleaning...") 119 | shutil.rmtree('_'+dec_filename+'.extracted') 120 | os.remove(file) 121 | os.remove(dec_filename) 122 | --------------------------------------------------------------------------------