
iOS 앱의 커스텀 base64 인코딩을 리버스 엔지니어링하여 BLE를 통해 D-Link Komfy 스마트 스위치에서 Wi-Fi SSID/비밀번호를 추출하는 방법을 보여주는 개념 증명(PoC) 및 라이트업
소개
이 라이트업은 D-Link의 Komfy 스위치 카메라에서 블루투스 4.0(BLE)을 통해 기기에 연결된 Wi-Fi SSID와 비밀번호를 탈취하는 방법에 대한 제 연구 결과를 자세히 설명합니다. Komfy 스위치는 홈 보안 및 자동화 제품으로, 집 안의 벽 스위치를 교체하여 영상 감시, 온도·습도·공기 질 모니터링, 조명 스위치 원격 제어 기능을 제공합니다.
블루투스 BLE 프로파일링
더 깊이 파고들기 전에 LightBlue iOS 앱으로 BLE 장치를 빠르게 프로파일링했습니다. 이 시점에서 Komfy 장치는 온라인 상태였고 일반적인 사용 사례 설정으로 구성되어 있었습니다. LightBlue로 Komfy에 연결했을 때, 8개의 커스텀 특성(또는 기능)을 드러내는 비표준 GATT 서비스를 발견했습니다. 그러한 특성 중 몇 개는 BLE 사양상 최대 20바이트임에도 비정상적인 양의 데이터를 수신하고 있었습니다. 주변 장치와 중앙 장치가 모두 지원한다면 더 높은 MTU를 협상하여 일반적으로 "롱" 읽기/쓰기라고 부르는 것을 지원할 수 있습니다. 아래 첫 번째 스크린샷은 GATT 서비스와 특성(0xB002 ~ 0xB00A로 시작)을 보여줍니다. 다음 두 스크린샷은 이 라이트업에서 중점적으로 다룰 두 특성(0xB006 및 0xB007)을 보여줍니다. 0xB006 및 0xB007 특성은 Wi-Fi SSID와 ascii로 디코딩했을 때 base64로 인코딩된 문자열처럼 보이는 값을 표시했습니다. 그러나 마지막 스크린샷에서 볼 수 있듯이 문자열을 base64 디코딩해도 읽을 수 있는 데이터는 드러나지 않았습니다.
Komfy 앱: 메서드 호출 추적
Komfy 장치에 구현된 GATT 특성을 더 잘 이해하기 위해 class-dump-z를 사용하여 Komfy iOS 앱의 메서드를 덤프하고 관심 있는 메서드에 대한 메서드 추적을 설정했습니다. 전체 클래스 덤프는 여기에서 참조할 수 있습니다. 저는 특히 BLEDevice 클래스와 블루투스를 참조하는 다른 메서드들에 관심이 있었습니다. 메서드 추적은 Prateek이 여기에서 자세히 설명한 Logify.pl perl 스크립트를 사용하여 설정할 수 있습니다.
위 스크린샷은 Komfy를 새로 설치하고 구성하는 동안의 메서드 추적 출력을 보여줍니다. Wi-Fi 비밀번호 "chipotlemakesmehappy"가 평문으로 표시되고, 앞서 LightBlue 앱이 0xB007 GATT 특성에서 검색한 그 base64처럼 보이는 문자열이 다시 나타나는 것을 주목하세요. 추적 결과 실제로 +[Base64 encode:] 메서드 호출이 표시되었는데, 표준 라이브러리를 사용하여 base64 디코딩할 수 없었기 때문에 처음에는 혼란을 주었습니다. base64 디코딩된 값이 암호화되었거나 추가 인코딩되었다고 거의 단정 지을 뻔했지만, +[Base64 encode:]가 (NSData 클래스가 아닌) 개인적으로 구현된 메서드라는 것을 깨닫게 되었습니다. 이 특이한 인코딩 방식을 해결해야 했습니다.
Hopper를 이용한 디스어셈블리
이제 D-Link가 구현한 "base64" 인코딩 방식을 리버스 엔지니어링할 차례입니다 ("리버스 엔지니어링"이라고 하면 최종 결과를 고려할 때 실제보다 훨씬 어려워 보이지만요). Hopper에서 Komfy 앱을 로드하고 -[BLEDevice getWifiPassword:] 및 +[Base64 decode:] 메서드를 분석하는 것이 명백한 시작점이었습니다. -[BLEDevice getWifiPassword:]를 분석한 결과 0xB007 GATT 특성이 실제로 Wi-Fi 비밀번호를 검색하고 있음이 확인되었습니다.
+[Base64 decode:]의 ARM 어셈블리를 살펴보면 표준 NSData 클래스 구현과 매우 유사해 보여서 +[Base64 encode:]를 훑어보기 위해 이동했습니다. Hopper는 곧바로 답을 알려주었습니다. 어셈블리 명령어 중 하나 근처에 표준 base64 알파벳의 모든 문자를 포함하지만 완전히 순서가 뒤섞인 문자열 상수가 출력되었습니다. 원래 시저 암호보다 어렵지 않은 사소한 치환을 생각하지 못한 것에 약간 부끄러워하며, base64 문자를 푸는 스크립트를 작성했고 짜잔! "chipotlemakesmehappy"가 화면에 출력되었습니다.
즉, 기본적으로 문자열을 푸는 방법과 base64 디코딩 방법은 다음과 같습니다:

전체 자동 공격(autopwn) 스크립트는 여기에 있습니다.
그리고, 그렇습니다. Chipotle은 정말로 저를 행복하게 만듭니다.
Ubertooth BLE 캡처는 여기에서 다운로드할 수 있습니다.