Skip to content

Instantly share code, notes, and snippets.

@plugnburn
Created June 16, 2020 22:16
Show Gist options
  • Save plugnburn/afdef1d10f17f1e744bf3a36592e6a02 to your computer and use it in GitHub Desktop.
Save plugnburn/afdef1d10f17f1e744bf3a36592e6a02 to your computer and use it in GitHub Desktop.
MTPhreak-6572: sKai-specific MP0B_001 file modifier
-- MTPhreak IMEI changer and randomizer for MediaTek NVRAM
-- This version is adapted specifically for the Sigma sKai and other MT6572 based phones
-- Usage: lua mtphreak-6572.lua NVRAMfile [imei1 [imei2]]
-- If no IMEIs are passed, they are randomized (with respect to Luhn checksum)
function parseImei(imeistr) -- imei string to 12-byte table
local imeiTbl = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
for i = 1, 15 do
local digit = tonumber(imeistr:sub(i,i))
local x = ((i - 1) >> 1) + 1
if i&1 == 1 then
imeiTbl[x] = imeiTbl[x] | digit
else
imeiTbl[x] = imeiTbl[x] | (digit << 4)
end
end
return imeiTbl
end
function tblToBytestring(tbl)
local s = ""
for i=1, #tbl do
s = s .. string.char(tbl[i])
end
return s
end
function encodeImei(imeistr, mk)
local opBlk = parseImei(imeistr)
for index, value in ipairs(opBlk) do
opBlk[index] = value ~ mk[index]
end
for i = 1, 10 do
local targetIndex = (i&1 == 0) and 12 or 11
opBlk[targetIndex] = (opBlk[targetIndex] + opBlk[i]) % 256
end
return tblToBytestring(opBlk)
end
function getRandomImei()
local imeiRndStr = string.format("%014d", math.random(0,10000000) .. math.random(0,10000000))
local imei = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
local revmap = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9}
for i = 1, 14 do
imei[i] = tonumber(imeiRndStr:sub(i,i))
end
local oddsum = imei[1] + imei[3] + imei[5] + imei[7] + imei[9] + imei[11] + imei[13]
local evensum = revmap[imei[2] + 1] + revmap[imei[4] + 1] + revmap[imei[6] + 1]
+ revmap[imei[8] + 1] + revmap[imei[10] + 1] + revmap[imei[12] + 1] + revmap[imei[14] + 1]
local luhn = 10 - (oddsum + evensum) % 10
return imeiRndStr .. ((luhn > 9) and 0 or luhn)
end
-- main command part
local imeiFileName = arg[1]
local imeiFile = assert(io.open(imeiFileName, "rb"))
local imei1 = arg[2]
local imei2 = arg[3]
local imeiFull = imeiFile:read("*all")
imeiFile:seek("end", -12)
local masterKey = { string.byte(imeiFile:read("*all"), 1, -1) }
-- for MT6572, we don't need the bitwise inversion of master key!
-- However, we need another mask transformation
local masterMask = {0x68, 3, 0x41, 0x20, 0, 0, 0x50, 0xf2, 0x87, 1, 0, 0}
for index, value in ipairs(masterKey) do
masterKey[index] = value ~ masterMask[index]
end
masterKey[11] = 0
masterKey[12] = 0
-- now we have the master key table ready
assert(imeiFile:close())
if imei1 == nil and imei2 == nil then -- randomize
math.randomseed(os.clock()*100000000000)
imei1 = getRandomImei()
imei2 = getRandomImei()
end
imeiFile = assert(io.open(imeiFileName, "wb"))
imeiFile:write(imeiFull)
if imei1 ~= nil then -- write the first IMEI
print('Writing IMEI 1: ' .. imei1)
local encodedImei1 = encodeImei(imei1, masterKey)
imeiFile:seek("set")
imeiFile:write(encodedImei1)
end
if imei2 ~= nil then -- write the second IMEI
print('Writing IMEI 2: ' .. imei2)
local encodedImei2 = encodeImei(imei2, masterKey)
imeiFile:seek("set", 12)
imeiFile:write(encodedImei2)
end
assert(imeiFile:close())
print('IMEIs written to ' .. imeiFileName)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment