Add da sla for xflash and minor fixes

This commit is contained in:
Bjoern Kerler 2024-06-27 20:45:39 +02:00
parent b84d16f2c0
commit 03e68c81db
No known key found for this signature in database
GPG key ID: A3E0FAF79F2F4578
11 changed files with 117 additions and 29 deletions

View file

@ -22,7 +22,7 @@ def customized_sign(n, e, msg):
return signature
def generate_brom_sla_challenge(d, e, data):
def generate_brom_sla_challenge(data, d, e):
d = bytes_to_long(bytes.fromhex(d))
e = bytes_to_long(bytes.fromhex(e))
for i in range(0, len(data), 2):
@ -33,11 +33,7 @@ def generate_brom_sla_challenge(d, e, data):
return msg
def generate_da_sla_signature(data, d, n, e):
d_da = bytes_to_long(bytes.fromhex(d))
n_da = bytes_to_long(bytes.fromhex(n))
e_da = bytes_to_long(bytes.fromhex(e))
pprivate_key = RSA.construct((n_da, d_da, e_da))
cipher = PKCS1_OAEP.new(pprivate_key, SHA256, mgfunc=lambda x, y: PKCS1_OAEP.MGF1(x, y, SHA256))
def generate_da_sla_signature(data, key):
cipher = PKCS1_OAEP.new(key, SHA256, mgfunc=lambda x, y: PKCS1_OAEP.MGF1(x, y, SHA256))
ciphertext = cipher.encrypt(data)
return ciphertext

View file

@ -1,3 +1,7 @@
from Cryptodome.PublicKey import RSA
from Cryptodome.Util.number import bytes_to_long
class SlaKey:
vendor = None
da_codes = None
@ -13,24 +17,72 @@ class SlaKey:
self.d = d
self.n = n
self.e = e
if isinstance(d,int):
d_da = d
else:
d_da = bytes_to_long(bytes.fromhex(self.d))
if isinstance(n, int):
n_da = n
else:
n_da = bytes_to_long(bytes.fromhex(self.n))
if isinstance(e, int):
e_da = e
else:
e_da = bytes_to_long(bytes.fromhex(self.e))
self.key = RSA.construct((n_da,d_da,e_da))
da_sla_keys = [
SlaKey(vendor="Generic",
# lk/files/pbp/keys/toolauth/da_prvk.pem
SlaKey(vendor="KaiOS",
da_codes=[],
name="",
d="707C8892D0DE8CE0CA116914C8BD277B821E784D298D00D3473EDE236399435F8541009525C2786CB3ED3D7530D47C9163692B0D588209E7E0E8D06F4A69725498B979599DC576303B5D8D96F874687A310D32E8C86E965B844BC2ACE51DC5E06859EA087BD536C39DCB8E1262FDEAF6DA20035F14D3592AB2C1B58734C5C62AC86FE44F98C602BABAB60A6C8D09A199D2170E373D9B9A5D9B6DE852E859DEB1BDF33034DCD91EC4EEBFDDBECA88E29724391BB928F40EFD945299DFFC4595BB8D45F426AC15EC8B1C68A19EB51BEB2CC6611072AE5637DF0ABA89ED1E9CB8C9AC1EB05B1F01734DB303C23BE1869C9013561B9F6EA65BD2516DE950F08B2E81",
n="A243F6694336D527C5B3ED569DDD0386D309C6592841E4C033DCB461EEA7B6F8535FC4939E403060646A970DD81DE367CF003848146F19D259F50A385015AF6309EAA71BFED6B098C7A24D4871B4B82AAD7DC6E2856C301BE7CDB46DC10795C0D30A68DD8432B5EE5DA42BA22124796512FCA21D811D50B34C2F672E25BCC2594D9C012B34D473EE222D1E56B90E7D697CEA97E8DD4CCC6BED5FDAECE1A43F96495335F322CCE32612DAB462B024281841F553FF7FF33E0103A7904037F8FE5D9BE293ACD7485CDB50957DB11CA6DB28AF6393C3E78D9FBCD4567DEBCA2601622F0F2EB19DA9192372F9EA3B28B1079409C0A09E3D51D64A4C4CE026FAD24CD7",
d="928d2a63d56bc42c3c02e836c025f6db39f06d57480dc705f3eaf238120a2b0d8fc00ec3cdf209615ca41bf73ae499dd9accb09b99fbb4046087008aab48d96f437292c160092dfc4ae33f94acee374e584b9d70d90ca46664d31cf72bba302e6eafab68e13a7f1ed9fa0ddc2604f3164bc97bc8c1b0be9db1d76d1d970ea36f4af8ad2ce0ab5b7ca6b4f99c133fa3f8ff9c92da874394d0e8f1bdbb83c8e811a344a5b5a7251c9b4fb4ad0ac494a2c50a1a79fa9b3992d749535b691dc2f016cee493e41cd2033190c4c0497f689e48bae5d3ad28cb0e8d17dae7f4e8c034ab60ab330f678fbfdd2c9716bfa6a617339d248b46df1593d5317b3af44a864641",
n="9BB734774443D77557A76E24B10733787750D90D09C869CD606D54F28978EA6220DC9948B3C9E89284F8551D6166F3754B6A3B890AC9CDA9E37DFAA0C1317E351CE5107C4273795949C6CCE638314AB1A345385D7642CB8D055A1F410C7D7E24A6F0A2AAB8184E773D21B3754A947541680F2C1A8D6BA5BEFD3B6E1FC28EC0B61D55B1454383F2C3E8BD27170A25978608F6788B90A2FC34F0CE35056BF7520795C8C60232CBBC0B0399367AF937869CA45CF737A8A066127893E93166C433298DD6FD009E6790E743B3392ACA8EA99F61DFC77BD99416DDA4B8A9D7E4DA24217427F3584119A4932016F1735CC63B12650FDDDA73C8FCFBC79E058F36219D3D",
e="010001"),
# lk/files/pbp/keys/toolauth/da_prvk.pem
SlaKey(vendor="Rowan",
da_codes=[],
name="",
d="09976537029b4362591c5b13873f223de5525d55df52dde283e52afa67f6c9dbf1408d2fb586a624efc93426f5f3be981f80e861ddd975a1e5e662db84f5164804a3ae717605d7f15866df9ed1497c38fdd6197243163ef22f958d7b822c57317203e9a1e7d18dad01f15054facdbddb9261a1272638da661fe4f9f0714ecf00e6541cc435afb1fd75a27d34b17ad400e9474ba850dafce266799caff32a058ff71e4c2daacaf8ba709e9ca4dc87584a7ffe8aa9a0a160ed069c3970b7dae3987ded71bd0bc824356987bd74363d46682c71913c3edbdb2a911f701f23aee3f8dd98180b5a138fd5ad74743682d2d2d1bb3d92786710248f316dd8391178ea81",
n="D16403466C530EF9BB53C1E8A96A61A4E332E17DC0F55BB46D207AC305BAE9354EAAC2CB3077B33740D275036B822DB268200DE17DA3DB7266B27686B8970B85737050F084F8D576904E74CD6C53B31F0BB0CD60686BF67C60DA0EC20F563EEA715CEBDBF76D1C5C10E982AB2955D833DE553C9CDAFD7EA2388C02823CFE7DD9AC83FA2A8EB0685ABDAB56A92DF1A7805E8AC0BD10C0F3DCB1770A9E6BBC3418C5F84A48B7CB2316B2C8F64972F391B116A58C9395A9CE9E743569A367086D7771D39FEC8EBBBA3DD2B519785A76A9F589D36D637AF884543FD65BAC75BE823C0C50AA16D58187B97223625C54C66B5A5E4DBAEAB7BE89A4E340A2E241B09B2F",
e="010001"),
"""
SlaKey(vendor="Generic",
da_codes=[],
name="VERIFIED_BOOT_IMG_AUTH_KEY.ini",
d=0xDACD8B5FDA8A766FB7BCAA43F0B16915CE7B47714F1395FDEBCF12A2D41155B0FB587A51FECCCB4DDA1C8E5EB9EB69B86DAF2C620F6C2735215A5F22C0B6CE377AA0D07EB38ED340B5629FC2890494B078A63D6D07FDEACDBE3E7F27FDE4B143F49DB4971437E6D00D9E18B56F02DABEB0000B6E79516D0C8074B5A42569FD0D9196655D2A4030D42DFE05E9F64883E6D5F79A5BFA3E7014C9A62853DC1F21D5D626F4D0846DB16452187DD776E8886B48C210C9E208059E7CAFC997FD2CA210775C1A5D9AA261252FB975268D970C62733871D57814098A453DF92BC6CA19025CD9D430F02EE46F80DE6C63EA802BEF90673AAC4C6667F2883FB4501FA77455,
n=0x8BC9B1F7A559BCDD1717F3F7BFF8B858743892A6338D21D0BE2CE78D1BCB8F61A8D31822F694C476929897E4B10753DDBE45A2276C0EFEE594CF75E47016DA9CDB3D8EB6C3E4C5D69B8BCCE1AE443CF299C22B905300C85875E8DBB8231F4E9949D8CF9D8E0F40E93F29F843420F22CD9D080A45A4407F58F3609D03A7DB950D3D847B8B4E7D50DB6359D37A2DD730D3CE77F8FB2A33C095B0A6CF3E08593E4F70254DCDF671790F530EC07C3CD1E80199CB42F24ACA92DB5996F2119003F502E16D88EB4E4A8DEAE4036558D2A52F5C9960B0FBBC6F6FA75EFF6F5A173CE1A82539A35973D568B8918ED12F7610748BEB0239A5006257E19574C77F4133A269,
e="010001"),
""",
SlaKey(vendor="Generic",
da_codes=[],
name="CodeSigKey",
d="00D57BCF5934CE1A035F4598B42DAD4BC8AE7577FB6D81FA232317E8EE7C4FBB33772EFE378DF7DFE5369BB9ACAB1008FA1CFBA737890012A883B372B15932335B689B46A32F1B383B75F0DE2E1B5B0B9F4E1C3E780C2AB0CD3671EB4E34F30BB4C630A60D168CA124810D0F91A1ACC8EFDCEE52D4762BB35813BCC93878E1D15B750561B78006B4C13A8F76B5F10C941E5776C21192357A9B9D7E02C0FC812D2B154671863DE97CE3ED07F90624A0CADD04079E145168A3558A64786820192F5B638354DA69520288B976296961C337FB18A90120F2B6B365C0E1A57CE4119AE8BC718E08FDA33F1F42AA1C91AED090EC6B5656A66C246F89FDE5FD41A76671",
n="01C6B6A1DDF05E818E3DFE16101C5DF65939F352EAB8AACA91CB5BFEC15A1989DD7553343683BC30BB38E45F15BF17BCCAB16A41D695A4318F26504675FE83E92EE21C991C0FBA705395B4A34C331842D8A6F69846B58CC67306E3DE27B05666A6C4372E3FC0D92F314805EDD5B1CB7D25BF3CF9CA9C33C36D97B0B37DA8A44A7A1CA651679D8D680557740C7C1CA25D84BDD12136C2930432808F28265D1E33E667389E4806D865F3CC06329534F7A11861EB688545DCCCEF0B04E96735A08368FA31A1F3260073B31299B216192E620B8D1EA468925ADBD627C49EFC3623658F3CF8AD6D8556272E48FA7711E650287DA19196610F036B6C0D394E42C121D1",
e="010001"),
SlaKey(vendor="Generic",
da_codes=[],
name="SecureROSigKey",
d="040AB412E994921780E7D3AC4E665B5018BAD2221D93A236FCD3D4245BB14EF5E715B687254BFC5D5C058FF5C33AF644E6B03748A6ABFDFAFF808265B9C12B42C2164826B3A8CD5D6B3295E025618AED68D33E02D75FB8C69FDE6753AF454EAA92F448961C5D11DFD8D2D5125E54C71DE5792EAD4B4AD2A47ED2F144C664A2EC2B5C527D4C4570162EBADF6FA6AA19D86C927257BDA4AC4B471AD94AC16C8A97E9201101EF268E35E66835FE9831F3D18495BA15B3FCD9089B4569F770896674173647EFED86F4570CE6118E48A7EDD6CE2A2ED72A2E6FD615A323708F0881443B6C6DEF3800B392385E060AAC6CE086DDBA9227027F80B0DFDF691A1ED8A601",
n="041EDF18B2702830A0D1D6D2C0C9833C46D55636929ABC8CBF62D03A8E352697F536DDF250E6CA5F1153A9227FEA4F6C4A91CF118FD821ABA9020FFC6AA05D4C361177AA384ACEE201E1326D5A0E1D566E74DA51CD735841FB5638E03F4E9A5AC58D0123F8E057686541E424F83508D1CEADDE7A893F57B852ECFF27953F53030953859EA265C0C7155F6B730E902BC23FEB58077E8D439606B164635D5AA0C53657BF2143EEE86F06781573BED22DD3E792591A263F2357CC42AEF4B8DB585987A311A022C4442A4DFA1C4891D8ADA1B231A92096E16D9C718FB09DFC0A5B008BB8243BF32C537A6B19542E37311085197B6BE8DA54EE1D6BC28BA94E0079CB",
e="010001"),
]
brom_sla_keys = [
SlaKey(vendor="Generic",
da_codes=[],
name="IMG_AUTH_KEY.ini",
d="4BD992E9A2230CD2ABEF49E4F6A7E11D7E2ADD24847787B320239829C560D5EAB94B8304317C938E9358E94758AE60D9B13F2913DD1A749A9941FACAFAB574D70EBBFBCC0133A4BE2134CBA3CE7EE18A6D3CC98D33DAB06AEEE512F405A3248EA316ABC31A2758D4C5A7B9DFCC02C2508A492EF3760A0D4CDA827CFFCADD11ED",
n="5FFF0B70D5DE3FC5BF41CB824B4BFD14820571CE57EDD3E7C668CC570E718DB07DCC7A6CACD0E80DADC38AA33DB37816839D97980DF3E577A6E0B1169D708071E17DD259CFE538DBDA804A2FC07D795841F2F59DEE023A9919360D0A3F4647FDF5657D9FC5944C8BFA2802336BA23AFDCDE8D546E8806EB532AA7F95A01D8DD1",
e="010001"),
"""SlaKey(vendor="Generic",
da_codes=[],
name="AuthGen_SV5.ini",
d="009a3c3d4da0650cef38ed96ef833904c9c13835199367c7b9cb03a55e7aa482016a820dfe597cd54dd1f81fd879cf070ec0c25899ac5a49822db09675a92acf6a01e0f8f538bbe66de48ca9bdca313b616470d9ec2914356d03c95f7d9236549e5a21457e4dd5fcaf09046c47ca7436f06cd7b82cb6d2a936fca88b707f6ce28f33110fea1ec363e8482419db901cb0d38e574fe0c02ad117166b40ec78f59aaa7f3eafa425010a95614e046651273a6cb1371380c4e6ce81bdb892db6ff4892cc4d8c613a8fb3fec1e72c279052896872fc23da07fba63783374f3be8e16a15e0a04a139108dd6ac239f191135f4a895e27c670de065d2248e3f9c7e920fd001",
d="9a3c3d4da0650cef38ed96ef833904c9c13835199367c7b9cb03a55e7aa482016a820dfe597cd54dd1f81fd879cf070ec0c25899ac5a49822db09675a92acf6a01e0f8f538bbe66de48ca9bdca313b616470d9ec2914356d03c95f7d9236549e5a21457e4dd5fcaf09046c47ca7436f06cd7b82cb6d2a936fca88b707f6ce28f33110fea1ec363e8482419db901cb0d38e574fe0c02ad117166b40ec78f59aaa7f3eafa425010a95614e046651273a6cb1371380c4e6ce81bdb892db6ff4892cc4d8c613a8fb3fec1e72c279052896872fc23da07fba63783374f3be8e16a15e0a04a139108dd6ac239f191135f4a895e27c670de065d2248e3f9c7e920fd001",
n="008C8BF38EB2FC7FC06D567DBF70E9C34BE4281C4239ED9C58A6B598C3AE7821815D94D0B463463EEBBD69FF6AF990AE0499B6C3B3CADCD91D54499CD66E5314DB610FC0C6CAEEB1F16B6F2D451E3F2B2D515008917FCEC50ADA4CE0699BCF247D5AE2A1DDD34C48624A657CCB11CE5F8C6CE92CAB6038EFC2A89E42E029488C02C3CF21947C86D51BBA8EF540A2A7CE85356F431891261D860B518E89DD73B2D240461ACB66BCC213403145DE83F6963147E65274EA1E45DB2D231E0774ECC86E4F2328F8A90835C4FDEF1088DDBA1D8F7CA0CA732A64BDA6816162C0F88F02CF97634D85530968CBF8B7CE6A8B67D53BBFB4910843EA413135D56FB5074445",
e="010001"),
""",
SlaKey(vendor="Generic",
da_codes=[],
name="ROWAN / 0_2048_key.pem / CHIP_TEST_KEY.ini / lk/files/pbp/keys/toolauth/sla_prvk.pem",

View file

@ -133,7 +133,7 @@ class DAloader(metaclass=LogBase):
dahash = hashlib.sha1(da2[:hashlen]).digest()
elif hashmode == 2:
dahash = hashlib.sha256(da2[:hashlen]).digest()
# orighash = da1[hashpos:hashpos + len(dahash)]
orighash = da1[hashpos:hashpos + len(dahash)]
da1[hashpos:hashpos + len(dahash)] = dahash
return da1

View file

@ -6,6 +6,9 @@ import time
import os
from binascii import hexlify
from struct import pack, unpack
from mtkclient.Library.Auth.sla import generate_da_sla_signature
from mtkclient.Library.Auth.sla_keys import da_sla_keys
from mtkclient.Library.DA.xflash.xflash_flash_param import NandExtension
from mtkclient.Library.DA.xflash.xflash_param import Cmd, ChecksumAlgorithm, FtSystemOSE, DataType
from mtkclient.Library.utils import LogBase, logsetup
@ -738,6 +741,17 @@ class DAXFlash(metaclass=LogBase):
self.error(f"Error on getting packet length: {self.eh.status(status)}")
return None
def get_sla_status(self):
resp = self.send_devctrl(self.Cmd.SLA_ENABLED_STATUS)
if resp != b"":
status = self.status()
if status == 0:
return int.from_bytes(resp,'little')
else:
self.error(f"Error on getting sla enabled status: {self.eh.status(status)}")
return None
def get_usb_speed(self):
resp = self.send_devctrl(self.Cmd.GET_USB_SPEED)
if resp != b"":
@ -1115,6 +1129,26 @@ class DAXFlash(metaclass=LogBase):
self.mtk.port.cdc.set_fast_mode(True)
self.config.set_gui_status(self.config.tr("Connected to stage2 with higher speed"))
def set_remote_sec_policy(self, data):
return self.send_devctrl(self.Cmd.SET_REMOTE_SEC_POLICY, data)
def handle_sla(self, da2):
res = self.get_dev_fw_info()
if res!=b"":
data = res[4:4+0x10]
found = False
for key in da_sla_keys:
if da2.find(bytes.fromhex(key.n)) != -1:
sla_signature = generate_da_sla_signature(data=data, key=key.key)
found = not self.set_remote_sec_policy(data=sla_signature)
if not found:
print("No valid sla key found, using dummy auth ....")
sla_signature = b"\x00" * 0x100
found = not self.set_remote_sec_policy(data=sla_signature)
if found:
print("SLA Signature was accepted.")
return found
def upload_da(self):
if not self.mtk.daloader.patch:
if (self.kamakiri_pl is not None and not self.mtk.config.chipconfig.damode == 6 and
@ -1184,6 +1218,14 @@ class DAXFlash(metaclass=LogBase):
loaded = self.boot_to(self.daconfig.da_loader.region[stage].m_start_addr, self.daconfig.da2)
if loaded:
self.info("Successfully uploaded stage 2")
sla_enabled = self.get_sla_status()
if sla_enabled:
self.info("DA SLA is enabled")
if not self.handle_sla(self.daconfig.da2):
self.error("Can't bypass DA SLA")
sys.exit(1)
else:
self.info("DA SLA is disabled")
self.reinit(True)
daextdata = self.xft.patch()
if daextdata is not None:

View file

@ -59,6 +59,7 @@ class Cmd:
GET_DEV_FW_INFO = 0x040013
GET_HRID = 0x040014
GET_ERROR_DETAIL = 0x040015
SLA_ENABLED_STATUS = 0x040016
START_DL_INFO = 0x080001
END_DL_INFO = 0x080002

View file

@ -274,16 +274,10 @@ class XmlFlashExt(metaclass=LogBase):
da2patched[idx2:idx2 + 8] = b"\x00\x00\xA0\xE3\x1E\xFF\x2F\xE1"
self.info("Patched Vivo Remote SLA authentification.")
else:
pubkey = bytes.fromhex(
"A243F6694336D527C5B3ED569DDD0386D309C6592841E4C033DCB461EEA7B6F8535FC4939E403060" +
"646A970DD81DE367CF003848146F19D259F50A385015AF6309EAA71BFED6B098C7A24D4871B4B82A" +
"AD7DC6E2856C301BE7CDB46DC10795C0D30A68DD8432B5EE5DA42BA22124796512FCA21D811D50B3" +
"4C2F672E25BCC2594D9C012B34D473EE222D1E56B90E7D697CEA97E8DD4CCC6BED5FDAECE1A43F96" +
"495335F322CCE32612DAB462B024281841F553FF7FF33E0103A7904037F8FE5D9BE293ACD7485CDB" +
"50957DB11CA6DB28AF6393C3E78D9FBCD4567DEBCA2601622F0F2EB19DA9192372F9EA3B28B10794" +
"09C0A09E3D51D64A4C4CE026FAD24CD")
n = "9BB734774443D77557A76E24B10733787750D90D09C869CD606D54F28978EA6220DC9948B3C9E89284F8551D6166F3754B6A3B890AC9CDA9E37DFAA0C1317E351CE5107C4273795949C6CCE638314AB1A345385D7642CB8D055A1F410C7D7E24A6F0A2AAB8184E773D21B3754A947541680F2C1A8D6BA5BEFD3B6E1FC28EC0B61D55B1454383F2C3E8BD27170A25978608F6788B90A2FC34F0CE35056BF7520795C8C60232CBBC0B0399367AF937869CA45CF737A8A066127893E93166C433298DD6FD009E6790E743B3392ACA8EA99F61DFC77BD99416DDA4B8A9D7E4DA24217427F3584119A4932016F1735CC63B12650FDDDA73C8FCFBC79E058F36219D3D"
pubkey = bytes.fromhex(n)
# Generic SLA patch, just replace the public key with a known one
idx2 = find_binary(da2patched, b"01000100")
idx2 = da2patched.rfind(b"\x01\x00\x01\x00")
# Infinix / Tecno
if idx2 is not None:
da2patched[idx2 - 0x100:idx2] = pubkey

View file

@ -248,6 +248,9 @@ class DAXML(metaclass=LogBase):
da2 = self.xmlft.patch_da2(da2)
da1 = self.mtk.daloader.fix_hash(da1, da2, hashaddr, hashmode, hashlen)
self.mtk.daloader.patch = True
self.daconfig.da2 = da2[:hashlen]
# open("/tmp/_da1","wb").write(da1)
# open("/tmp/_da2", "wb").write(self.daconfig.da2)
else:
self.mtk.daloader.patch = False
self.daconfig.da2 = da2[:-da2sig_len]
@ -283,6 +286,7 @@ class DAXML(metaclass=LogBase):
if self.patch or not self.config.target_config["sbc"]:
da1, da2 = self.patch_da(da1, da2)
self.patch = True
self.daconfig.da2 = da2
else:
self.patch = False
self.daconfig.da2 = da2[:-da2sig_len]
@ -616,9 +620,8 @@ class DAXML(metaclass=LogBase):
found = False
for key in da_sla_keys:
if da2.find(bytes.fromhex(key.n)) != -1:
sla_signature = generate_da_sla_signature(data=self.dev_info["rnd"], d=key.d, n=key.n,
e=key.e)
self.handle_sla(data=sla_signature)
sla_signature = generate_da_sla_signature(data=self.dev_info["rnd"], key=key.key)
if self.handle_sla(data=sla_signature):
found = True
break
if not found:

View file

@ -665,7 +665,7 @@ class Preloader(metaclass=LogBase):
d = key.d
challenge_length = self.rdword()
challenge = self.rbyte(challenge_length)
response = generate_brom_sla_challenge(n, d, challenge)
response = generate_brom_sla_challenge(data=challenge, d=n, e=d)
resplen = len(response) # 0x80, 0x100, 0x180
self.usbwrite(int.to_bytes(resplen, 4, 'little'))
rlen = self.rdword()

Binary file not shown.

View file

@ -40,7 +40,7 @@ Issues = "https://github.com/bkerler/mtkclient/issues"
[project.scripts]
mtk = "mtk:main"
stage2 = "mtkclient.Tools.stage2:main"
stage2 = "stage2:main"
da_parser = "mtkclient.Tools.da_parser:main"
brom_to_offs = "mtkclient.Tools.brom_to_offs:main"