1.개요
공유기 익스를 해보면서 삽질했던 과정을 정리하고자 한다. 정리를 안하면 다 까먹...
공유기 몇대를 익스하면서 가장 어려웠던 점은 취약점 찾는게 아닌 펌웨어 추출이였다. 하드웨어 지식이 부족한 터라 플래시메모리가 뭔지, UART가 뭔지 도통 모르는게 한두개가 아니였다. 펌웨어를 따서 파일 시스템을 추출해야 취약점을 찾든가 말든가하는데 앞에서 막혀버리면 암울 그자체다. 따라서 지금까지 시도하고 분석했던 펌웨어 추출 방법을 정리해보고자 한다.
2. 펌웨어 추출 방법
우선 공유기나 IoT 장비를 구매한뒤 드라이버로 한땀 한땀 나사를 다 제거한 뒤에 PCB 기판을 뜯는 것부터 시작된다. 보드가 큰 것도 있고 IP 카메라 같이 매우 작은 놈들도 있다.
•
IoT 장비를 여러대 분석하다보면 어디가 UART고 어디가 Flash Memory인지 대충 감이 온다.
•
일반적으로 UART 포트는 제거되어있는 경우가 대부분이므로 우선적으로 GND, RX, TX, VCC 핀을 식별하여 핀 헤더를 납땜하는게 편하다.
2.1 UART 이용
•
보드에서 VCC, RX, TX, GND 핀을 각각 식별해야한다. 식별하는 방법은 보편적으로 멀티테스터기를 이용하거나 로직 분석기를 이용한다.
•
UART 핀은 총 4개의 핀을 사용한다.
- TX : 데이터 송신
- RX : 데이터 수신
- GND : 그라운드
- VCC : 전압
•
TX와 RX는 항상 반대이다. 공유기 UART의 TX는 공유기에서 데이터 송신이므로 실제 PC에서의 RX와 연결시켜야 한다.
•
공유기의 RX는 공유기에서 데이터를 수신하므로 실제 PC에서 TX와 연결시켜야 한다.
•
위 그림과 같이 UST to TTL 장비를 이용해서 공유기의 UART와 PC를 연결할 수 있다.
•
우측 사진 처럼 PC와 공유기 UART를 연결한다음, baud rate를 맞춘뒤 putty나 xshell로 시리얼 모니터를 확인하면 된다.
•
baud rate를 잘 맞춰주면 위 그림과 같이 부팅로그가 나온다. 여기서 크게 3가지로 나뉜다.
1. 특정 키를 입력하면 바로 쉘이 떨어진다. (요즘은 거의 X)
2. 부트 쉘에 접속하여 펌웨어 덤프
3. 글리칭을 통해 부트 쉘 접속 후 2번 항목 시도
2.2 Flashrom 프로그램 이용
•
8핀 짜리 Flash memory는 위 그림과 같은 장비를 이용해서 다리에 후크를 걸고 flashrom 프로그램을 이용하여 덤프를 뜰 수 있다.
•
flashrom은 flash memory를 쉽게 읽을 수 있게 도와주는 프로그램으로 라즈베리파이에 설치하여 바로 사용 가능하다.
flashrom 지원 가능한 칩일 경우
•
flash memory chip을 자세히 보면 위에 모델명이 적혀있다. 해당 모델의 datasheet를 검색하여 핀맵을 확인한 뒤 라즈베리파이 연결하여 flashrom을 이용하면 된다.
Flash memory pin map
라파 - Flash memory 매핑
•
데이터 시트를 검색하여 핀 맵을 확인한 뒤, 라파의 SPI 핀과 매핑하여 다음 명령어를 실행시키면 된다.
$ sudo flashrom -r [생성할 이름] -p linux_spi:dev=/dev/spidev0.0 , spispeed=8000
Bash
복사
flashrom에서 지원하는 칩이 아닌 경우
•
flashchips.h 코드를 보면 flashrom에서 지원 가능한 모델 명을 확인할 수 있다.
•
만약 추출하려는 칩이 flashrom에서 지원하지 않는 경우도 있다. 그런 경우 datasheet를 분석하여 필요한 정보를 획득한 후 flashchips.c 파일에 다음 형태로 코드 추가 후 빌드를 다시 하면 된다.
•
2.3 spi 통신 코드이용
만약 flashrom을 이용한 펌웨어 덤프가 실패한 경우, spi 통신을 이용하여 직접 플래시메모리에서 데이터를 읽어오는 방법을 시도할 수 있다. 해당 방법의 경우 직접 대상 플래시메모리의 데이터 시트를 분석하여 코드를 짜야한다.
•
데이터 시트를 잘 보면 특정 명령에 따른 opcode를 확인 할 수 있다. Read Data 의 경우 Opcode는 3이며 제조사 ID를 읽는 Opcode는 0x9F이다.
•
예를 들어 제조사 ID를 읽고 싶으면 0x9F 클럭 주기에 맞춰 Opcode 한바이트와 더미 값 2바이트 총 3바이트를 보내면 된다.
•
그렇게 되면 Data Output 라인으로 한바이트의 제조사 ID를 읽을 수 있다.(뒤에 디바이스 ID 2바이트도 딸려온다는 것을 확인할 수 있다.)
import sys
from spidev import SpiDev
...
def probe(self):
try:
data = self.__spi.xfer([0x9f, 0, 0, 0])
return data[1], data[2] << 8 | data[3]
Python
복사
•
데이터 시트를 통해 필요한 정보를 어느정도 파악했다면 파이썬을 이용하여 spi 통신을 구현할 수 있다.
•
위 코드는 플래시메모리의 제조사 ID와 디바이스 ID를 읽어오는 코드이다. spidev 모듈을 사용하였으며 spi.xfer 함수를 이용하여 spi 통신 구현을 할 수 있다.
•
xfer을 통해 0x9f와 한바이트의 더미값을 보낸 후 그 결과 값을 data 변수에 담는다.
•
정상적으로 0x9F Opcode가 전송되면 data[1]에 제조사 ID, data[2]-data[3]에 디바이스 ID가 담긴다.
•
이런식으로 데이터 시트를 분석하여 Spi 통신을 이용하여 read하는 코드를 구현하면 된다.
•
2.4 Rom Writer 사용
만약 위 방법이 다 실패하거나 혹은 해당 장비를 가지고 있을 경우 쉽게 펌웨어를 추출 할 수 있다.
Rom Writer는 플래시메모리를 쉽게 읽거나 쓰거나 수정할 수 있는 장비로 저가부터 고가까지 다양한 금액대가 존재한다.
•
롬라이터로 가장 유명한 Beeprog가 있다.
•
해당 장비는 대략 100만원 ~ 150만원 정도 하며 비싼 장비인 만큼 지원하는 모델이 많다는 장점이 있다. 하지만 8핀이냐 onboard 형식이냐 혹은 크기에 따라 각각에 맞는 소켓을 추가적으로 구매해서 사용해야 한다.
•
저가형 롬라이터로 xgecu 가 있다.
•
가격은 대략 10만원 안팍이며 해당 장비 역시 추가적인 소켓이 필요하다.
내가 사용해본 롬라이터는 위 두개이다. 이 외에도 찾아보면 다양한 종류의 롬라이터가 존재한다. 롬라이터를 이용하면 해당 장비에서 지원하는 소프트웨어를 설치하여 read하면 끝이다. 예를 들어 beeprog를 이용하는 경우 다음과 같다.
•
사이즈에 맞는 소켓을 구매하여 플래시 메모리를 디솔더링하여 뽑아낸다.
•
뽑아낸 칩을 소켓에 넣은 후 beeprog와 연결한다.
•
beeprog와 pc와 연결한 뒤 beeprog 프로그램을 연다.
•
메뉴얼 대로 실행하여 플래시메모리 read를 한다.
•
정상적으로 read가 되면 위 사진과 같이 플래시 메모리 정보가 읽힌다.
•
해당 내용을 저장하여 파일 시스템 추출을 진행하면 된다.
•
beeprog에서 read 기능을 바로 사용하여 되는 경우도 있고 몇가지 설정을 변경해야지 되는 경우도 있기 때문에 주의해서 사용해야 한다.
3. 결론
여태 공유기나 IoT 장비를 타겟으로 버그바운티를 진행하면서 펌웨어를 추출하기까지의 과정을 정리해봤다. 하드웨어 지식이 부족해서 처음에 막혔던 부분도 많았으나 하나씩 공부해가면서 분석하니까 그 나름대로 재미가 있었다.
여태 펌웨어 추출은 위 설명했던 방식으로 전부 성공하였다. 후에 또 새롭게 알게되는 방법이 있으면 추가적인 정리를 할 예정이다.