회사에서 BMS 제품을 인수했다. 72V 리튬이온 배터리 관리 시스템.

받은 것:

  • 완제품 10대
  • 회로도 (PDF)
  • HEX 파일 (펌웨어)
  • 소스코드 → 없음

문제 발생

현장에서 버그가 발견됐다. 펌웨어 수정이 필요한데…

"소스코드 주세요"
"전 담당자 퇴사했어요"
"서버에 백업 없음"
"Git이 뭐예요?"

소스코드 증발. 실화다.


선택지

  1. 처음부터 다시 개발 - 6개월+
  2. 버그 무시 - 고객 클레임
  3. 역분석으로 복원 - ???

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

0x300x40: 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)

목표

  1. 부트로더 프로토콜 파악
  2. Connection Key 알고리즘 해독
  3. Python 업로더 제작
  4. (보너스) 부트로더 소스 복원

소스코드 백업은 필수다. Git, NAS, 클라우드 어디든. 역분석은 최후의 수단이다. 시간 많이 든다.

그래도 HEX 파일이라도 있어서 다행이다.

다음 글에서 HEX 파일 구조부터 살펴본다.

#2 - HEX 파일 구조