2P by GN⁺ | ★ favorite | 댓글 1개
  • 저가 Bluetooth LE LED 조명을 Home Assistant에 붙이려는 역공학 과정에서, 10M 주소 지정 가능 LED 스트링의 숨겨진 효과 값을 시험하다 컨트롤러가 동작하지 않게 됨
  • Android의 Bluetooth HCI snoop과 Wireshark/tshark로 앱이 조명에 쓰는 BLE 패킷을 캡처하고, btatt.opcode.method==0x12 쓰기 요청에서 제어 바이트를 추적함
  • iDeal LED 앱의 패킷은 단순한 on/off 값처럼 보이지 않았고, APK 디컴파일과 기존 분석 글을 거쳐 libAES.so 안의 고정 AES 키로 복호화함
  • 복호화된 on/off 패킷은 고정 헤더와 5번째 바이트의 1/0 차이로 정리됐고, 색상·밝기·효과 기능을 반복 실행해 바이트 패턴을 기록함
  • RGB에 앱이 쓰는 5비트 범위 0x1F를 넘어 8비트 값을 보내자 더 밝은 색상이 가능했지만, 효과 번호 12를 보내는 순간 조명이 꺼지고 Bluetooth 광고도 사라짐

저가 BLE 조명을 홈 자동화에 붙이는 출발점

  • Bluetooth LE로 통신하고 전용 앱이 있는 기기는 홈 자동화 시스템에 통합할 수 있다는 전제에서 여러 저가 LED 스트립을 역공학함
  • 이전에는 £2.38짜리 Bluetooth LE 제어 5M 비주소 지정 LED 스트립을 몇 시간 만에 Home Assistant에 연결했고, 관련 코드는 bj_led에 공개됨
  • LEDnetWF 컨트롤러의 BLE 역공학 작업도 lednetwf_ble에 있음
  • 이번 대상은 책상 위에 있던 10M 주소 지정 가능 LED 스트링으로, “iDeal LED” 앱으로 제어됨
    • 앱은 기능이 많고 비교적 잘 동작함
    • LED는 WS2812 또는 유사 제품일 가능성이 있음
    • 제품은 AliExpress에서 구매한 조명임

앱이 보내는 BLE 바이트 캡처

  • 자체 소프트웨어로 기기를 제어하려면 앱이 Bluetooth로 기기에 보내는 바이트열을 먼저 확인해야 함
  • 일반적인 조명 프로토콜은 헤더, on/off나 색상 변경 같은 명령 바이트, 체크섬일 수 있는 푸터로 구성될 수 있음
  • Android에서는 다음 순서로 캡처함
    • 개발자 모드를 켬
    • 조명 앱을 설치함
    • 개발자 설정에서 Bluetooth HCI snoop을 활성화함
    • 앱에서 조명을 켜고 끄는 등 동작을 수행함
    • adb pull sdcard/btsnoop_hci.log .로 로그를 컴퓨터에 복사함
  • Wireshark에서 로그를 열면 조명으로 전송된 바이트를 볼 수 있음
    • 필터 예시는 bluetooth.dst == ff:ff:ff:ff:ff:ff && btatt.opcode.method==0x12
    • MAC 주소는 실제 조명의 MAC으로 바꿔야 함
    • btatt.opcode.method==0x12는 Android 기기에서 조명으로 쓰기 작업이 발생했음을 뜻함
  • tshark를 쓰면 패킷 값을 터미널에서 바로 뽑을 수 있음
    • tshark -r <filename> -T fields -e btatt.value는 LED 컨트롤러에 쓰인 페이로드를 출력함

단순 리플레이로는 부족했던 iDeal LED 프로토콜

  • 일부 조명은 on/off 동작에서 거의 그대로 읽히는 패턴을 보임
    • 예시는 69 96 02 01 0169 96 02 01 00이 반복되는 형태임
    • 마지막 바이트가 10으로 바뀌며 켜기/끄기를 나타냄
  • 이번 iDeal LED 조명은 훨씬 긴 바이트열이 반복됐고, on/off에 해당하는 두 종류의 패킷은 구분되지만 값이 노이즈처럼 보였음
  • 단순히 켜고 끄는 목적이면 캡처한 바이트열을 그대로 재전송하는 리플레이로 충분할 수 있음
    • gatttool로 BLE 기기에 연결해 바이트를 보낼 수 있음
    • 전송할 핸들은 Wireshark에서 확인해야 함
  • 더 많은 제어를 하려면 패킷 구조를 이해해야 했고, Android 앱 자체를 분석하는 단계로 넘어감

APK 디컴파일과 AES 키 찾기

  • APK를 내려받아 jadx로 열고 앱 코드를 확인함
  • 소스 안에서 AES 참조가 보여 프로토콜이 암호화됐을 가능성이 생김
  • 암호화된 데이터에 대해 다음 조건을 가정함
    • 같은 동작의 암호문이 매번 바뀌지 않아 일관된 키가 있을 수 있음
    • 저전력 MCU에서 빠르게 복호화해야 하므로 짧은 키가 유리함
    • 키가 기기마다 고유하지 않고 고정 키일 수 있음
  • 앱에는 libAES.so라는 컴파일된 AES 라이브러리가 들어 있었고, jadx만으로는 분석할 수 없었음
  • 다른 사람이 ida free로 AES 라이브러리를 디컴파일해 내장 키를 찾은 분석 글을 발견했고, 그 키를 시험함
  • Crypto.Cipher의 AES ECB 모드로 복호화하자 on/off 패킷이 의미 있는 형태로 바뀜
    • 복호화된 값은 05 54 55 52 4E 01 ...05 54 55 52 4E 00 ...처럼 나타남
    • 고정 헤더 뒤 5번째 바이트가 1 또는 0으로 바뀌며 on/off를 나타냄
    • 나머지는 0으로 채워짐
  • 이 단계부터 앱이 보내는 패킷을 복호화하고, 자체 코드에서 같은 제어를 재현할 수 있게 됨

기능별 바이트 패턴 기록

  • 앱의 모든 기능을 하나씩 실행하며 전송 바이트를 기록하는 방식으로 프로토콜 범위를 넓힘
  • 각 동작은 여러 번 반복하고, 섹션 구분을 위해 조명을 껐다 켜는 패턴을 끼워 넣음
    • 색상을 red, green, blue 순서로 여러 번 바꿈
    • 밝기를 100%, 50%, 10%, 50%, 100%로 바꿈
    • 각 묶음 사이에 off/on을 넣어 캡처 로그에서 경계를 찾기 쉽게 함
  • 이 방식으로 동작에 따라 어떤 바이트가 바뀌는지 확인하고, 기록한 동작과 캡처된 패킷을 맞출 수 있음

컨트롤러를 벽돌로 만든 효과 번호 12

  • 색상 변경을 조사하던 중 앱이 red, green, blue 값에 0x1F보다 큰 값을 보내지 않는 것을 확인함
    • 0x1F는 5비트 범위임
    • 8비트 값을 직접 보내자 더 밝은 색상이 동작함
  • 앱이 쓰는 10개 효과 외에 추가 효과가 있는지 확인하려고 range(20) 루프를 돌려 효과 번호를 순서대로 보냄
    • 1부터 10까지는 정상적으로 진행됨
    • 11에서 숨겨진 모드처럼 보이는 동작을 발견함
    • 12로 넘어가자 조명이 꺼짐
  • 이후 조명은 다시 켜지지 않음
    • Bluetooth 광고를 더 이상 하지 않음
    • 연결도 되지 않음
    • 전원을 켤 때 버튼을 누르고 있어도 복구되지 않음
    • 밤새 전원을 뽑아 둬도 돌아오지 않음
  • 버퍼 오버플로로 펌웨어가 손상됐을 가능성을 추정했지만, 원인은 확정되지 않음
  • LED 자체는 표준 주소 지정 가능 LED라서 다른 마이크로컨트롤러에 연결해 스트링을 재사용할 수 있음

남은 결과물과 주의점

  • 실패에도 불구하고 프로토콜 대부분을 문서화했고, Home Assistant 커스텀 컴포넌트가 포함된 GitHub 프로젝트를 만들었음
  • 컴포넌트는 동작하지만, 같은 방식의 실험은 조명 컨트롤러를 고장 낼 수 있으므로 각자 책임하에 진행해야 함

댓글과 토론

Hacker News 의견들
  • FTA의 “고정 헤더”라기보다는 길이 바이트(“명령은 5바이트”), 명령어 TURN, 인자 0/1이 있고, 나머지를 16바이트까지 0으로 채운 형태로 보임

    • 54 55 52 4E는 대문자 알파벳 TURN으로 바로 눈에 띔
      숫자는 0x30, 대문자는 0x41, 소문자는 0x61에서 시작한다는 걸 알면 16진수 덤프에서 영숫자 패턴을 찾기 쉬움
      짧은 문자열에는 이런 지식이 유용하지만, 패킷이나 메모리 덤프를 볼 때는 표준 hexdump 형식이 가장 좋음
    • 잘 짚었음. 0x54 55 52 4E는 실제로 T U R N
    • 좋은 발견임. 다른 명령도 확인해서 길이 바이트 가설이 맞는지 보겠고, 가능성 있어 보임
    • 패딩이 아니라 그냥 uint일 가능성이 큼
    • 이 경우에는 길이와 시작 지점 기준으로 헤더가 고정된 셈임
  • 전원 공급 문제일 수 있음. WS281x 계열은 아주 밝게 켤 수 있고, 여러 개를 묶으면 전류를 엄청 먹음
    100개짜리 스트립에 12V 3A 전원공급장치면 전체를 최대 밝기 흰색으로 겨우 켤 정도이고 매우 눈부심
    그래서 끊어진 퓨즈를 먼저 볼 것 같음. 펌웨어가 최대 밝기 255 중 31까지만 쓰는 것도 단서가 됨

    • 밝기가 0x1f로 제한된 걸 보고 나도 처음엔 그렇게 생각했음. 운이 좋으면 전원공급장치에 퓨즈가 있고, 퓨즈만 나갔을 수도 있음
      못 살리더라도 표준 WS281x LED 문자열은 Raspberry Pi에 연결할 수 있고, 내 오픈소스 주소 지정 LED 컨트롤러도 쓸 수 있음 :) https://github.com/mbevand/ledthemfight
      내장 효과가 있고, DIY용으로 매우 모듈식으로 만들어서 Python 두 줄이면 간단한 커스텀 LED 효과 모듈을 만들 수 있음. 데모는 여기: https://youtu.be/qpd2rILsnM4
    • 좋은 생각임. 멀티미터를 꺼내보겠음
    • 이건 WS2812처럼 보이지 않음. 올린 Ali 링크를 보면 스트립에 12V, 빨강, 초록, 파랑 네 가닥 선이 있음
      개별 주소 지정이 아니라 스트립 전체가 같은 색으로 켜지는 아날로그 RGB 스트립 같음
      https://www.aliexpress.com/item/1005005485885067.html
      LED 조명을 뭔가 만져보려는 사람은 WLED를 꼭 봐야 함. 내장 효과가 많고, 웹 GUI가 있고, 아주 싼 ESP32나 ESP8266을 컨트롤러로 쓰며, 소리 반응도 가능함. 지금 실내 크리스마스 조명에 WLED를 돌리고 있는데 아주 좋아 보임
    • 팁 고마움. 코드를 오른쪽으로 3비트 시프트해서 다시 5비트 숫자로 돌아가게 업데이트했음
      전력 사용량을 제한하는 깔끔한 방법임
  • 좋은 글임. 갖고 있는 조명을 역공학하려다가 암호화돼 있다는 걸 알게 된 기억이 남
    하나는 amaran 60d이고 나머지는 SmallRig RM75 배터리 LED 조명 몇 개였는데, 앱 두 개를 따로 만지지 않고 한 스크립트로 모두 켜고 끄고 싶었음
    앱과 프로토콜을 역공학하는 데 시간을 꽤 썼고, 두 조명 모두 같은 협상 절차를 쓰지만 서로 다른 라이브러리로 구현한 것 같았음
    연결 시 수행하는 Diffie-Hellman 키 교환을 흉내 내려 했지만 결국 포기했음. 기억상 그 뒤에 한두 단계가 더 있었고, 첫 키를 보낸 뒤 또 무작위처럼 보이는 숫자(또 다른 키?)를 보내는데 그게 뭘 원하는지 알아내지 못했음
    이 글을 보니 그냥 하드코딩된 키를 넣어보고 동작하는지 확인해봐야겠다는 생각이 듦

    • Amaran 조명에서 성공하면 정말 좋겠음. 그러면 아마 Aputure 제품군 전체도 역공학으로 이어질 수 있을 듯함
      Elgato Stream Deck이나 Home Assistant용 오픈소스 연동이 생기면 큰 성공 사례가 될 것 같음. 책상에서 토킹헤드 영상을 찍는 YouTube 쪽 사람들에게는 휴대폰 앱으로 조명을 제어하는 것보다 훨씬 나을 것임
  • BLE 연결 크리스마스 조명을 자동화하려다 전자폐기물을 만들었음. 이제 당신도 할 수 있음

    • 어떻게 했는지는 모르겠지만, 이런 SmartTrash 중 일부는 빠르게 5번 껐다 켜는 식의 마법 같은 순서로 하드 리셋되는 걸 봤음
    • BLE 패킷 스니핑을 더 GUI 중심으로 하고 싶다면 nRF Connect 앱을 써보면 됨
      iPhone은 잘 모르겠지만 Android에서는 백그라운드에 두면 휴대폰의 깔끔한 GUI에서 BLE 활동을 잡을 수 있음. 매일 쓰고 있음
    • 컨트롤러를 우회하면 여전히 더미/클래식 조명으로 쓸 수 있음
  • 특정 조명 명령을 받으면 벽돌이 되던 키보드 MCU들이 떠오름
    OpenRGB는 결국 해당 하드웨어에서 그 모듈이 자동 실행되지 않도록 비활성화해야 했음. 가끔은 제조사 소프트웨어도 같은 버그를 유발했음
    안타깝게도 보통 시스템 내 프로그래밍 모드로 들어가려면 USB HID 리포트를 보내야 했는데, 영향을 받은 장치들은 더 이상 열거조차 되지 않았음
    실제로 펌웨어 손상인지, 아니면 다른 정의되지 않은 동작 때문에 하드웨어가 망가진 것인지는 별개임

  • “무선으로 평문을 보내면 안전하지 않잖아”
    “걱정 마, AES 암호화를 넣었어”

    • Tuya는 이 점에서 정말 웃김. 프로토콜은 그냥 TCP 위의 TLS인데, 앱은 새 장치를 추가할 때마다 주변 모든 STA에 Wi-Fi 비밀번호를 마구 뿌림
      페어링 방식이 그렇기 때문임. 앱이 255.255.255.255로 패킷을 무작정 브로드캐스트하고, 대상 장치(전구, 콘센트 등)는 무차별 모드로 대기함
      패킷 내용은 WPA2 등으로 보호되지만 패킷 길이는 보호되지 않아서, 설정 핸드셰이크의 다음 문자의 ASCII 바이트값을 각 패킷 길이로 설정한 아주 작은 패킷을 엄청 많이 보냄. 아마 여러 번 반복해서 보낼 것임
      그래서 페어링이 2분 걸리다가 카운터가 0에 도달하기 전에 항상 갑자기 멈춤
    • 공기를 상대로 한 암호화인 듯함
  • 작년에 내 벽난로 BLE 컨트롤러를 역공학할 때 정말 걱정했던 게 이거였음
    특히 “Set password” 명령은 원시 바이트 입력을 받는데, OEM 앱은 길이 제한된 숫자 데이터만 보냈기 때문임
    다행히 잠깐 전원이 끊기면 이전에 있었던 일을 전부 잊어버리는 것 같았음
    그래서 같은 브랜드의 BLE 컨트롤러 대부분이 기본 비밀번호 0000 그대로 남아 있는 듯함. 정전이 한 번 나면 결국 그 상태로 돌아감. 정말 심심하다면 BLE 워드라이빙 소재로 꽤 괜찮을 것임
    나도 역공학 결과를 Home Assistant 연동으로 만들었고(https://github.com/kaechele/napoleon-efire), 시스템과 프로토콜 문서도 작성했음(https://bonaparte.readthedocs.io/en/latest/index.html)

  • 자동차 루프랙에 달 유연하고 튼튼한 조명을 찾고 있음
    배터리 전원이고 실외/전천후에 맞아야 하며, 배터리 박스를 케이블타이로 표면에 쉽게 붙일 수 있으면 좋겠음
    가능하면 “미니” 폼팩터인 T5였으면 하고, RGB에 프로그래밍 가능해서 크리스마스에는 빨강/초록, 핼러윈에는 보라/주황 등 계절별로 쓰고 싶음
    이 조건에 맞는 제품을 아는 사람이 있는지 궁금함. 앞의 세 조건은 Walmart나 Home Depot에서 구할 수 있는데, 마지막 조건을 만족하는 걸 찾기 어려웠음
    검색하면 잡음만 잔뜩 나옴
    [1] https://cdn.christmaslightsetc.com/images/CategoryDetail/788...

    • 얼마나 DIY할 의향이 있는지에 따라 방향이 달라질 것 같음
      예를 들어 12V LED 스트립 중 IP67 방수(실리콘 튜브 안에 들어간 형태)는 쉽게 구할 수 있고 [0], 크리스마스 조명 같은 문자열보다 LED 수가 훨씬 많아서 효과도 더 강할 것임
      다만 Arduino, ESP32, ESP8266 같은 마이크로컨트롤러를 사서 프로그래밍하고, 자동차 배터리에서 전원을 어떻게 끌어올지 직접 해결해야 함 [1]
      전자부품은 차 안에 넣고 트렁크 밖으로 선만 빼면 기존 트렁크 씰로 방수를 기대할 수도 있음
      [0] https://www.aliexpress.com/item/1005004289391906.html
      [1] https://www.aliexpress.com/item/1005005977505151.html
    • “bullet string” 스타일 WS2811을 봐도 됨. 차의 12V에 연결할 거라면 12V 네이티브이고, 보통 xConnect 피그테일이 달린 방수 제품으로 나오며, 붙이기 쉽고 유연함
      연장선으로 다시 납땜하거나 체인으로 잇기도 쉬움
      https://www.aliexpress.com/item/4000105913323.html
      읽어본 바로는 이런 제품이나 비슷한 5V 조명이 야외 크리스마스 조명 쇼에서 표준처럼 쓰이는 듯함
    • WLED Discord에 들어가서 #projects#showcase 채널을 보면 됨. 차량에 RGB LED 조명을 장착한 프로젝트가 많음
      다만 이쪽은 쉽게 빠져들 수 있으니 조심해야 함
      초대 링크: https://discord.gg/eVhhh2Wh
  • 고장 난 크리스마스 조명을 분해한 모습을 볼 수 있을까?
    안에 어떤 칩이 있는지 알면 플래시 메모리가 있는지, 덤프하기 쉬운지 단서가 될 수 있음