1만 원대 장난감 카메라에서 구동된 DOOM: 공용 펌웨어의 허점이 열어준 해커의 놀이터

1만 원대 장난감 카메라에서 구동된 DOOM: 공용 펌웨어의 허점이 열어준 해커의 놀이터

DOOM하드웨어 리버스 엔지니어링펌웨어 해킹임베디드 시스템HX3302B소비자 가전

데이터 소스:Hackaday + Spode's Abode

2026년 11월 초, 리버스 엔지니어링 개발자 앤드루 스포드가 인상적인 하드웨어 해킹 결과를 공개했다. 온라인 쇼핑몰에서 1만 원대에 구입한 무명 어린이용 장난감 카메라에서 고전 FPS 명작 게임인 《DOOM》을 온전히 이식해 구동하는 데 성공한 것이다. 게임 내 이동과 사격이 정상 작동하며, 약 30프레임의 부드러운 화면 재생과 함께 다성 폴리포닉 음향 효과 및 배경음악까지 지원한다.

플라스틱 외관에는 만화 캐릭터 그림이 인쇄되어 있고, 상자에는 제조사 이름이나 상표조차 없으며 설명서에 적힌 유일한 모델명은 ‘X9S’뿐이었다. 하지만 이 조잡한 껍데기 내부에는 32비트 사양의 중국산 SoC인 HX3302B 칩셋이 탑재되어 있었다.

노브랜드 하드웨어 공급망은 단가를 최대한 낮추기 위해 시장에 이미 나와 있는 턴키 메인 제어 칩셋 솔루션을 그대로 가져다 쓴다. 덕분에 저렴한 장난감 기기임에도 단순한 사진 촬영 용도를 훌쩍 뛰어넘는 연산 능력을 품게 되었다. 게다가 빠른 출시를 위해 보안 검증을 거의 생략한 공용 펌웨어 설계 탓에, 이 폐쇄적인 장난감은 하드웨어 리버스 엔지니어링을 위한 이상적인 실험실로 탈바꿈했다.

장난감 카메라 화면에서 부드럽게 구동되는 DOOM 게임 화면 사진: 소형 컬러 화면에서 30프레임으로 DOOM을 구동 중인 어린이용 장난감 카메라. 출처: Spode’s Abode.

남은 891KB 메모리로 DOOM 구동: 1만 원대 장난감에 숨겨진 120 MIPS 연산력

본체를 분해하기 전에는 인터넷에서 관련 기술 자료를 거의 찾을 수 없었다. 유일한 단서는 테스트 촬영된 사진의 EXIF 메타데이터에 있었다. 제조사 항목에 적힌 ‘HX-Tech’라는 문구는 하드웨어 해커 예룬 돔버그의 이전 기기 분해 기록을 떠올리게 했다.

스포드는 배터리 연결선을 인두기로 떼어내고 내부 회로 기판을 분리했다. 기판 중앙에는 HX3302B 칩과 8핀 규격의 4MB SPI 플래시 메모리가 자리 잡고 있었다. 프로그래머 장비로 펌웨어를 덤프해 분석한 결과, CPU 코어가 OpenRISC 명령어 집합을 사용한다는 사실이 확인되었다.

마이크로벤치마크 테스트를 통해 칩의 연산 성능이 드러났다. 이 저전력 칩셋은 8KB L1 명령어 캐시와 8KB 데이터 캐시를 갖추고 있으며 캐시 대역폭은 164MB/s에 달했다. 프로세서는 최대 120 MIPS의 연산 처리 성능을 발휘했고, 잦은 분기 예측 실패 상황에서도 82 MIPS를 유지했다. 30년 전 출시된 고전 3D 게임 엔진의 프로젝션 연산을 감당하기에 차고 넘치는 수준이었다.

진짜 병목은 메모리 용량이었다. 기기 전체의 물리적 RAM은 2MB(읽기 속도 65MB/s)에 불과했다. 시스템 작업과 디스플레이 프레임버퍼가 대부분의 영역을 차지해 사용자 애플리케이션에 할당 가능한 여유 힙 메모리는 891KB뿐이었다. CPU 연산 자원은 여유로웠지만, 게임 엔진 전체를 1MB도 안 되는 좁은 공간에 우겨넣어야 했다.

분해된 어린이 장난감 카메라 기판과 메인 칩셋 사진: 장난감 카메라 기판 위의 HX3302B 칩셋과 8핀 플래시 메모리. 출처: Spode’s Abode.

EXIF를 활용한 펌웨어 블라인드 덤프: 검증을 생략한 공용 설계의 허점

펌웨어 업데이트 루틴은 방어선을 뚫는 첫 번째 통로가 되었다. 카메라는 전원이 켜질 때마다 SD 카드 루트 디렉터리에 있는 Xly100s.bin 파일을 검색한다. 파일 헤더에 체크섬 필드가 준비되어 있었지만, 부트로더 업데이트 프로그램은 해시값을 전혀 검증하지 않았다.

또한 업데이트 루틴은 부분 덮어쓰기 방식을 취하고 있었다. 플래시 메모리의 시작 번지부터 기록을 시작하며, 덮어쓰는 길이는 입력된 파일의 크기에 따라 결정되었다. 즉, 1MB 크기의 파일을 넣으면 앞부분 1MB만 변경되고 나머지 3MB 영역은 그대로 유지되었다. 헤더의 타임스탬프만 살짝 바꿔주면 펌웨어 덮어쓰기가 실행되므로, SD 카드 슬롯은 사실상 검증 없는 코드 삽입 경로로 열려 있었다.

쓰기 권한을 확보한 뒤 필요한 작업은 내부 메모리 구조를 파악하는 일이었다. 스포드는 메모리 덤프 데이터를 사진의 EXIF 헤더에 저장하는 기발한 방식을 고안했다. 표준 JPEG 규격은 최대 64KB의 EXIF 메타데이터를 담을 수 있지만, 카메라 기본 소프트웨어는 약 730바이트만 사용하고 있었다.

스포드는 카메라의 사진 저장 루틴을 패치했다. 전용 하드웨어 인코더가 내부 부팅 메모리에 직접 접근할 수 없었기 때문에, CPU를 통해 대상 메모리 영역을 잘라내어 EXIF 버퍼로 복사하도록 만들었다. 셔터를 한 번 누를 때마다 4KB의 내부 메모리를 기록하고 포인터를 다음 구간으로 이동시켰다. 셔터를 16번 연속으로 누르자 64KB 부팅 메모리 전체가 SD 카드에 온전히 덤프되었다. 데이터를 비교 분석한 결과 마스크 ROM 같은 잠금장치는 없었으며, 모든 로우레벨 코드가 고스란히 노출되어 있었다.

29KB 핵심 루프 메모리 상주: 플래시 XIP 분산으로 4MB 장벽 돌파

오리지널 PC 버전 《DOOM》은 최소 4MB의 RAM 환경을 요구한다. 891KB에 불과한 장난감 하드웨어에서 이를 구동하기 위해서는 메모리 관리 체계를 밑바닥부터 뜯어고쳐야 했다. 스포드는 카메라가 사용하지 않는 버퍼와 메모리 조각을 정리해 사용 가능한 힙 공간을 약 1.4MB까지 확보했다.

그러나 끌어모은 메모리 공간은 심각한 단편화 문제를 겪고 있었다. 큰 연속 메모리 블록 할당이 번번이 실패했다. 원작 엔진은 메모리 풀링 없이 파편화된 할당을 반복했기 때문이다. 스포드는 작은 오브젝트를 위한 전용 메모리 풀을 구축하고, 맵 레벨과 오디오 리소스는 스테이지를 클리어하는 즉시 메모리에서 해제하여 메모리 부족 현상을 방지했다.

코드 바이너리의 배치 역시 까다로운 난제였다. 260KB에 달하는 실행 바이너리 전체를 RAM에 올릴 여유는 없었다. HX3302B 칩은 SPI 플래시에서 직접 코드를 실행하는 XIP 기능을 지원하지만, 측정 결과 플래시에서의 실행 속도는 내부 RAM보다 무려 18배나 느렸다.

에뮬레이터를 통한 코드 프로파일링이 해결의 실마리를 제공했다. 프로파일 데이터 분석 결과, 전체 실행 시간의 99%가 단 29KB 크기의 메인 루프에서 소모되고 있었다. 나머지 코드는 대부분 초기화나 메뉴 인터페이스 등 가끔 실행되는 루틴이었다. 스포드는 29KB의 핫 루프만 물리 RAM에 영구 상주시키고, 나머지 콜드 패스는 필요할 때 플래시 메모리에서 XIP 방식으로 호출하도록 분리했다. 이 분산 실행 구조 덕분에 메모리 제한 속에서도 풀스피드 구동이 가능해졌다.

장난감 카메라 전면 외관과 버튼 배치 사진: 브랜드 로고가 없는 X9S 장난감 카메라 외관. 출처: Spode’s Abode.

메인 루프 우회와 소프트웨어 합성기: 직접 폴링으로 달성한 30 FPS

메모리 문제를 해결하자 펌웨어 자체의 구동 방식이 성능의 발목을 잡았다. 순정 OS는 협조형 이벤트 루프를 사용했는데, 한 프레임당 이벤트 디스패치에만 38밀리초가 소요되어 프레임이 절반으로 깎였다.

스포드는 기본 이벤트 프레임워크를 완전히 걷어내고 초경량 직접 폴링 루프를 작성했다. 물리 GPIO 레지스터를 직접 읽어 방향 버튼으로 이동하고 셔터 버튼으로 사격하도록 구성했다. 전원 버튼을 짧게 누르면 무기가 바뀌고, 길게 누르면 설정 메뉴가 열리며, 벽에 몸을 부딪치면 문 열림이 판정되도록 구현했다. 불필요한 스케줄링 오버헤드를 없애자 프레임 속도는 안정적인 30 FPS까지 올라섰다.

사운드 하드웨어 역시 단일 PWM 출력 핀만 제공되어 다중 채널 재생이 불가능했다. 스포드는 소프트웨어 믹서를 직접 제작해 여러 효과음을 단일 PCM 오디오 스트림으로 합성했다.

배경음악 재생도 별도의 하드웨어 없이 소프트웨어로 해결했다. 원작 음악은 MUS 포맷으로 FM 음원 칩에 맞춰 제작되었으나 장난감 기판에는 관련 부품이 전무했다. 스포드는 CPU 점유율이 2%에 불과한 초경량 소프트웨어 파형 합성기를 개발했다. 구형파와 삼각파를 조합해 16채널 폴리포닉 멜로디를 생성함으로써, 보잘것없는 내장 스피커에서도 원작의 사운드트랙을 생생하게 재현해냈다.

SCSI 명령어 취약점: 기기 분해 없는 USB 펌웨어 덤프 경로 개척

포팅에 성공한 뒤, 개발자는 이 작업을 커뮤니티에 손쉽게 공유할 방법을 고민했다. 컴파일된 펌웨어를 직접 배포하는 것은 저작권 문제가 발생할 수 있어 기기를 뜯거나 납땜하지 않고도 펌웨어를 덤프할 수 있는 도구가 필요했다.

이때 카메라의 USB 대용량 저장소 모드에서 치명적인 설계 결함이 발견되었다. 일반 저장 장치로 연결되었을 때 컨트롤러가 문서화되지 않은 벤더 전용 SCSI 명령어에 응답하는 현상이 확인된 것이다. PC에서 특정 제어 패킷을 보내면 칩셋이 지정된 RAM 주소로 직접 점프해 코드를 실행하도록 명령할 수 있었다. 스포드는 이 원리를 이용해 메모리 탐색 페이로드를 작성했다. 호스트 PC가 SCSI 프로토콜로 마이크로코드를 RAM에 주입하면, 칩셋이 대신 4MB 플래시 메모리를 읽어 USB 케이블을 통해 PC로 전송했다.

이제 일반 사용자도 USB 케이블 하나만 연결하면 몇 초 만에 기기 손상 없이 펌웨어를 백업할 수 있다. 범용 레퍼런스 솔루션이 인터페이스에 남겨둔 디버깅 통로가 기기의 허술한 방어선을 완벽하게 무너뜨린 셈이다.

1만 원대 초저가 소비재 하드웨어는 극단적인 원가 절감과 빠른 납기로 움직인다. 몇 센트의 부품비와 며칠의 일정을 아끼기 위해 시장에 쏟아지는 범용 하드웨어들은 불필요하게 넉넉한 연산 능력을 품고 있으면서도 보안에는 무방비하다. 공장을 떠나 시중에 유통되는 순간, 허술한 하드웨어는 제조사의 통제를 벗어난다. 해커 커뮤니티의 이번 성과는 세상의 무관심 속에 잊힌 노브랜드 전자기기라도 리버스 엔지니어링을 거치면 얼마든지 매력적인 오픈 플랫폼으로 거듭날 수 있음을 명쾌하게 증명한다.

참고 링크:

  • Hackaday 특집 기사
  • Spode’s Abode 리버스 엔지니어링 블로그
  • Sprite_tm 장난감 카메라 펌웨어 분석