RT-4D: реверс прошивки, русификация, кастомный UI, флешеры
- Полный RE стока V3.25 (Cortex-M4F) + FM100B: карта памяти, протокол, codeplug, UI-архитектура - Русификация: свой CP1251-шрифт + патч рендера, перевод меню и надписей, ребренд Ru-4D V3.25 - Блюпринт переделки UI + C-тулчейн (clang thumbv7em), доказан инъекцией - Готовые флешеры: WebSerial .html и Windows .exe со вшитой прошивкой - Дамп SPI рации, стоковая прошивка, инструменты сборки Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Этот коммит содержится в:
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Inject the compiled custom UI blob (ui/my_ui_code.bin, my_draw_router @0x08029000)
|
||||
over the russified image and redirect the draw-dispatch bl @0x080207E6 to it."""
|
||||
import struct
|
||||
from keystone import Ks, KS_ARCH_ARM, KS_MODE_THUMB
|
||||
|
||||
BASE = 0x08002800
|
||||
UI_BASE = 0x08029000 # free flash, after russification cave+font
|
||||
DRAW_BL = 0x080207E6 # bl 0x0801E1BC in ui_tick_normal
|
||||
ROOT = "C:/Users/vikto/Documents/Claude/rt-4d"
|
||||
|
||||
def main():
|
||||
img = bytearray(open(f"{ROOT}/stock-fw/rt4d_ru_full.bin", "rb").read())
|
||||
blob = open(f"{ROOT}/ui/my_ui_code.bin", "rb").read() # my_draw_router first
|
||||
end = (UI_BASE - BASE) + len(blob)
|
||||
if len(img) < end:
|
||||
img += b"\xff" * (end - len(img))
|
||||
img[UI_BASE-BASE:UI_BASE-BASE+len(blob)] = blob
|
||||
|
||||
ks = Ks(KS_ARCH_ARM, KS_MODE_THUMB)
|
||||
old = bytes(img[DRAW_BL-BASE:DRAW_BL-BASE+4])
|
||||
new = bytes(ks.asm(f"bl #{UI_BASE}", DRAW_BL)[0]); assert len(new) == 4
|
||||
img[DRAW_BL-BASE:DRAW_BL-BASE+4] = new
|
||||
|
||||
out = f"{ROOT}/stock-fw/rt4d_ui_home.bin"
|
||||
open(out, "wb").write(img)
|
||||
print(f"blob {len(blob)}B @0x{UI_BASE:08X} | draw bl @0x{DRAW_BL:08X}: {old.hex()} -> {new.hex()}")
|
||||
print(f"image {len(img)}B -> {out}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Ссылка в новой задаче
Block a user