Поскольку программ для сборки и редактирования закриптованных SHX этого поколения телефонов не существует, я немного разобрался в структуре SHX файлов и решил написать этот небольшой мануал.
01. Распаковываем SHX с помощью RSD Lite или MFFT, трюком с несовместимым телефоном или выдёргиванием шнура до начала прошивки.
Flash&Backup 3 и SBF-Recalc не годятся, распаковывают такие SHX'ы кривовато.
02. Декриптуем каждый SMG с помощью fl_decr.EXE от Vilko.
03. Открываем SBF-Recalc'ом SHX-файл, чтобы прочитать чексуммы кодовых групп из его заголовка.
Адресация здесь кривая и не совпадает с реальной для расчёта чексумм. Аналогично в карте памяти RAMDLD, но по нему считаются чексуммы. Реальная адресация в карте памяти CG0 в самой прошивке.
04. Создаём бинарную болванку в HEX-редакторе размером во Flash Chip телефона: 4, 8, 16 MB и т.д. забитую полностью FF-нулями. Копируем внутрь раскриптованные кодовые группы так, будто этот бинарь — FlashROM телефона.
Используем кривые адреса с перехлёстами из заголовка SHX (в SBF-Recalc они как раз показаны).
Эта болванка позволит нарезать нам куски CG для корректного подсчёта чексумм.
05. Открываем распакованный RAMDLD, смотрим в нём карту памяти и нарезаем болванку-бинарь согласно карте памяти в RAMDLD на кодовые группы.
CG0 и CG1 здесь пока ещё слеплены в одно целое, называем CG01.bin получившийся файлик.
06. Разделяем CG0 и CG1 из файла CG01.bin на файлы CG0.bin и CG1.bin, размер CG0 может быть как C4h, так и C8h, для уточнения размера следует смотреть карту памяти в самом CG0.
Забиваем первые восемь 8 байт у CG0 значениями FF. Именно эта хрень не даёт включиться телефону если чексуммы не сошлись.
07. Скриптом выше рассчитываем чексуммы каждой из вырезанных из болванки кодовых групп.
Они должны совпадать с теми, что прописаны в заголовок SHX. Если всё сошлось — отлично, двигаемся дальше!
08. Теперь мы можем патчить и редактировать эти бинари из болванок любым образом в пределах их размеров. Например, применить патч для разблокировки записи PDS SEEMs, что поможет снять SIM-Lock.
09. Сохраняем патчи в бинаре, рассчитываем изменившеюся чексумму. Бинарь восстанавливаем до вида как он распаковывается из SHX (к примеру убираем перехлёсты и сокращаем размер) и затем криптуем его обратно утилитой fl_crypt.EXE от Vilko.
10. И только теперь переходим к редактированию SHX-файла. Во-первых, проставляем новую чексумму в заголовок SHX. На примере выше, было 52C7 стало 557F, внимание, в заголовке SHX все адреса и значения в Little-Endian формате! Это значит нужно перевернуть все байты в числе.
11. Теперь переходим к переносу патча в сам SHX. Сравнительным анализом с помощью утилиты vbindiff или подобной, находим разницу в байтах в закриптованных файлах:
12. Ищем оригинальные S3-Record строки внутри SHX-файла с теми значениями байт, которые пока не менялись. Таких нашлось две штуки, в которые попали наши четыре изменения. Важно захватить каждую строку. Их может быть как больше, так и меньше. Изменения могут быть разбиты по нескольким S3-строкам данных.
Меняем текстовые значения на пропатченные, именно в ASCII, а не в байтах.
13. Скриптом пересчитываем правильные строчные чексуммы S-Records и записываем их в файл. Удобно использовать Notepad++ для сверки чексумм в S-Records, для этого нужно отрезать заголовок размером 1FEC файлу SHX и сохранить полученный результат в формате firmware.srec, это позволит просматривать и валидировать чексуммы подсветкой синтаксиса.
14. Теперь нужно подсчитать чексумму всего SHX-файла. Для этого у SHX-файла отгрызаем самый последний терминатор в конце файла такого вида:
Формат у него такой: S7054353XXXXYY — XXXX это чексумма файла, YY это чексумма S-Record строки.
Рассчитываем скриптом новую чексумму XXXX на весь файл:
Для само-проверки проверяем чексумму оригинальной прошивки. Должны совпадать!
Чексумму YY снова рассчитываем скриптом:
И сохраняем пересчитанный терминатор S705435302A5BD в файл.
15. Итоговые изменения в SHX-файле в сравнении с оригинальным.
1. Пересчёт раскриптованной чексуммы CG1.
2. Инъецированный патч.
3. Пересчитанный терминатор.
Для самоконтроля можно распаковать пропатченный файл SHX, декриптовать бинарные кодовые группы и проверить валидность патча.
Прикреплённые файлы:
01. Распаковываем SHX с помощью RSD Lite или MFFT, трюком с несовместимым телефоном или выдёргиванием шнура до начала прошивки.
Flash&Backup 3 и SBF-Recalc не годятся, распаковывают такие SHX'ы кривовато.
02. Декриптуем каждый SMG с помощью fl_decr.EXE от Vilko.
03. Открываем SBF-Recalc'ом SHX-файл, чтобы прочитать чексуммы кодовых групп из его заголовка.
Адресация здесь кривая и не совпадает с реальной для расчёта чексумм. Аналогично в карте памяти RAMDLD, но по нему считаются чексуммы. Реальная адресация в карте памяти CG0 в самой прошивке.
04. Создаём бинарную болванку в HEX-редакторе размером во Flash Chip телефона: 4, 8, 16 MB и т.д. забитую полностью FF-нулями. Копируем внутрь раскриптованные кодовые группы так, будто этот бинарь — FlashROM телефона.
Используем кривые адреса с перехлёстами из заголовка SHX (в SBF-Recalc они как раз показаны).
Эта болванка позволит нарезать нам куски CG для корректного подсчёта чексумм.
05. Открываем распакованный RAMDLD, смотрим в нём карту памяти и нарезаем болванку-бинарь согласно карте памяти в RAMDLD на кодовые группы.
CG0 и CG1 здесь пока ещё слеплены в одно целое, называем CG01.bin получившийся файлик.
06. Разделяем CG0 и CG1 из файла CG01.bin на файлы CG0.bin и CG1.bin, размер CG0 может быть как C4h, так и C8h, для уточнения размера следует смотреть карту памяти в самом CG0.
Забиваем первые восемь 8 байт у CG0 значениями FF. Именно эта хрень не даёт включиться телефону если чексуммы не сошлись.
Код
#!/usr/bin/env python3
import sys
def checksum_srec(srecord):
old_srec = srecord[:-2]
old_chk = srecord[-2:]
new_srec = old_srec[2:]
byte_sum = sum([int(new_srec[i:i + 2], 16) for i in range(0, len(new_srec), 2)])
new_chk = ~(byte_sum & 0xFF) & 0xFF
if old_chk.upper() != f'{new_chk:02X}'.upper():
print(f'Warning: {old_chk} != {new_chk:02X}')
return old_srec + f'{new_chk:02X}'
def checksum_16(data):
checksum = 0
for byte in data:
checksum = (checksum + byte) % 65536
return checksum
def bin_checksum(file_path):
with open(file_path, 'rb') as binary_file:
return checksum_16(binary_file.read())
if __name__ == '__main__':
if len(sys.argv) != 3:
print('Usage: ./shx_chk_sum.py <mode> <file or data>')
print()
print('Examples:')
print('\t./shx_chk_sum.py F CG1.bin')
print('\t./shx_chk_sum.py S S705435302DD85')
sys.exit(1)
mode = sys.argv[1]
data = sys.argv[2]
if mode == 'F':
print(f'{data} checksum_16 is: {bin_checksum(data):04X}')
elif mode == 'S':
print(f'{checksum_srec(data)}')
else:
print('Unknown mode!')
sys.exit(1)
sys.exit(0)
import sys
def checksum_srec(srecord):
old_srec = srecord[:-2]
old_chk = srecord[-2:]
new_srec = old_srec[2:]
byte_sum = sum([int(new_srec[i:i + 2], 16) for i in range(0, len(new_srec), 2)])
new_chk = ~(byte_sum & 0xFF) & 0xFF
if old_chk.upper() != f'{new_chk:02X}'.upper():
print(f'Warning: {old_chk} != {new_chk:02X}')
return old_srec + f'{new_chk:02X}'
def checksum_16(data):
checksum = 0
for byte in data:
checksum = (checksum + byte) % 65536
return checksum
def bin_checksum(file_path):
with open(file_path, 'rb') as binary_file:
return checksum_16(binary_file.read())
if __name__ == '__main__':
if len(sys.argv) != 3:
print('Usage: ./shx_chk_sum.py <mode> <file or data>')
print()
print('Examples:')
print('\t./shx_chk_sum.py F CG1.bin')
print('\t./shx_chk_sum.py S S705435302DD85')
sys.exit(1)
mode = sys.argv[1]
data = sys.argv[2]
if mode == 'F':
print(f'{data} checksum_16 is: {bin_checksum(data):04X}')
elif mode == 'S':
print(f'{checksum_srec(data)}')
else:
print('Unknown mode!')
sys.exit(1)
sys.exit(0)
07. Скриптом выше рассчитываем чексуммы каждой из вырезанных из болванки кодовых групп.
Код
$ ./shx_chk_sum.py F t720pm_g_05.41.54r_flashRAMDLD.bin
t720pm_g_05.41.54r_flashRAMDLD.bin checksum_16 is: 36AD
$ ./shx_chk_sum.py F CG0.bin
CG0.bin checksum_16 is: 9DE1
$ ./shx_chk_sum.py F CG1.bin
CG1.bin checksum_16 is: 52C7
$ ./shx_chk_sum.py F CG3.bin
CG3.bin checksum_16 is: 150D
$ ./shx_chk_sum.py F CG4.bin
CG4.bin checksum_16 is: 369E
t720pm_g_05.41.54r_flashRAMDLD.bin checksum_16 is: 36AD
$ ./shx_chk_sum.py F CG0.bin
CG0.bin checksum_16 is: 9DE1
$ ./shx_chk_sum.py F CG1.bin
CG1.bin checksum_16 is: 52C7
$ ./shx_chk_sum.py F CG3.bin
CG3.bin checksum_16 is: 150D
$ ./shx_chk_sum.py F CG4.bin
CG4.bin checksum_16 is: 369E
Они должны совпадать с теми, что прописаны в заголовок SHX. Если всё сошлось — отлично, двигаемся дальше!
08. Теперь мы можем патчить и редактировать эти бинари из болванок любым образом в пределах их размеров. Например, применить патч для разблокировки записи PDS SEEMs, что поможет снять SIM-Lock.
09. Сохраняем патчи в бинаре, рассчитываем изменившеюся чексумму. Бинарь восстанавливаем до вида как он распаковывается из SHX (к примеру убираем перехлёсты и сокращаем размер) и затем криптуем его обратно утилитой fl_crypt.EXE от Vilko.
Код
$ ./shx_chk_sum.py F CG1.bin
CG1.bin checksum_16 is: 557F
CG1.bin checksum_16 is: 557F
10. И только теперь переходим к редактированию SHX-файла. Во-первых, проставляем новую чексумму в заголовок SHX. На примере выше, было 52C7 стало 557F, внимание, в заголовке SHX все адреса и значения в Little-Endian формате! Это значит нужно перевернуть все байты в числе.
11. Теперь переходим к переносу патча в сам SHX. Сравнительным анализом с помощью утилиты vbindiff или подобной, находим разницу в байтах в закриптованных файлах:
Код
vbindiff t720pm_g_05.41.54r_flashCG1.smg CG1.smg
12. Ищем оригинальные S3-Record строки внутри SHX-файла с теми значениями байт, которые пока не менялись. Таких нашлось две штуки, в которые попали наши четыре изменения. Важно захватить каждую строку. Их может быть как больше, так и меньше. Изменения могут быть разбиты по нескольким S3-строкам данных.
Меняем текстовые значения на пропатченные, именно в ASCII, а не в байтах.
Код
S3451040A5C029C34B32380CD1664AD093D0E853F9F329C34B32380CD166E93115DAB22B702C29C34B32380CD1660E99334F09E2588529C34B32380CD166EDADD251A56EAA12D2
S3451040A60029C34B32380CD1663AAEDA2D3D31F91B29C34B32380CD166C6D9C3A30C04745029C34B32380CD166914209E1DAC3FF1529C34B32380CD1661CEF968D67DCEFA478
S3451040A60029C34B32380CD1663AAEDA2D3D31F91B29C34B32380CD166C6D9C3A30C04745029C34B32380CD166914209E1DAC3FF1529C34B32380CD1661CEF968D67DCEFA478
13. Скриптом пересчитываем правильные строчные чексуммы S-Records и записываем их в файл. Удобно использовать Notepad++ для сверки чексумм в S-Records, для этого нужно отрезать заголовок размером 1FEC файлу SHX и сохранить полученный результат в формате firmware.srec, это позволит просматривать и валидировать чексуммы подсветкой синтаксиса.
Код
$ ./shx_chk_sum.py S S3451040A5C029C34B32380CD1664AD093D0E853F9F329C34B32380CD166E93115DAB22B702C29C34B32380CD166C9A2E6AB15F9973129C34B32380CD166EEEB77BB16BC19D8D2
Warning: D2 != AF
S3451040A5C029C34B32380CD1664AD093D0E853F9F329C34B32380CD166E93115DAB22B702C29C34B32380CD166C9A2E6AB15F9973129C34B32380CD166EEEB77BB16BC19D8AF
$ ./shx_chk_sum.py S S3451040A60029C34B32380CD1663AAEDA2D3D31F91B29C34B32380CD166C6D9C3A30C04745029C34B32380CD1664CF2F6440B15F30929C34B32380CD1668EFE100CEE066B2C78
Warning: 78 != 23
S3451040A60029C34B32380CD1663AAEDA2D3D31F91B29C34B32380CD166C6D9C3A30C04745029C34B32380CD1664CF2F6440B15F30929C34B32380CD1668EFE100CEE066B2C23
Warning: D2 != AF
S3451040A5C029C34B32380CD1664AD093D0E853F9F329C34B32380CD166E93115DAB22B702C29C34B32380CD166C9A2E6AB15F9973129C34B32380CD166EEEB77BB16BC19D8AF
$ ./shx_chk_sum.py S S3451040A60029C34B32380CD1663AAEDA2D3D31F91B29C34B32380CD166C6D9C3A30C04745029C34B32380CD1664CF2F6440B15F30929C34B32380CD1668EFE100CEE066B2C78
Warning: 78 != 23
S3451040A60029C34B32380CD1663AAEDA2D3D31F91B29C34B32380CD166C6D9C3A30C04745029C34B32380CD1664CF2F6440B15F30929C34B32380CD1668EFE100CEE066B2C23
14. Теперь нужно подсчитать чексумму всего SHX-файла. Для этого у SHX-файла отгрызаем самый последний терминатор в конце файла такого вида:
Код
S705435302DD85
Формат у него такой: S7054353XXXXYY — XXXX это чексумма файла, YY это чексумма S-Record строки.
Рассчитываем скриптом новую чексумму XXXX на весь файл:
Код
$ ./shx_chk_sum.py F T720PM_G_05.41.54R_flash_.shx
T720PM_G_05.41.54R_flash_.shx checksum_16 is: 02DD
$ ./shx_chk_sum.py F T720PM_G_05.41.54R_flash_PDS_SEEMs_Patch_.shx
T720PM_G_05.41.54R_flash_PDS_SEEMs_Patch_.shx checksum_16 is: 02A5
T720PM_G_05.41.54R_flash_.shx checksum_16 is: 02DD
$ ./shx_chk_sum.py F T720PM_G_05.41.54R_flash_PDS_SEEMs_Patch_.shx
T720PM_G_05.41.54R_flash_PDS_SEEMs_Patch_.shx checksum_16 is: 02A5
Для само-проверки проверяем чексумму оригинальной прошивки. Должны совпадать!
Чексумму YY снова рассчитываем скриптом:
Код
$ ./shx_chk_sum.py S S705435302A585
Warning: 85 != BD
S705435302A5BD
Warning: 85 != BD
S705435302A5BD
И сохраняем пересчитанный терминатор S705435302A5BD в файл.
15. Итоговые изменения в SHX-файле в сравнении с оригинальным.
1. Пересчёт раскриптованной чексуммы CG1.
2. Инъецированный патч.
3. Пересчитанный терминатор.
Для самоконтроля можно распаковать пропатченный файл SHX, декриптовать бинарные кодовые группы и проверить валидность патча.
Прикреплённые файлы: