Skip to content

Instantly share code, notes, and snippets.

@jkinred
Created January 4, 2021 09:44
Show Gist options
  • Save jkinred/73689e463a08af963c45c137df6646d0 to your computer and use it in GitHub Desktop.
Save jkinred/73689e463a08af963c45c137df6646d0 to your computer and use it in GitHub Desktop.
Sierra Keygen
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2019 under MIT license
# If you use my code, make sure you refer to my name
# If you want to use in a commercial product, ask me before integrating it
import serial
import sys
import argparse
from binascii import hexlify, unhexlify
'''
C7 = 7 0 0 2 7 5 0
C6 = 3 1 7 0 3 0 1
C5 = 0 2 5 3 0 3 2
C8 = 1 3 3 1 5 7 3
C4 = 5 4 1 4 1 1 4
'''
prodtable = {
"MDM8200": dict(openlock=0, openmep=1, opencnd=0, clen=8, init=[1,3,5,7,0], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 2, 4, 1, 3, 0, 3, 4, 0)"), # MC878XC_F1.2.3.15 verified, key may be stored in nvitem 0x4e21;MC8700 M3.0.9.0 verified
"MDM9200": dict(openlock=0, openmep=1, opencnd=0, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"), # AC881U, EM8805 SWI9X15C_05.05.58.00, at!openlock?6A1F1CEA298A14B0 => AT!OPENLOCK="3A9EA70D86FEE58C"
"MDM9200_V1": dict(openlock=2, openmep=1, opencnd=0, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"), # AC710
"MDM9200_V2": dict(openlock=3, openmep=1, opencnd=0, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"), # AC775
"MDM9200_V3": dict(openlock=8, openmep=1, opencnd=8, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"), # AC775
#"MDM9x15": dict(openlock=0, openmep=1, opencnd=0, clen=8, init=[5,0,3,7,1], run="resultbuffer[i]=self.SierraCalc9x15(challenge[i])"), # 9x15C 06.03.32.02, AC340U 1.13.12.14 verified, #AT!CUSTOM=\"ADBENABLE\",1
"MDM9x15": dict(openlock=0, openmep=1, opencnd=0, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"), # 9x15C 06.03.32.02, AC340U 1.13.12.14 verified, #AT!CUSTOM=\"ADBENABLE\",1
#"MDM9x28": dict(openlock=9, openmep=10, opencnd=9, clen=8, init=[5,0,3,7,1], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 0, 1, 2, 3, 4, 3, 1, 0)"), # SWI9X07Y_02.25.02.01
"MDM9x28": dict(openlock=9, openmep=10, opencnd=9, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"), # SWI9X07Y_02.25.02.01
#"MDM9x30": dict(openlock=0, openmep=1, opencnd=0, clen=8, init=[0,7,5,3,1], run="resultbuffer[i]=self.SierraCalc9x30(challenge[i])"), # MC7455_2.30.01.01 #4
"MDM9x30": dict(openlock=5, openmep=4, opencnd=5, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"), # MC7455_2.30.01.01 #4
"MDM9x30_V1": dict(openlock=18, openmep=16, opencnd=18, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"), # AC791L/AC790S NTG9X35C_02.08.29.00
#"MDM9x40": dict(openlock=11, openmep=1, opencnd=11, clen=8, init=[0,7,5,3,1], run="resultbuffer[i]=self.MDM9x40(challenge[i], 2, 0, 3, 1, 4, 1, 0, 0)"),
"MDM9x40": dict(openlock=11, openmep=12, opencnd=11, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"), # AC815s
"MDM9x50_V1": dict(openlock=11, openmep=12, opencnd=11, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"),
#"MDM9x50": dict(openlock=7, openmep=6, opencnd=7, clen=8, init=[7,0,1,3,5], run="resultbuffer[i]=self.SierraCalc9x50(challenge[i])"),
"MDM9x50": dict(openlock=7, openmep=6, opencnd=7, clen=8, init=[7,3,0,1,5], run="resultbuffer[i]=self.SierraAlgo(challenge[i], 4, 2, 1, 0, 3, 2, 0, 0)"), # EM7565
}
infotable = {
"MDM8200": ["M81A", "M81B", "AC880", "AC881", "MC8780", "MC8781", "AC880E", "AC881E", "EM8780", "EM8781",
"MC8780V", "MC8781V", "MC8700", "AC308U"],
"MDM9200": ["AC710", "MC8775", "MC8775V", "AC875", "MC8700", "AC313U", "MC8801", "MC7700", "MC7750", "MC7710",
"EM7700"],
"MDM9200_V1": ["AC710", "MC8775", "MC8775V", "AC875", "MC8700", "AC313U", "MC8801", "MC7700", "MC7750",
"MC7710", "EM7700"],
"MDM9200_V2": ["AC775", "PC7200"],
"MDM9x28": ["SWI9X07Y", "WP76xx"],
"MDM9x15": ["SWI9X15C", "AR7550", "AR7552", "AR7554", "EM7355", "EM7655", "MC7354", "WP7100", "WP7102", "WP7104",
"MC7305", "EM7305", "MC8805", "EM8805", "MC7350", "MC7350-L", "MC7802", "MC7304", "AR7556", "AR7558",
"WP75xx", "WP85xx", "WP8548", "WP8548G", "AC340U"],
"MDM9x30": ["EM7455", "MC7455", "EM7430", "MC7430"],
"MDM9x30_V1" : ["Netgear AC790/MDM9230"],
"MDM9x40": ["AC815s"],
"MDM9x50": ["EM7565", "EM7565-9", "EM7511"],
"MDM9x50_V1" : ["Netgear MR1100"]
}
keytable = bytearray([0xF0, 0x14, 0x55, 0x0D, 0x5E, 0xDA, 0x92, 0xB3, 0xA7, 0x6C, 0xCE, 0x84, 0x90, 0xBC, 0x7F, 0xED, #0 MC8775_H2.0.8.19 !OPENLOCK, !OPENCND .. MC8765V,MC8765,MC8755V,MC8775,MC8775V,MC8775,AC850,AC860,AC875,AC881,AC881U,AC875, AC340U 1.13.12.14
0x61, 0x94, 0xCE, 0xA7, 0xB0, 0xEA, 0x4F, 0x0A, 0x73, 0xC5, 0xC3, 0xA6, 0x5E, 0xEC, 0x1C, 0xE2, #1 MC8775_H2.0.8.19 AC340U, OPENMEP default
0x39, 0xC6, 0x7B, 0x04, 0xCA, 0x50, 0x82, 0x1F, 0x19, 0x63, 0x36, 0xDE, 0x81, 0x49, 0xF0, 0xD7, #2 AC750,AC710,AC7XX,SB750A,SB750,PC7000,AC313u OPENMEP
0xDE, 0xA5, 0xAD, 0x2E, 0xBE, 0xE1, 0xC9, 0xEF, 0xCA, 0xF9, 0xFE, 0x1F, 0x17, 0xFE, 0xED, 0x3B, #3 AC775,PC7200
0xFE, 0xD4, 0x40, 0x52, 0x2D, 0x4B, 0x12, 0x5C, 0xE7, 0x0D, 0xF8, 0x79, 0xF8, 0xC0, 0xDD, 0x37, #4 MC7455_02.30.01.01 OPENMEP
0x3B, 0x18, 0x99, 0x6B, 0x57, 0x24, 0x0A, 0xD8, 0x94, 0x6F, 0x8E, 0xD9, 0x90, 0xBC, 0x67, 0x56, #5 MC7455_02.30.01.01 OPENLOCK
0x47, 0x4F, 0x4F, 0x44, 0x4A, 0x4F, 0x42, 0x44, 0x45, 0x43, 0x4F, 0x44, 0x49, 0x4E, 0x47, 0x2E, #6 SWI9x50 Openmep Key SWI9X50C_01.08.04.00
0x4F, 0x4D, 0x41, 0x52, 0x20, 0x44, 0x49, 0x44, 0x20, 0x54, 0x48, 0x49, 0x53, 0x2E, 0x2E, 0x2E, #7 SWI9x50 Openlock Key SWI9X50C_01.08.04.00
0x8F, 0xA5, 0x85, 0x05, 0x5E, 0xCF, 0x44, 0xA0, 0x98, 0x8B, 0x09, 0xE8, 0xBB, 0xC6, 0xF7, 0x65, #8 MDM8200 Special
0x4D, 0x42, 0xD8, 0xC1, 0x25, 0x44, 0xD8, 0xA0, 0x1D, 0x80, 0xC4, 0x52, 0x8E, 0xEC, 0x8B, 0xE3, #9 SWI9x07 Openlock Key 02.25.02.01
0xED, 0xA9, 0xB7, 0x0A, 0xDB, 0x85, 0x3D, 0xC0, 0x92, 0x49, 0x7D, 0x41, 0x9A, 0x91, 0x09, 0xEE, #10 SWI9x07 Openmep Key 02.25.02.01
0x8A, 0x56, 0x03, 0xF0, 0xBB, 0x9C, 0x13, 0xD2, 0x4E, 0xB2, 0x45, 0xAD, 0xC4, 0x0A, 0xE7, 0x52, #11 NTG9X40C_11.14.08.11 / mdm9x40r11_core AC815s / SWI9x50 MR1100 Openlock Key
0x2A, 0xEF, 0x07, 0x2B, 0x19, 0x60, 0xC9, 0x01, 0x8B, 0x87, 0xF2, 0x6E, 0xC1, 0x42, 0xA8, 0x3A, #12 SWI9x50 MR1100 Openmep Key
0x28, 0x55, 0x48, 0x52, 0x24, 0x72, 0x63, 0x37, 0x14, 0x26, 0x37, 0x50, 0xBE, 0xFE, 0x00, 0x00, #13 SWI9x50 Unknown key
0x22, 0x63, 0x48, 0x02, 0x24, 0x72, 0x27, 0x37, 0x19, 0x26, 0x37, 0x50, 0xBE, 0xEF, 0xCA, 0xFE, #14 SWI9x50 IMEI nv key
0x98, 0xE1, 0xC1, 0x93, 0xC3, 0xBF, 0xC3, 0x50, 0x8D, 0xA1, 0x35, 0xFE, 0x50, 0x47, 0xB3, 0xC4, #15 NTG9X35C_02.08.29.00 Openmep Key AC791L/AC790S Old
0x61, 0x94, 0xCE, 0xA7, 0xB0, 0xEA, 0x4F, 0x0A, 0x73, 0xC5, 0xC3, 0xA6, 0x5E, 0xEC, 0x1C, 0xE2, #16 NTG9X35C_02.08.29.00 Openmep Key AC791/AC790S
0xC5, 0x50, 0x40, 0xDA, 0x23, 0xE8, 0xF4, 0x4C, 0x29, 0xE9, 0x07, 0xDE, 0x24, 0xE5, 0x2C, 0x1D, #17 NTG9X35C_02.08.29.00 Openlock Key AC791/AC790S Old
0xF0, 0x14, 0x55, 0x0D, 0x5E, 0xDA, 0x92, 0xB3, 0xA7, 0x6C, 0xCE, 0x84, 0x90, 0xBC, 0x7F, 0xED, #18 NTG9X35C_02.08.29.00 Openlock Key AC791/AC790S
])
class SierraImplementationTest():
def SierraCalc9x50(self, challenge):
r3 = self.rtbl[2]
r4 = challenge
r5 = r3 + 1
self.rtbl[2] = r5 & 0xFF #.new
r5 = r5 & 0xFF
r6 = self.rtbl[3]
r3 = self.tbl[r3]
r3 = r6 + r3
#r7 = r2 + r5
self.rtbl[3] = r3 & 0xFF #.new
r3 = r3 & 0xFF
r0 = self.rtbl[1]
r14 = self.rtbl[0]
#r13 = r2 + r3
r8 = self.tbl[r0]
r9 = self.tbl[r3]
#r28 = r2 + r14
r15 = self.rtbl[4]
#memb(r12 + # 0) = r9
self.tbl[r0]=r9
#r18 = self.tbl[r14]
#memb(r13 + # 0) = r18.new
self.tbl[r3]=self.tbl[r14]
#r5 = self.tbl[r5]
#memb(r28 + # 0) = r5.new
self.tbl[r14]=self.tbl[r5]
# memb(r7 + # 0) = r8
self.tbl[r5]=r8
r1 = self.tbl[r8]
r5 = r15 + r1
self.rtbl[4] = r5 & 0xFF #.new
r5 = r5 & 0xFF
r3 = self.tbl[r3]
self.rtbl[0] = r4 #Disasm error, was 1
r3 = r3 + r8
r6 = self.tbl[r0]
r7 = self.tbl[r14]
r3 = r3 & 0xFF
r5 = self.tbl[r5]
r5 += r6 + r7
r3 = self.tbl[r3]
r5 = r5 & 0xFF
r3 = r3 ^ r4
r5 = self.tbl[r5]
r5 = self.tbl[r5]
r3 = r3 ^ r5
self.rtbl[1] = r3 # Disasm error, was 0 before
return r3
def SierraCalc9x50_MR1100(self,challenge):
'''
{ r3 = memub(gp+#4192)
r4 = memub(r17++#1) }
{ r5 = add(r3,#1)
memb(gp+#4192) = r5.new }
{ r5 = and(r5,#255)
r6 = memub(gp+#4193)
r3 = memub(r2+r3<<#0) }
{ r3 = add(r6,r3)
r7 = add(r2,r5)
memb(gp+#4193) = r3.new }
{ r3 = and(r3,#255)
r0 = memub(gp+#4191)
r14 = memub(gp+#4190) }
{ r12 = add(r2,r0)
r13 = add(r2,r3)
r8 = memub(r2+r0<<#0)
r9 = memub(r2+r3<<#0) }
{ r28 = add(r2,r14)
r15 = memub(gp+#4194)
memb(r12+#0) = r9 }
{ r18 = memub(r2+r14<<#0)
memb(r13+#0) = r18.new }
{ r5 = memub(r2+r5<<#0)
memb(r28+#0) = r5.new }
{ memb(r7+#0) = r8 }
{ r1 = memub(r2+r8<<#0) }
{ r5 = add(r15,r1)
memb(gp+#4194) = r5.new }
{ r5 = and(r5,#255)
r3 = memub(r2+r3<<#0)
memb(gp+#4191) = r4 }
{ r3 = add(r3,r8)
r6 = memub(r2+r0<<#0)
r7 = memub(r2+r14<<#0) }
{ r3 = and(r3,#255)
r5 = memub(r2+r5<<#0) }
{ r5 += add(r6,r7)
r3 = memub(r2+r3<<#0) }
{ r5 = and(r5,#255)
r3 = xor(r3,r4) }
{ r5 = memub(r2+r5<<#0) }
{ r5 = memub(r2+r5<<#0) }
{ r3 = xor(r3,r5)
memb(gp+#4190) = r3.new }
{ nop
memb(r16++#1) = r3 } :endloop0
'''
r3 = self.rtbl[2]
r4 = challenge
r5 = r3+1
self.rtbl[2] = r5
r5 = r5 & 0xFF
r6 = self.rtbl[3]
r3 = self.tbl[r3]
r3 = r6+r3
#r7 = self.tbl[r5]
self.rtbl[3] = r3 & 0xFF
r3 = r3 & 0xFF
r0 = self.rtbl[1]
r14 = self.rtbl[0]
#r12 = self.tbl[r0]
#r13 = self.tbl[r3]
r8 = self.tbl[r0]
r9 = self.tbl[r3]
#r28 = self.tbl[r14]
r15 = self.rtbl[4]
#memb(r12+#0) = r9
self.tbl[r0]=r9
r18 = self.tbl[r14]
#memb(r13+#0) = r18
self.tbl[r3]=r18
#r5 = self.tbl[r5]
#memb(r28+#0) = r5
#self.tbl[r14]=r5
self.tbl[r14]=self.tbl[r5]
#memb(r7+#0) = r8
self.tbl[r5] = r8
r1 = self.tbl[r8]
r5 = r15+r1
self.rtbl[4] = r5 & 0xFF
r5 = r5 & 0xFF
r3 = self.tbl[r3]
self.rtbl[1] = r4
r3 = r3+r8
r6 = self.tbl[r0]
r7 = self.tbl[r14]
r3 = r3 & 0xFF
r5 = self.tbl[r5]
r5 += r6+r7
r3 = self.tbl[r3]
r5 = r5 & 0xFF
r3 = r3 ^ r4
r5 = self.tbl[r5]
r5 = self.tbl[r5]
r3 = r3 ^ r5
self.rtbl[0] = r3
#Fix
tmp = self.rtbl[0]
self.rtbl[0] = self.rtbl[1]
self.rtbl[1] = tmp
#Fix
return r3
def SierraMDM9x40(self, challenge):
r1 = self.rtbl[4]
r3 = self.rtbl[3]
r2 = r1 + 1
r4 = self.tbl[r1]
r5 = self.rtbl[0]
r1 = r3 + r4
r8 = r5
r3 = challenge
r6 = self.rtbl[1]
r4 = r1 & 0xFF
r13 = r2 & 0xFF
r9 = r6
r7 = self.tbl[r5]
r15 = r4
r14 = r13
r28 = self.tbl[r4]
r12 = self.rtbl[2]
self.tbl[r8] = r28
self.rtbl[1] = r3 #Issue with decompiler, Radare2 was fine, IDA sucked
r8 = self.tbl[r6]
self.rtbl[3] = r1 & 0xFF
self.tbl[r15] = r8
self.rtbl[4] = r2
r8 = self.tbl[r13]
self.tbl[r9] = r8
self.tbl[r14] = r7
r9 = self.tbl[r7]
r8 = self.tbl[r4]
r4 = r12 + r9
r7 = r8 + r7
r5 = self.tbl[r5]
r6 = self.tbl[r6]
r9 = r4 & 0xFF
r8 = r7 & 0xFF
self.rtbl[2] = r4 & 0xFF
r7 = self.tbl[r9]
r8 = self.tbl[r8]
r7 = r7 + (r5 + r6)
r5 = r8 ^ r3
r6 = r7 & 0xFF
r6 = self.tbl[r6]
r3 = self.tbl[r6]
r1 = r5 ^ r3
self.rtbl[0] = r1 #Issue with decompiler, Radare2 was fine, IDA sucked
return r1
def SierraCalc9x30(self, challenge):
r1 = self.rtbl[4]
r3 = self.rtbl[3]
r2 = r1 + 1
r4 = self.tbl[r1]
r5 = self.rtbl[0]
r1 = r3 + r4
r3 = challenge
r6 = self.rtbl[1]
r4 = r1 & 0xFF
r13 = r2 & 0xFF
r7 = self.tbl[r5]
r28 = self.tbl[r4]
r12 = self.rtbl[2]
self.tbl[r5] = r28
self.rtbl[0] = r3
r8 = self.tbl[r6]
self.rtbl[3] = r1 & 0xFF
self.tbl[r4] = r8
self.rtbl[4] = r2 & 0xFF
r8 = self.tbl[r13]
self.tbl[r6] = r8
self.tbl[r13] = r7
r9 = self.tbl[r7]
r8 = self.tbl[r4]
r4 = r12 + r9
r7 = r8 + r7
r5 = self.tbl[r5]
r6 = self.tbl[r6]
r9 = r4 & 0xFF
r8 = r7 & 0xFF
self.rtbl[2] = r4 & 0xFF
r7 = self.tbl[r9]
r8 = self.tbl[r8]
r7 = r7 + r5 + r6
r5 = r8 ^ r3
r6 = r7 & 0xFF
r6 = self.tbl[r6]
r3 = self.tbl[r6]
r1 = r5 ^ r3
self.rtbl[1] = r1
##Fix
tmp = self.rtbl[1]
self.rtbl[1] = self.rtbl[0]
self.rtbl[0] = tmp
##Fix
return r1
def SierraCalc9x07(self,challenge):
r1 = self.rtbl[4]
r3 = self.rtbl[2]
r2 = r1 + 1
r4 = self.tbl[r1]
r5 = self.rtbl[1]
r1 = r3 + r4
r3 = challenge
r6 = self.rtbl[3]
r4 = r1 & 0xFF
r13 = r2 & 0xFF
r7 = self.tbl[r5]
r28 = self.tbl[r4]
r12 = self.rtbl[0]
self.tbl[r5] = r28
self.rtbl[1] = r3
r8 = self.tbl[r6]
self.rtbl[2] = r1 &0xFF
self.tbl[r4] = r8
self.rtbl[4] = r2
r8 = self.tbl[r13]
self.tbl[r6] = r8
self.tbl[r13] = r7
r9 = self.tbl[r7]
r8 = self.tbl[r4]
r4 = r12 + r9
r7 = r8 + r7
r5 = self.tbl[r5]
r6 = self.tbl[r6]
r9 = r4 & 0xFF
r8 = r7 & 0xFF
self.rtbl[0] = r4 &0xFF
r7 = self.tbl[r9]
r8 = self.tbl[r8]
r7 = r7 + (r5 + r6)
r5 = r8 ^ r3
r6 = r7 & 0xFF
r6 = self.tbl[r6]
r3 = self.tbl[r6]
r1 = r5 ^ r3
self.rtbl[3] = r1
##Fix
tmp = self.rtbl[3]
self.rtbl[3] = self.rtbl[1]
self.rtbl[1] = tmp
##Fix
return r1
def SierraCalc9x15(self, challenge):
r6 = self.rtbl[4]
r2 = self.rtbl[2]
r3 = self.tbl[(r6 & 0xFF)]
r5 = self.rtbl[1]
r2 = r3 + r2
r6 = r6 + 1 & 0xFF
r7 = challenge
r3 = self.tbl[(r5 & 0xFF)]
r2 = r2 & 0xFF
r4 = self.rtbl[3]
r8 = self.rtbl[0]
r9 = self.tbl[(r2 & 0xFF)]
self.rtbl[2] = r2
self.tbl[(r5 & 0xFF)] = r9
self.rtbl[4] = r6
r9 = self.tbl[(r4 & 0xFF)]
self.rtbl[1] = r7
self.tbl[(r2 & 0xFF)] = r9
r9 = self.tbl[(r6 & 0xFF)]
self.tbl[(r4 & 0xFF)] = r9
self.tbl[(r6 & 0xFF)] = r3
r9 = self.tbl[(r3 & 0xFF)]
r6 = self.tbl[(r5 & 0xFF)]
r8 = r9 + r8
r5 = self.tbl[(r4 & 0xFF)]
r2 = self.tbl[(r2 & 0xFF)]
r4 = r8 & 0xFF
r3 = r2 + r3
r3 = r3 & 0xFF
r2 = self.tbl[(r4 & 0xFF)]
self.rtbl[0] = r4
r2 += r6 + r5
r3 = self.tbl[(r3 & 0xFF)]
r2 = r2 & 0xFF
r2 = self.tbl[(r2 & 0xFF)]
r2 = self.tbl[(r2 & 0xFF)]
r2 = r2 ^ (r7 ^ r3)
r2 = r2 & 0xFF
self.rtbl[3] = r2
##Fix
tmp = self.rtbl[3]
self.rtbl[3] = self.rtbl[1]
self.rtbl[1] = tmp
##Fix
# r1 = r1+1
# memb (r17 + r1 << #0) = r2
return r2
class SierraGenerator():
tbl=bytearray()
rtbl=bytearray()
def __init__(self):
for i in range(0, 0x14):
self.rtbl.append(0x0)
for i in range(0, 0x100):
self.tbl.append(0x0)
def run(self, devicegeneration, challenge, type):
challenge = bytearray(unhexlify(challenge))
self.devicegeneration=devicegeneration
if not devicegeneration in prodtable:
print("Sorry, "+devicegeneration+" not supported.")
exit(0)
mepid = prodtable[devicegeneration]["openmep"]
cndid = prodtable[devicegeneration]["opencnd"]
lockid = prodtable[devicegeneration]["openlock"]
clen=prodtable[devicegeneration]["clen"]
if len(challenge)<clen:
for i in range(0,clen-len(challenge)):
challenge.append(0)
challengelen=len(challenge)
if type==0: #lockkey
idf=lockid
elif type==1: #mepkey
idf=mepid
elif type==2: #cndkey
idf=cndid
key = keytable[idf * 16:(idf * 16) + 16]
resp = self.SierraKeygen(challenge, key, challengelen, 16)[:challengelen]
resp=hexlify(resp).decode('utf-8').upper()
return resp
def test(self):
#MSM9200 expected=AT!OPENLOCK?BE96CBBEE0829BCA => EEDBF8BFF8DAE346 (!OPENLOCK), 84E7405583ED5845 (!OPENMEP)
#EM7305 expected=AT!OPENLOCK?8101A18AB3C3E66A => D1E128FCA8A963ED
devicegeneration="MSM9200"
challenge="BE96CBBEE0829BCA"
openlock,openmep,opencnd=self.run(devicegeneration,challenge)
if devicegeneration=="MSM9200":
if openlock=="EEDBF8BFF8DAE346" and openmep=="84E7405583ED5845":
challenge = "8101A18AB3C3E66A"
openlock, openmep, opencnd = self.run(devicegeneration, challenge)
if openlock == "D1E128FCA8A963ED":
print("MSM9200 passed")
elif devicegeneration=="MDM9x40":
if openlock == "1033773720F6EE66":
print("MDM9x40 passed")
def SierraPreInit(self,counter, key, keylen, challengelen, mcount):
if counter!=0:
tmp2=0
i=1
while (i<counter):
i=2*i+1
while (True):
tmp=mcount
mcount=tmp+1
challengelen=(key[tmp&0xFF] + self.tbl[(challengelen&0xFF)])&0xFF
if (mcount>=keylen):
mcount=0
challengelen = ((challengelen&0xFF)+keylen)&0xFF
tmp2=tmp2+1
tmp3=((challengelen&0xFF) & i)&0xFF
if tmp2>=0xB:
tmp3=counter%tmp3
if tmp3 <= counter:
break
counter=tmp3 & 0xFF
return [counter,challengelen,mcount]
def SierraInit(self, key, keylen):
if keylen==0 or keylen>0x20:
retval=[0, keylen]
elif keylen >= 1 and keylen <= 0x20:
for i in range(0,0x100):
self.tbl[i]=i&0xFF
mcount=0
cl=keylen&0xffffff00
i=0xFF
while i>-1:
t,cl,mcount=self.SierraPreInit(i, key, keylen, cl, mcount)
m=self.tbl[i]
self.tbl[i]=self.tbl[(t&0xff)]
i = i - 1
self.tbl[(t&0xFF)]=m
self.rtbl[0]=self.tbl[prodtable[self.devicegeneration]["init"][0]] if prodtable[self.devicegeneration]["init"][0]!=0 else self.tbl[(cl&0xFF)]
self.rtbl[1]=self.tbl[prodtable[self.devicegeneration]["init"][1]] if prodtable[self.devicegeneration]["init"][1]!=0 else self.tbl[(cl&0xFF)]
self.rtbl[2]=self.tbl[prodtable[self.devicegeneration]["init"][2]] if prodtable[self.devicegeneration]["init"][2]!=0 else self.tbl[(cl&0xFF)]
self.rtbl[3]=self.tbl[prodtable[self.devicegeneration]["init"][3]] if prodtable[self.devicegeneration]["init"][3]!=0 else self.tbl[(cl&0xFF)]
self.rtbl[4]=self.tbl[prodtable[self.devicegeneration]["init"][4]] if prodtable[self.devicegeneration]["init"][4]!=0 else self.tbl[(cl&0xFF)]
retval=[1, keylen]
return retval
def sierra_calc8F(self, challenge, a=0, b=1, c=2, d=3, e=4, ret=0, ret2=2):
#MDM9200
self.rtbl[b] = (self.rtbl[b] + self.tbl[(self.rtbl[d] & 0xFF)]) & 0xFF
uVar2 = self.rtbl[c] & 0xFF
bVar1 = self.tbl[uVar2]
uVar4 = self.rtbl[b] & 0xFF
self.tbl[uVar2] = self.tbl[uVar4]
self.rtbl[d] = (self.rtbl[d] + 1)&0xFF
uVar5 = self.rtbl[a] & 0xFF
self.tbl[uVar4] = self.tbl[uVar5]
uVar3 = self.rtbl[d] & 0xFF
self.tbl[uVar5] = self.tbl[uVar3]
self.tbl[uVar3] = bVar1
self.rtbl[ret] = challenge #c
self.rtbl[ret2] = self.tbl[self.tbl[(self.tbl[(self.rtbl[e] + self.tbl[bVar1]) & 0xFF] + (self.tbl[uVar5] & 0xFF) + (self.tbl[uVar2] & 0xFF) & 0xff) & 0xFF] & 0xFF] ^ self.tbl[((self.tbl[uVar4] & 0xFF) + (bVar1 & 0xff))&0xFF] ^ challenge #a
self.rtbl[e] = (self.rtbl[e] + self.tbl[bVar1])&0xFF
return self.rtbl[ret2] & 0xFF #a
def SierraAlgo(self, challenge,a=0,b=1,c=2,d=3,e=4,ret=3,ret2=1,flag=1): #M9x15
v6=self.rtbl[e]
v0 = (v6 + 1) & 0xFF
self.rtbl[e]=v0
self.rtbl[c] = (self.tbl[v6+flag & 0xFF] + self.rtbl[c]) & 0xFF
v4 = self.rtbl[c] & 0xFF
v2 = self.rtbl[b] & 0xFF
v1 = self.tbl[(v2&0xFF)]
self.tbl[(v2&0xFF)] = self.tbl[(v4&0xFF)]
v5=self.rtbl[d]&0xFF
self.tbl[(v4&0xFF)] = self.tbl[(v5&0xFF)]
self.tbl[(v5&0xFF)] = self.tbl[(v0&0xFF)]
self.tbl[v0] = v1&0xFF
u = self.tbl[(self.tbl[(self.tbl[((self.rtbl[a] + self.tbl[(v1&0xFF)])&0xFF)] + self.tbl[(v5&0xFF)] + self.tbl[(v2&0xFF)] &0xff)]&0xFF)]
v = self.tbl[((self.tbl[(v4 & 0xFF)] + v1) & 0xFF)]
self.rtbl[ret] = u ^ v ^ challenge
self.rtbl[a] = (self.tbl[(v1 & 0xFF)]+self.rtbl[a]) & 0xFF
self.rtbl[ret2] = challenge & 0xFF
return self.rtbl[ret]&0xFF
def SierraFinish(self):
for i in range(0,0x100):
self.tbl[i]=0
self.rtbl[0]=0
self.rtbl[1]=0
self.rtbl[2]=0
self.rtbl[3]=0
self.rtbl[4]=0
return 1
def SierraKeygen(self, challenge, key, challengelen,keylen):
resultbuffer=bytearray()
for i in range(0,0x100+1):
resultbuffer.append(0x0)
ret, keylen = self.SierraInit(key, keylen)
if ret:
for i in range(0,challengelen):
exec(prodtable[self.devicegeneration]["run"])
self.SierraFinish()
return resultbuffer
def readreply(ser):
info=[]
while (True):
tmp=ser.readline().decode('utf-8').replace('\r','').replace('\n','')
if ("OK" in info):
return info
elif ("ERROR" in info) or info=="":
return -1
info.append(tmp)
return info
def main(args):
version = "1.0"
info = 'Sierra Wireless Generator ' + version + ' (c) B. Kerler 2019'
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
description=info)
parser.add_argument(
'-openlock', '-l',
help='AT!OPENLOCK? modem response',
default="")
parser.add_argument(
'-openmep', '-m',
help='AT!OPENMEP? modem response',
default="")
parser.add_argument(
'-opencnd', '-c',
help='AT!OPENCND? modem response',
default="")
parser.add_argument(
'-devicegeneration', '-d',
help='Device devicegeneration generation',
default="")
parser.add_argument(
'-port', '-p',
help='use com port for auto unlock',
default="")
parser.add_argument(
'-unlock', '-u',
help='use com port for auto unlock',
default=False, action='store_true')
args = parser.parse_args()
openlock = args.openlock
openmep = args.openmep
opencnd = args.opencnd
devicegeneration = args.devicegeneration
if (devicegeneration == "" or (openlock == "" and openmep == "" and opencnd == "")) and not args.unlock:
print(info)
print("------------------------------------------------------------\n")
print("Usage: ./sierrakeygen [-l,-m,-c] [challenge] -d [devicegeneration]")
print("Example: ./sierrakeygen.py -l BE96CBBEE0829BCA -d MDM9200")
print("or: ./sierrakeygen.py -u for auto unlock")
print("or: ./sierrakeygen.py -u -p [portname] for auto unlock with given portname")
print("Supported devicegenerations :")
for key in infotable:
info = f"\t{key}:\t\t"
count = 0
for item in infotable[key]:
count += 1
if (count > 15):
info += "\n\t\t\t\t\t"
count = 0
info += item + ","
info = info[:-1]
print(info)
exit(0)
if devicegeneration == "" and not args.unlock:
print("You need to specific a device generation as well. Option -d")
exit(0)
keygen = SierraGenerator()
port = ""
if args.unlock:
import serial.tools.list_ports
if args.port != "":
port = args.port
else:
for port in serial.tools.list_ports.comports():
if port.vid == 0x1199:
portid = port.location[-1:]
if int(portid) == 3:
port = port.device
print("Detected Sierra Wireless device at: " + port)
break
if port != "":
ser = serial.Serial(port=port, baudrate=115200, bytesize=8, parity='N', stopbits=1, timeout=1)
ser.write(b"ATI\r")
info = readreply(ser)
if info != -1:
for line in info:
if "Revision" in line:
if "SWI9X15" in line:
devicegeneration = "MDM9x15"
elif "SWI9X30" in line:
devicegeneration = "MDM9x30"
elif "SWI9X40" in line:
devicegeneration = "MDM9x40"
elif "SWI9X50" in line:
devicegeneration = "MDM9x50"
break
else:
print("Error on getting ATI modem response. Wrong port? Aborting.")
ser.close()
exit(0)
if devicegeneration == "":
print("Unknown device generation. Please send me details :)")
else:
print("Device generation detected: " + devicegeneration)
print("Sending AT!ENTERCND=\"A710\" request.")
ser.write(b"AT!ENTERCND=\"A710\"\r")
info = readreply(ser)
if info == -1:
print("Uhoh ... invalid entercnd password. Aborting ...")
ser.close()
exit(0)
print("Sending AT!OPENLOCK? request")
ser.write(b"AT!OPENLOCK?\r")
info = readreply(ser)
challenge = ""
if info != -1:
if len(info) > 2:
challenge = info[1]
else:
print("Error on AT!OPENLOCK? request. Aborting.")
ser.close()
exit(0)
if challenge == "":
print("Error: Couldn't get challenge. Aborting.")
ser.close()
exit(0)
resp = keygen.run(devicegeneration, challenge, 0)
print("Sending AT!OPENLOCK=\"" + resp + "\" response.")
ser.write(bytes("AT!OPENLOCK=\"" + resp + "\"\r", "utf-8"))
info = readreply(ser)
if info == -1:
print("Damn. AT!OPENLOCK failed.")
else:
print("Success. Device is now engineer unlocked.")
ser.close()
exit(0)
else:
if openlock != "":
resp = keygen.run(devicegeneration, openlock, 0)
print("AT!OPENLOCK=\"" + resp + "\"")
# -l BE96CBBEE0829BCA -d MDM9x40 ==> AT!OPENLOCK="1033773720F6EE66"
elif openmep != "":
resp = keygen.run(devicegeneration, openmep, 1)
print("AT!OPENMEP=\"" + resp + "\"")
elif opencnd != "":
resp = keygen.run(devicegeneration, opencnd, 2)
print("AT!OPENCND=\"" + resp + "\"")
if __name__ == '__main__':
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment