v1ral_ITS

mtk.py

May 28th, 2026
82
0
Never
5
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 16.63 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # MTK Flash Client (c) B.Kerler 2018-2025 (refactored & cleaned 2025/2026)
  3. # Licensed under GPLv3 License
  4.  
  5. import argparse
  6. import logging
  7. import os
  8. import sys
  9.  
  10. from mtkclient.Library.mtk_main import Main, metamodes
  11.  
  12. INFO = "MTK Flash/Exploit Client V2.1.4 (c) B.Kerler 2018-2026"
  13.  
  14. CMDS_HELP = {
  15.     "printgpt": "Print GPT Table information",
  16.     "gpt": "Save gpt table to given directory",
  17.     "r": "Read flash to filename",
  18.     "rl": "Read all partitions from flash to a directory",
  19.     "rf": "Read whole flash to file",
  20.     "rs": "Read sectors starting at start_sector to filename",
  21.     "ro": "Read flash starting at offset to filename",
  22.     "fs": "Mount the device as a FUSE filesystem",
  23.     "w": "Write partition from filename",
  24.     "wf": "Write flash from filename",
  25.     "wl": "Write partitions from directory path to flash",
  26.     "wo": "Write flash starting at offset from filename",
  27.     "e": "Erase partition",
  28.     "es": "Erase partition with sector count",
  29.     "ess": "Erase sector with sector count",
  30.     "footer": "Read crypto footer from flash",
  31.     "reset": "Send mtk reset command",
  32.     "meta": "Switch to meta mode",
  33.     "meta2": "Switch to meta mode (wdt)",
  34.     "dumpbrom": "Try to dump the bootrom",
  35.     "dumpsram": "Try to dump the sram",
  36.     "dumppreloader": "Try to dump the preloader",
  37.     "payload": "Run a specific kamakiri / da payload",
  38.     "crash": "Try to crash the preloader",
  39.     "brute": "Bruteforce the kamakiri var1",
  40.     "gettargetconfig": "Get target config (sbc, daa, etc.)",
  41.     "logs": "Get target logs",
  42.     "peek": "Read memory in patched preloader mode",
  43.     "stage": "Run stage2 payload via boot rom mode (kamakiri)",
  44.     "plstage": "Run stage2 payload via preloader mode (send_da)",
  45.     "da": "Run da xflash/legacy special commands",
  46.     "script": "Run multiple commands using text script",
  47.     "multi": "Run multiple commands using semicolon-separated list",
  48.     "devices": "List supported devices"
  49. }
  50.  
  51.  
  52. # ================== Argument Groups ==================
  53.  
  54. def add_connection_group(parser):
  55.     g = parser.add_argument_group("Connection & Interface")
  56.     g.add_argument('--vid', type=str)
  57.     g.add_argument('--pid', type=str)
  58.     g.add_argument('--serialport', nargs='?', const='DETECT', default=None,
  59.                    help='Use serial port (can be DETECT)')
  60.     g.add_argument('--noreconnect', action='store_true')
  61.     g.add_argument('--stock', action='store_true', help='use stock da')
  62.     g.add_argument('--uartloglevel', help='Set uart log level (0=Trace, 2=Normal)')
  63.     g.add_argument('--logchannel', help='Set log channel ("UART","USB", "BOTH")', default="UART")
  64.     g.add_argument('--loglevel', help='Set log level (0=Trace, 2=Normal)')
  65.     g.add_argument('--write_preloader_to_file', action='store_true', help='Dump preloader to file')
  66.     g.add_argument('--generatekeys', action='store_true', help='Derive HW keys')
  67.     g.add_argument('--iot', help='Use special mode for iot MT6261/2301', action="store_true",
  68.                            default=False)
  69.     g.add_argument('--socid', action='store_true', help='Read Soc ID')
  70.  
  71. def add_auth_group(parser):
  72.     g = parser.add_argument_group("Authentication")
  73.     g.add_argument('--auth', type=str, help="Use auth file (auth_sv5.auth)")
  74.     g.add_argument('--cert', type=str, help="Use cert file")
  75.  
  76.  
  77. def add_debug_group(parser):
  78.     g = parser.add_argument_group("Debug & Sector")
  79.     g.add_argument('--debugmode', action='store_true', help='Enable verbose mode')
  80.  
  81. def add_exploit_group(parser):
  82.     g = parser.add_argument_group("Bootrom / Preloader Exploit")
  83.     g.add_argument('--loader', type=str, help='Use specific DA loader, disable autodetection')
  84.     g.add_argument('--preloader', help='Set the preloader filename for dram config')
  85.     g.add_argument('--ptype', help='Payload type: amonet, kamakiri, kamakiri2, carbonara')
  86.     g.add_argument('--var1', help='Set kamakiri specific var1 value')
  87.     g.add_argument('--uart_addr', help='Set payload uart_addr value')
  88.     g.add_argument('--da_addr', help='Set a specific da payload addr')
  89.     g.add_argument('--brom_addr', help='Set a specific brom payload addr')
  90.     g.add_argument('--mode', help='Set a crash mode (0=dasend1,1=dasend2,2=daread)')
  91.     g.add_argument('--wdt', help='Set a specific watchdog addr')
  92.     g.add_argument('--skipwdt', action='store_true', help='Skip wdt init')
  93.     g.add_argument('--crash', action='store_true', help='Enforce crash if device is in pl mode')
  94.     g.add_argument('--appid', help='Use app id (hexstring)')
  95.  
  96. def add_gpt_group(parser):
  97.     g = parser.add_argument_group("GPT & Partition")
  98.     g.add_argument("--sectorsize", default='0x200', help='Set default sector size')
  99.     g.add_argument('--gpt-num-part-entries', default='0', help='Set GPT entry count')
  100.     g.add_argument('--gpt-part-entry-size', default='0', help='Set GPT entry size')
  101.     g.add_argument('--gpt-part-entry-start-lba', default='0', help='Set GPT entry start lba sector')
  102.     g.add_argument('--parttype', help='Partition type (user/boot1/rpmb/lu0 etc.)')
  103.     g.add_argument('--skip', help='Skip partitions (comma separated names)')
  104.  
  105.  
  106. # ================== Base Parser ==================
  107.  
  108. def create_base_parser():
  109.     parser = argparse.ArgumentParser(
  110.         description=INFO,
  111.         add_help=False
  112.     )
  113.     add_connection_group(parser)
  114.     add_auth_group(parser)
  115.     add_debug_group(parser)
  116.     add_exploit_group(parser)
  117.     add_gpt_group(parser)
  118.     return parser
  119.  
  120.  
  121. # ================== Helper for common flash commands ==================
  122.  
  123. def add_common_flash_cmd(subparsers, name, title, parent_parser):
  124.     return subparsers.add_parser(
  125.         name,
  126.         help=title,
  127.         parents=[parent_parser]
  128.     )
  129.  
  130.  
  131. def main():
  132.     base = create_base_parser()
  133.  
  134.     parser = argparse.ArgumentParser(
  135.         description=INFO,
  136.         parents=[base],
  137.         formatter_class=argparse.RawDescriptionHelpFormatter
  138.     )
  139.  
  140.     subparsers = parser.add_subparsers(dest='cmd', required=True, metavar='command')
  141.  
  142.     # ─── Commands using most common options ──────────────────────────────
  143.  
  144.     common_cmds = [
  145.         "printgpt", "gpt", "r", "rl", "rf", "rs", "ro",
  146.         "w", "wf", "wl", "wo", "e", "es", "ess", "footer"
  147.     ]
  148.  
  149.     cmd_parsers = {}
  150.     for cmd in common_cmds:
  151.         cmd_parsers[cmd] = add_common_flash_cmd(
  152.             subparsers, cmd, CMDS_HELP.get(cmd, cmd), base
  153.         )
  154.  
  155.     # Specific positional/required arguments
  156.     # Read partition(s)
  157.     cmd_parsers["r"].add_argument("partitionname", help="Partitions (comma sep)")
  158.     cmd_parsers["r"].add_argument("filename", help="Output files (comma sep)")
  159.     cmd_parsers["r"].add_argument("--offset", help="Offset to read from")
  160.     cmd_parsers["r"].add_argument("--length", help="Length to read")
  161.  
  162.     # Write partition(s)
  163.     cmd_parsers["w"].add_argument("partitionname", help="Partitions (comma sep)")
  164.     cmd_parsers["w"].add_argument("filename", help="Input files (comma sep)")
  165.     cmd_parsers["w"].add_argument('--gpt_file', help='Use a gpt file instead of trying to read gpt from flash')
  166.  
  167.     # Directory based
  168.     for cmd in ["rl", "gpt", "wl"]:
  169.         cmd_parsers[cmd].add_argument("directory", help="Directory path")
  170.  
  171.     # Full flash image
  172.     for cmd in ["rf", "wf"]:
  173.         cmd_parsers[cmd].add_argument("filename", help="Flash image file")
  174.         cmd_parsers[cmd].add_argument("--offset", help="Byte offset")
  175.         cmd_parsers[cmd].add_argument("--length", help="Length")
  176.         cmd_parsers[cmd].add_argument('--disable_internal_flash',
  177.                                       help='Disable internal flash read for iot MT6261/2301',
  178.                                       action="store_true",
  179.                                       default=False)
  180.  
  181.     # Sector based
  182.     for cmd in ["rs", "ess"]:
  183.         cmd_parsers[cmd].add_argument("startsector", help="Start sector")
  184.         cmd_parsers[cmd].add_argument("sectors", help="Sector count")
  185.  
  186.     # Offset based
  187.     for cmd in ["ro", "wo"]:
  188.         cmd_parsers[cmd].add_argument("offset", help="Byte offset")
  189.         cmd_parsers[cmd].add_argument("length", help="Length")
  190.         cmd_parsers[cmd].add_argument("filename", help="File")
  191.  
  192.  
  193.     # Erase
  194.     cmd_parsers["e"].add_argument("partitionname", help="Partition to erase")
  195.     cmd_parsers["es"].add_argument("partitionname", help="Partition to erase")
  196.     cmd_parsers["es"].add_argument("sectors", help="Sectors count")
  197.  
  198.     # Footer
  199.     cmd_parsers["footer"].add_argument("filename", help="Filename to store footer")
  200.  
  201.     # ─── Other commands ──────────────────────────────────────────────────
  202.  
  203.     cmd_fs = subparsers.add_parser("fs", help="Mount as FUSE filesystem")
  204.     cmd_fs.add_argument("mountpoint")
  205.     cmd_fs.add_argument("--rw", action="store_true")
  206.  
  207.     subparsers.add_parser("reset", help="Send reset command", parents=[base])
  208.     subparsers.add_parser("meta", help="Enter meta mode", parents=[base]) \
  209.         .add_argument("metamode", nargs="?", default=None, help=f"[{metamodes}]")
  210.     subparsers.add_parser("meta2", help="Enter meta mode (wdt)", parents=[base])
  211.  
  212.     subparsers.add_parser("dumpbrom", help=CMDS_HELP["dumpbrom"], parents=[base]
  213.                           ).add_argument('--filename', help='Optional filename')
  214.     subparsers.add_parser("dumpsram", help=CMDS_HELP["dumpsram"], parents=[base]
  215.                           ).add_argument('--filename', help='Optional filename')
  216.     subparsers.add_parser("dumppreloader", help=CMDS_HELP["dumppreloader"], parents=[base]
  217.                           ).add_argument('--filename', help='Optional filename')
  218.  
  219.     parser_payload = subparsers.add_parser("payload", help=CMDS_HELP["payload"], parents=[base])
  220.     parser_payload.add_argument("--payload", type=str, help="Payload file (optional)")
  221.     parser_payload.add_argument("--metamode", type=str, default=None, help=f"metamode to use [{metamodes}]")
  222.  
  223.     subparsers.add_parser("crash", help=CMDS_HELP["crash"], parents=[base])
  224.     subparsers.add_parser("brute", help=CMDS_HELP["brute"], parents=[base])
  225.     subparsers.add_parser("gettargetconfig", help=CMDS_HELP["gettargetconfig"], parents=[base])
  226.     subparsers.add_parser("logs", help=CMDS_HELP["logs"], parents=[base])
  227.  
  228.     cmd_peek=subparsers.add_parser("peek", help=CMDS_HELP["peek"], parents=[base])
  229.     cmd_peek.add_argument('address', help='Address to read from memory')
  230.     cmd_peek.add_argument('length', help='Bytes to read from memory')
  231.     cmd_peek.add_argument("--filename", help="Save to file (optional)")
  232.  
  233.     stage=subparsers.add_parser("stage", help=CMDS_HELP["stage"], parents=[base])
  234.     stage.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
  235.     stage.add_argument('--stage2', help='Set stage2 filename')
  236.     stage.add_argument('--stage2addr', help='Set stage2 loading address')
  237.     stage.add_argument('--filename', help='Set stage1 loader filename')
  238.  
  239.     plstage=subparsers.add_parser("plstage", help=CMDS_HELP["plstage"], parents=[base])
  240.     plstage.add_argument('--startpartition', help='Option for plstage - Boot to (lk, tee1)')
  241.     plstage.add_argument('--offset', help='Address to read from memory')
  242.     plstage.add_argument('--length', help='Bytes to read from memory')
  243.     plstage.add_argument('--pl', help='pl stage filename (optional)')
  244.     plstage.add_argument("--metamode", type=str, help="metamode to use [off,usb,uart]")
  245.  
  246.  
  247.     # DA subcommands
  248.     p_da = subparsers.add_parser("da", help=CMDS_HELP["da"], parents=[base])
  249.     da_subs = p_da.add_subparsers(dest="subcmd", required=True)
  250.  
  251.     da_peek = da_subs.add_parser("peek", parents=[base])
  252.     da_peek.add_argument('address', type=str, help="Address to read from (hex value)")
  253.     da_peek.add_argument('length', type=str, help="Length to read")
  254.     da_peek.add_argument('--filename', type=str, help="Save to file (optional)")
  255.  
  256.     da_subs.add_parser("efuse", parents=[base], help="Read efuses")
  257.     da_subs.add_parser("generatekeys", parents=[base], help="Generate keys")
  258.     da_subs.add_parser("keyserver", parents=[base], help="Enable key server")
  259.     da_meta = da_subs.add_parser("meta", parents=[base], help="MetaMode Tools")
  260.     da_meta.add_argument("metamode", type=str, help="metamode to use [off,usb,uart]")
  261.     da_vbmeta = da_subs.add_parser("vbmeta", parents=[base], help="Patch vbmeta partition")
  262.     da_vbmeta.add_argument("vbmode", type=str,
  263.                            help="vbmeta mode (0=locked, 1=disable_verity, 2=disable_verification, 3=disable verity+verification)")
  264.  
  265.     da_nvitem = da_subs.add_parser("nvitem", parents=[base], help="nvitem decryption/encryption")
  266.     da_nvitem.add_argument('filename',type=str, help="LD0B_001.bin")
  267.     da_nvitem.add_argument('--encrypt', action="store_true", default=False, help='Encrypt')
  268.     da_nvitem.add_argument('--seed', type=str, default="3132616263646566", help='seed')
  269.     da_nvitem.add_argument('--aeskey', type=str, default="0102030405060708090A0B0C0D0E0F1011120B1415161718191A1B1C00000000", help='aeskey')
  270.  
  271.     da_patchmodem = da_subs.add_parser("patchmodem", parents=[base], help="patch modem for imei")
  272.  
  273.     da_imei = da_subs.add_parser("imei", parents=[base], help="imei decryption/encryption")
  274.     da_imei.add_argument('imeis', type=str, help="imeis, separated by ,",nargs="?", default="")
  275.     da_imei.add_argument('--product', type=str, default="thunder", help='productname')
  276.     da_imei.add_argument('--write', action="store_true", default=False, help='Write')
  277.     da_imei.add_argument('--seed', type=str, default="3132616263646566", help='seed')
  278.     da_imei.add_argument('--aeskey', type=str,
  279.                            default="0102030405060708090A0B0C0D0E0F1011120B1415161718191A1B1C00000000", help='aeskey')
  280.  
  281.     da_rpmb = da_subs.add_parser("rpmb", parents=[base], help="RPMB Tools")
  282.     da_rpmb_cmds = da_rpmb.add_subparsers(dest='rpmb_subcmd', help='Commands: r w')
  283.     da_rpmb_r = da_rpmb_cmds.add_parser("r", help="Read rpmb")
  284.     da_rpmb_r.add_argument('filename', type=str, help="Filename to write data into", default="rpmb.bin", nargs="?")
  285.     da_rpmb_r.add_argument('--sector', help='Start sector (offset/0x100 bytes)')
  286.     da_rpmb_r.add_argument('--sectors', help='Sector count')
  287.  
  288.     da_rpmb_w = da_rpmb_cmds.add_parser("w", help="Write rpmb")
  289.     da_rpmb_w.add_argument('filename', type=str, help="Filename to write from", default="rpmb.bin", nargs="?")
  290.     da_rpmb_w.add_argument('--sector', help='Start sector (offset/0x100 bytes)')
  291.     da_rpmb_w.add_argument('--sectors', help='Sector count')
  292.  
  293.     da_rpmb_e = da_rpmb_cmds.add_parser("e", help="Erase rpmb")
  294.     da_rpmb_e.add_argument('--sector', help='Start sector (offset/0x100 bytes)')
  295.     da_rpmb_e.add_argument('--sectors', help='Sector count')
  296.  
  297.     da_rpmb_a = da_rpmb_cmds.add_parser("a", help="Auth rpmbkey")
  298.     da_rpmb_a.add_argument('--rpmbkey', help='rpmb key (hexstring, 32 bytes)')
  299.  
  300.     da_dump = da_subs.add_parser("memdump", parents=[base], help="Dump whole memory areas")
  301.     da_dump.add_argument('directory', type=str, help="Directory to dump ram dump files")
  302.     da_dump.add_argument('--startpartition', help='Option for plstage - Boot to (lk, tee1)')
  303.  
  304.     da_dramdump = da_subs.add_parser("memdram", parents=[base], help="Dump dram memory")
  305.     da_dramdump.add_argument('directory', type=str, help="Directory to dump ram dump files")
  306.     da_dramdump.add_argument('--startpartition', help='Option for plstage - Boot to (lk, tee1)')
  307.  
  308.     da_dumpbrom = da_subs.add_parser("dumpbrom", parents=[base], help="Dump whole memory areas")
  309.  
  310.     da_poke = da_subs.add_parser("poke", parents=[base], help="Write memory")
  311.     da_poke.add_argument('address', type=str, help="Address to read from (hex value)")
  312.     da_poke.add_argument('data', type=str, help="Data to write")
  313.  
  314.     da_unlock = da_subs.add_parser("seccfg", parents=[base], help="Unlock device / Configure seccfg")
  315.     da_unlock.add_argument('flag', type=str, help="Needed flag (unlock,lock)")
  316.  
  317.     # Minimal commands
  318.     subparsers.add_parser("devices", help=CMDS_HELP["devices"])\
  319.         .add_argument("--filter", help="Optional Filter string")
  320.  
  321.     subparsers.add_parser("script", help=CMDS_HELP["script"])\
  322.         .add_argument("script")
  323.  
  324.     subparsers.add_parser("multi", help=CMDS_HELP["multi"])\
  325.         .add_argument("commands")
  326.  
  327.     # ─── Parse & Run ─────────────────────────────────────────────────────
  328.  
  329.     args = parser.parse_args()
  330.  
  331.     if not args.cmd:
  332.         parser.print_help()
  333.         sys.exit(0)
  334.  
  335.     logging.basicConfig(
  336.         level=logging.DEBUG if args.debugmode else logging.INFO,
  337.         format="%(levelname)s: %(message)s"
  338.     )
  339.     if args.debugmode:
  340.         if not os.path.exists("logs"):
  341.             os.makedirs("logs")
  342.  
  343.     mtk = Main(args)
  344.     return mtk.run(parser)
  345.  
  346.  
  347. if __name__ == '__main__':
  348.     sys.exit(main() or 0)
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
Add Comment
Please, Sign In to add comment