회사에서 BMS 제품을 인수했다. 72V 리튬이온 배터리 관리 시스템.
받은 것:
- 완제품 10대
- 회로도 (PDF)
- HEX 파일 (펌웨어)
- 소스코드 → 없음
문제 발생
현장에서 버그가 발견됐다. 펌웨어 수정이 필요한데…
"소스코드 주세요"
"전 담당자 퇴사했어요"
"서버에 백업 없음"
"Git이 뭐예요?"
소스코드 증발. 실화다.
선택지
- 처음부터 다시 개발 - 6개월+
- 버그 무시 - 고객 클레임
- 역분석으로 복원 - ???
3번을 선택했다. 어차피 펌웨어는 있으니까.
다행히 있던 것들
부트로더 HEX 파일 하나. 16KB.
200429.hex
CAN 통신으로 펌웨어 업데이트하는 기능이 있다고 한다. 프로토콜 문서? 없다.
기적적으로 헤더 파일 일부가 남아있었다:
/* PC → BMS (0x5FF) */
#define IAP_BMS_P2B_CONN_KEY_REQ 0x30
#define IAP_BMS_P2B_CONN_KEYCAL_REQ 0x31
#define IAP_BMS_P2B_SIZE_RES 0x32
/* BMS → PC (0x5FE) */
#define IAP_BMS_B2P_CONN_KEY_RES 0x40
#define IAP_BMS_B2P_CONN_OK 0x41
명령 코드는 알겠는데, 구현 로직을 모른다.
CAN 스니핑
기존 EXE 업로더를 실행하면서 CAN 버스 스니핑:
PC → BMS (0x5FF): 30 00 00 00 00 00 00 00
BMS → PC (0x5FE): 40 12 34 56 78 20 04 29
PC → BMS (0x5FF): 31 XX XX XX XX 00 00 00
BMS → PC (0x5FE): 41 00 00 00 00 00 00 00
0x30 → 0x40: Connection 요청/응답. 0x40 응답에 20 04 29 → 날짜? (2020-04-29). 0x31로 뭔가 계산값 보내는데 이게 뭔지 모르겠다.
스니핑만으로는 한계. 부트로더 바이너리를 직접 분석해야 한다.
왜 Ghidra인가
IDA Pro는 업계 표준이지만 라이선스 수백만원.
Ghidra는 NSA에서 2019년 공개한 무료 도구. ARM Cortex-M 지원하고, 디컴파일러 내장이고, 무료다. IDA Pro 90% 수준이면 이거다.
분석 대상
ST-Link로 플래시 덤프:
0x08000000 ~ 0x08003FFF: 부트로더 (16KB)
0x08004000 ~ 0x08041FFF: 버퍼 영역 (254KB)
0x08042800 ~ 0x0807FFFF: 애플리케이션 (246KB)
목표
- 부트로더 프로토콜 파악
- Connection Key 알고리즘 해독
- Python 업로더 제작
- (보너스) 부트로더 소스 복원
소스코드 백업은 필수다. Git, NAS, 클라우드 어디든. 역분석은 최후의 수단이다. 시간 많이 든다.
그래도 HEX 파일이라도 있어서 다행이다.
다음 글에서 HEX 파일 구조부터 살펴본다.