UART 에 대해 간단히 알아보았으므로 다음은 SWD 포트를 이용한 완전한 동적 디버깅을 실습해보겠다.
재미있는 예제를 위해 Login 과정을 직접 만들어서 보드에 올리고 gdb 를 통해 인증을 우회하는 방법을 실습해보려한다.
가장 유명하고 실제로 자주 사용되는 ST사의 STM32F103C8T6 (Black Pill) 보드를 대상으로 한다.
인증과정을 직접 만들어보아야 원리를 더 잘 알수있는 것이기때문에 실제와 가깝게 해보기위해 IDE 를 사용하였다.
(개발과정은 아두이노IDE 에 STM32보드 를 추가 하는방법도 있으니 아두이노 IDE 가 편하다면 그 방법으로 하여도 된다.)
실습을 요약해보면 다음과 같은 구조로 진행된다.
준비물
- STM32F103C8T6 (BLACK PILL) 개발보드, bread board
- ST-LINK V2 (STM32보드의 SWD포트 연결)
- FT232RL 호환 USB-TO-TTL
- PC에 STM32CubeIDE, OpenOCD, gdbmultiarch 설치
- 지식 : STM32CubeIDE 기본적인 사용법
기본 연결 구조
- 입출력 (UART) : STM32 보드의 SWD <-> FT232RL <-> PC usb허브
- 디버깅 (SWD) : STM32 보드의 SWD <-> ST-LINK V2 <-> PC usb허브 -> OpenOCD (on-chip-debugger), GDBmultiarch
- LOGIN 인증 프로그래밍 : STM32CUBEIDE ( Arduino 로 하는 방법도 가능 )
과정
- 개발의 과정) STM32CubeIDE 로 Login 구현하기
- 해킹의 과정) OpenOCD 설치, 펌웨어 다운로드, gdb 로 로그인 우회
먼저 UART 입출력을 위한 FT232RL과 디버깅지원을 위한 ST사의 ST-LINK 를 연결하였다.
SWD의 핀은 (3.3V GND IO CLK) 4가지를 각각 같은곳으로 연결하면 되므로 어렵지않다.
다음 STM32CubeIDE 를 설치하고 그림과 같이 핀을 세팅한다. 코딩을 하는 부분 외에 칩셋을 세팅하는 화면을 Device Control Tool 이라고 하는데, 나는 아래 목록을 세팅하였다. 이부분은 개발과정에 해당되므로 자세한 사항은 유투브나 다른블로그를 참조하면 좋을것이다.
- Pinout View 에서 PB12 -> GPIO_OUTPUT ( LED 점등을 위한 핀 )
- RCC 에서 HSE -> Crystal/Ceramic ... ( 클럭을 위한것, 옵션 )
- SYS 에서 Debug -> Serial Wire ( 디버깅 지원을 위해 필수 )
- USART1 에서 Mode -> Asynchronous ( UART 를 위한 필수, Flow Control 은 하지않음 )
- Project Manager 에서 Generate peripheral initialization 체크 ( 소스코드를 위한것, 옵션 )
저장하면 MX_GPIO_Init(); MX_USART1_UART_Init(); 와 같은 초기화 코드들이 자동으로 추가되고 프로그래밍을 하기위한 준비가 될것이다. main.c 내부에 while 구문을 다음과 같이 프로그래밍 하였다.
UART 통신을 위한 함수는 HAL_UART_Transmit / HAL_UART_Receive 이고
LED 점등을 위한 함수는 HAL_GPIO_TogglePin 이다.
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
uint8_t rc = 0;
static uint8_t i = 0;
// 처음 실행할 경우 Login 메세지 출력.
if (login_msg == 1) {
HAL_UART_Transmit(&huart1, (uint8_t*)"\rLogin : ", 9, 1000);
login_msg = 0;
}
// UART 포트로 한문자씩 RX 전송받아 TX 로 출력하며 LED 를 깜빡인다.
if(HAL_UART_Receive(&huart1, (uint8_t *)&rc, 1, 1000)==HAL_OK) {
HAL_UART_Transmit(&huart1, (uint8_t *)&rc, 1, 1000);
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(100);
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}
// 전송한 문자열에 리턴값을 포함할때까지 버퍼에 문자열을 저장한다.
// 리턴값이 들어오면 널문자를 추가하고 문자열을 패스워드와 비교한다.
if (rc != 0) {
if(rc != '\r' && rc != '\n') {
buf_passwd[i++] = rc;
if(i >= 32) i = 32 - 1;
}
else {
HAL_UART_Transmit(&huart1, (uint8_t *)"\n", 1, 1000);
buf_passwd[i] = '\0';
if (strcmp((const char *)buf_passwd, "hardwarehacker") == 0) {
HAL_UART_Transmit(&huart1, (uint8_t *)"Access Granted!\n", 16, 1000);
break;
} else {
HAL_UART_Transmit(&huart1, (uint8_t *)"Access Denied.\n", 15, 1000);
}
i = 0;
login_msg = 1;
}
}
/* USER CODE END 3 */
}
이 코드가 하는일은 간단하다. login_msg 가 1일때 "Login : " 을 띄운후,
rc 에 한 문자열씩 입력될 때마다 LED 를 깜빡이고, 그 문자열이 \n 또는 \r 이 아닐때 버퍼에 저장한다.
엔터를 입력하면 그 값을 strcmp 로 패스워드와 비교하여 일치하는지에따라 결과를 출력하는 것이다 :)
컴파일하여 올린후 Workspace 에 가보면 다음과같은 bin, elf 바이너리가 생성되어있다.
OpenOCD 를 설치하고 ( 이부분은 생략하였으나 다른 자료를 참고 ) OpenOCD 서버를 실행하면 telnet 과 gdb 를 사용할 수 있는 상태가 된다. 먼저 telnet 을 실행하여 보드의 초기화와 halt 하고, 펌웨어를 덤프 할 수 있다.
디버깅중 실수하여 원하는 breakpoint 지점으로 다시 새롭게 시작하려면 다시 reset init - halt 이후 다시 continue 하면 될 것이다.
지금은 예제이므로 실행파일을 SYMBOL 을 가져다 쓰기위해 .ELF 파일을 GDB 에 로드할 것이지만 실제로는 여러 함수의 심볼을 보기는 어려울 것이다.
gdb 서버를 통해 halt 되어있는 보드에 디버거를 연결한다.
workspace dir $ gdb-multiarch -q --eval-command="target remote localhost 3333: simple-login.elf
main() 에 breakpoint 를 걸고 10개의 명령어씩을 확인하도록 display 설정을 해주었다.
이후 함수들의 심볼을 확인해보았다. 대부분의 HAL 관련함수, strcmp, standard C 함수들도 보인다.
문자열을 비교하는것이므로 strcmp 를 타겟으로 하면 좋을것이다. continue 한후 UART 가 연결된 터미널에 test 를 입력한 후 continue 해보았더니 strcmp 에 breakpoint 가 걸렸고, 함수 인자를 확인해 보기위해 r0, r1 을 확인해보았다. (arm 프로세서는 인자들을 보통 r1-r4 레지스터에 저장한다. )
의외로 쉽게 패스워드를 확인 할 수 있었고, finish 를 통해 빠져나와보면 r0 와 0 을 비교하여 점프하는 구문이 있는데, reversing 에 조금만 익숙하다면 MOV, CMP, BNE 이 세가지 조합은 위에서 코딩한 if (strcmp(arg1, arg2) ... 와 비슷한 점프 구문임을 예상할 수 있을 것이다.
strcmp 는 두 문자열이 같을때 0을 리턴하므로 r0 레지스터에 0을 넣고 continue 하면 성공! 틀린패스워드이지만 통과되었다.
직접 만들어보니 많은 공부가 된 것 같다. 개인적인 기록이고 문자로 모든부분을 남겨둘 수 없어 OpenOCD 설치나 보드의 여러 환경 세팅과정의 많은 부분을 생략하였다. 직접 똑같이 따라하기 어려울 수 있으나, 디테일한 내용은 쉽게 검색할 수 있으니 참고하면 될 것이다. 세팅과정은 다음에 따로 정리 하려고 한다.
참고목록)
http://slemi.info/2018/08/17/black-pill-blinky/
https://blog.naver.com/crucian2k3/222105552572
https://www.youtube.com/playlist?list=PLUaCOzp6U-RqMo-QEJQOkVOl1Us8BNgXk
'Practice Notes > IoT Hardware Hacking Concept' 카테고리의 다른 글
Install and Usage Guide for IoT Hacking Tools [Ubuntu] (0) | 2021.07.28 |
---|---|
라우터 UART Pin 확인 실습 (0) | 2021.07.17 |