diff --git a/.github/workflows/mikrotik_patch.yml b/.github/workflows/mikrotik_patch.yml index d82e659..681078d 100644 --- a/.github/workflows/mikrotik_patch.yml +++ b/.github/workflows/mikrotik_patch.yml @@ -152,29 +152,50 @@ jobs: ./new_iso sudo rm -rf ./new_iso - - name: Get install-image-${{ env.LATEST_VERSION }}.img + - name: Get chr-${{ env.LATEST_VERSION }}.img run: | - sudo wget -nv -O install-image-$LATEST_VERSION.zip https://download.mikrotik.com/routeros/$LATEST_VERSION/install-image-$LATEST_VERSION.zip - - - name: Patch install-image-${{ env.LATEST_VERSION }}.img + sudo wget -nv -O chr-$LATEST_VERSION.img.zip https://download.mikrotik.com/routeros/$LATEST_VERSION/chr-$LATEST_VERSION.img.zip + sudo unzip chr-$LATEST_VERSION.img.zip + + - name: Patch chr-${{ env.LATEST_VERSION }}.img run: | - sudo unzip install-image-$LATEST_VERSION.zip - sudo mkdir ./install - sudo mount -o loop install-image-$LATEST_VERSION.img ./install - sudo rm install-image-$LATEST_VERSION.zip - sudo rm ./install/1.npk - NPK_FILES=$(find ./install/*.npk) - for file in $NPK_FILES; do - sudo -E python3 npk.py sign $file $file - done - sudo cp routeros-$LATEST_VERSION.npk ./install/1.npk - sudo cp keygen.zip ./install/ - sudo cp option-$LATEST_VERSION.npk ./install/100.npk - sudo cp python3-$LATEST_VERSION.npk ./install/101.npk - sudo cp linux ./install/ - sudo umount ./install - sudo rm -rf ./install - sudo zip install-image-$LATEST_VERSION.zip ./install-image-$LATEST_VERSION.img + sudo apt -y install qemu-utils 2> /dev/null + sudo qemu-img convert -f raw -O qcow2 chr-$LATEST_VERSION.img chr-$LATEST_VERSION.qcow2 + sudo rm chr-$LATEST_VERSION.img.zip + sudo rm chr-$LATEST_VERSION.img + sudo qemu-nbd -c /dev/nbd0 chr-$LATEST_VERSION.qcow2 + sudo -E python3 patch.py boot /dev/nbd0p1 + sudo mkdir ./routeros + sudo mount /dev/nbd0p2 ./routeros + sudo mkdir -p ./qcow2/routeros/rw/disk + sudo cp keygen.zip ./qcow2/routeros/rw/disk + sudo mkdir -p ./qcow2/routeros/var/pdb/option + sudo cp option-$LATEST_VERSION.npk ./qcow2/routeros/var/pdb/option/image + sudo cp routeros-$LATEST_VERSION.npk ./qcow2/routeros/var/pdb/system/image + sudo umount /dev/nbd0p2 + sudo rm -rf ./routeros + sudo qemu-nbd -d /dev/nbd0 + + sudo qemu-img convert -f qcow2 -O vmdk chr-$LATEST_VERSION.qcow2 chr-$LATEST_VERSION.vmdk + sudo qemu-img convert -f qcow2 -O vpc chr-$LATEST_VERSION.qcow2 chr-$LATEST_VERSION.vhd + sudo qemu-img convert -f qcow2 -O vhdx chr-$LATEST_VERSION.qcow2 chr-$LATEST_VERSION.vhdx + sudo qemu-img convert -f qcow2 -O vdi chr-$LATEST_VERSION.qcow2 chr-$LATEST_VERSION.vdi + sudo qemu-img convert -f qcow2 -O raw chr-$LATEST_VERSION.qcow2 chr-$LATEST_VERSION.img + + sudo zip chr-$LATEST_VERSION.qcow2.zip chr-$LATEST_VERSION.qcow2 + sudo zip chr-$LATEST_VERSION.vmdk.zip chr-$LATEST_VERSION.vmdk + sudo zip chr-$LATEST_VERSION.vhd.zip chr-$LATEST_VERSION.vhd + sudo zip chr-$LATEST_VERSION.vhdx.zip chr-$LATEST_VERSION.vhdx + sudo zip chr-$LATEST_VERSION.vdi.zip chr-$LATEST_VERSION.vdi + sudo zip chr-$LATEST_VERSION.img.zip chr-$LATEST_VERSION.img + + sudo rm chr-$LATEST_VERSION.qcow2 + sudo rm chr-$LATEST_VERSION.vmdk + sudo rm chr-$LATEST_VERSION.vhd + sudo rm chr-$LATEST_VERSION.vhdx + sudo rm chr-$LATEST_VERSION.vdi + sudo rm chr-$LATEST_VERSION.img + - name: Delete Release tag ${{ env.LATEST_VERSION }} run: | @@ -200,5 +221,5 @@ jobs: make_latest: ${{ matrix.channel == 'stable' }} files: | mikrotik-${{ env.LATEST_VERSION }}.iso - install-image-${{ env.LATEST_VERSION }}.zip + chr-${{ env.LATEST_VERSION }}.*.zip netinstall-${{ env.LATEST_VERSION }}.zip \ No newline at end of file diff --git a/patch.py b/patch.py index 3b98f8e..70e5810 100644 --- a/patch.py +++ b/patch.py @@ -52,6 +52,42 @@ def run_shell_command(command): process = subprocess.run(command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return process.stdout, process.stderr + +def patch_bootloader(key_dict,boot_dev): + IMAGE_OFFSET_BLK = 512 + BLOCK_SIZE = 4096 + #debugfs /dev/sda1 -R 'icheck 512' 2> /dev/null | grep 512 + stdout,stderr = run_shell_command(f"debugfs {boot_dev} -R 'icheck {IMAGE_OFFSET_BLK}' 2> /dev/null | sed -n '2p'") + tmp = stdout.decode().strip().split('\t') + assert len(tmp) >= 2 , f'debugfs icheck error {tmp} {stderr.decode()}' + inode = int(tmp[1]) + print(f'inode : {inode}') + #sudo debugfs /dev/sda1 -R 'stat <12>' 2> /dev/null | sed -n '11p' + stdout,stderr = run_shell_command(f"debugfs /dev/sda1 -R 'stat <12>' 2> /dev/null | sed -n '11p' ") + blocks_info = stdout.decode().strip().split(',') + blocks = [] + ind_block_id = None + for block_info in blocks_info: + _tmp = block_info.strip().split(':') + if _tmp[0].strip() == '(IND)': + ind_block_id = int(_tmp[1]) + else: + id_range = _tmp[0].strip().replace('(','').replace(')','').split('-') + block_range = _tmp[1].strip().replace('(','').replace(')','').split('-') + blocks += [id for id in range(int(block_range[0]),int(block_range[1])+1)] + print(f' blocks : {len(blocks)} ind_block_id : {ind_block_id}') + stdout,stderr = run_shell_command(f"debugfs /dev/sda1 -R 'cat <{inode}>' 2> /dev/null") + bzImage = stdout + new_bzImage = patch_bzimage(bzImage,key_dict) + print(f'write block {len(blocks)} : [',end="") + with open(boot_dev,'wb') as f: + for index,block_id in enumerate(blocks): + print('#',end="") + f.seek(block_id*BLOCK_SIZE) + f.write(new_bzImage[index*BLOCK_SIZE:(index+1)*BLOCK_SIZE]) + f.flush() + print(']') + def patch_squashfs(path,key_dict): for root, dirs, files in os.walk(path): for file in files: @@ -108,6 +144,8 @@ if __name__ == '__main__': npk_parser = subparsers.add_parser('npk',help='patch and sign npk file') npk_parser.add_argument('input',type=str, help='Input file') npk_parser.add_argument('-o','--output',type=str,help='Output file') + boot_parser = subparsers.add_parser('boot',help='patch bootloader') + boot_parser.add_argument('dev',type=str, help='boot device') netinstall_parser = subparsers.add_parser('netinstall',help='patch netinstall file') netinstall_parser.add_argument('input',type=str, help='Input file') netinstall_parser.add_argument('-o','--output',type=str,help='Output file') @@ -121,6 +159,9 @@ if __name__ == '__main__': if args.command =='npk': print(f'patching {args.input} ...') patch_npk_file(key_dict,kcdsa_private_key,eddsa_private_key,args.input,args.output) + if args.command =='boot': + print(f'patching {args.dev} ...') + patch_bootloader(key_dict,args.dev) elif args.command == 'netinstall': from netinstall import patch_netinstall print(f'patching {args.input} ...')