R&D
CAN BUS [1]
서영일
Oct 29, 2020

Prologue

최근 자동차 해킹에 대해 관심을 가지는 사람들이 늘고 있다. 워낙 차를 좋아해서 기회가 생기면 자동차 해킹을 해봐야겠다고 생각했었는데 마침 기술 블로그에 기고할 차례가 되어 글을 쓰게 되었다.

아무거나 다 해볼 수 있는 차가 있었으면 좋았을 것이다. 그러나 타고 다닐 차를 실습용으로 쓰기엔 불안하고, 그렇다고 실험용 차를 따로 구매하는 건 꽤 부담스럽다. 게다가 자동차 해킹 실습하는데 철판이나 바퀴 같은 게 필요한 건 아니니까 새로운 방법을 써보자!

image-20201028170658529
사실 자동차는 꽤나 비싼 물건이다….

ECU를 활용하면 좋을 것이다. 자동차와 관련된 연산은 대부분 ECU에서 이뤄지기 때문이다. 그러한 고로, 이번 글에서는 ECU를 활용한 해킹 테스트 환경을 구성해본다.

ECU란 무엇인가

ecu_pic
출처 : https://images.app.goo.gl/PRsNPqiKFuc95ni66

ECU는 전자제어유닛(Electronic Control Unit)의 약자로 자동차에서 필요한 각종 연산을 수행하는 일종의 컴퓨터이다. 과거에는 엔진제어유닛(Engine Control Unit)의 의미로만 사용되었으나 차량의 전자화가 이뤄지면서 다양한 모듈에서 전자제어가 사용되어 전자제어장치들을 모두 통칭할 때 사용하게 되었다. 최근에는 엔진 제어 유닛을 ECM(Engine Control Module) 이라고 부르며 TCU, BCM 등 다양한 유닛이 차량에 탑재되고 있다.

ECU 구매하기

ECU 테스트 벤치를 만들기 위해 ECU를 구매해보자.

필자가 구매한 물건은 17년식 아반떼(AD) 1.6 GDI A/T에 탑재되는 ECU(39110-2BAZA)이다.

구매 시 고려사항

차량 형식

요즘 차량들은 모두 ECU를 가지고 있기 때문에 어떤 차종을 선택하더라도 무관하지만, 차종이 동일하더라도 차량 형식이 바뀔 때에는 새로운 코드명을 부여받는다. 예를 들어 쏘나타는 1986년 이래로 지금까지 계속 “쏘나타”였지만 형식에 따라 코드명은 Y2, Y3, EF, NF, YF, LF, DN8로 바뀌어왔다. 차량 형식이 바뀔 때는 통상적으로 부품이 많이 바뀌기 때문에 이 부분을 반드시 확인해야 한다.

연식

연식에 따라 ECU 모듈이 바뀌는 경우는 흔하지 않지만 차후 분석에서 중요한 힌트가 될 수 있고, 간혹 연식변경 모델에서 전장 구성이 바뀌는 경우도 있기 때문에 알아둘 필요가 있다.

엔진 형식

같은 차종이더라도 여러 엔진 형식이 존재할 수 있으며, 엔진 형식에 따라 다른 ECU를 사용할 수도 있다. 예를 들어 분석에 사용되는 17년식 아반떼는 가솔린 2종(감마 1.6 T-GDI, 감마 1.6 GDI), 디젤 1종 (U-II 1.6 VGT), 총 3종류의 엔진 형식이 존재한다. 점화플러그를 사용하지 않는 디젤의 경우 엔진의 부품 구성이 달라지기 때문에 ECU 구성이 바뀔 가능성이 높다. 따라서 구매 전 엔진 형식을 알아두어야 한다.

변속기 유형

변속기 형식(자동/수동/DCT 등)에 따라 ECU가 달라지기 때문에 변속기 유형에 대해서도 알아두어야 한다.

구매 방법

pic_1
출처 : 현대모비스 부품정보검색

신품을 구매하면 좋겠으나 가격이 다소 부담스럽다. 실험에 사용하는 목적이라면 중고를 구매해도 무관하다. 인터넷 쇼핑몰이나 gparts 등에서 중고 ECU를 구할 수 있다.

image-20201028131033957
신품 가격으로 3개 쯤 살 수 있다… 🤔

신품에 비해 저렴한 가격으로 판매중인 것을 확인할 수 있다. 일부 판매점에서는 ECU와 연결되는 커넥터도 같이 판매하는 경우가 있으므로 판매점에 확인하여 함께 구매하는 것을 추천한다. 커넥터가 있는 경우 케이블을 연결하기 훨씬 쉬워진다.

ECU 연결

ECU 핀들을 보면서 속이 복잡해지겠지만 걱정하지 않아도 된다. 현대/기아 차량은 정비를 위한 기술정보 사이트 GSW를 제공하고 있다. GSW를 통해 차량 전장회로도, ECU 커넥터 정보 등을 확인하여 연결하면 된다.

image-20201028145437329
[회로도-엔진 전장-엔진 컨트롤 회로(A/T)]

회원가입 후 [전장회로도 - 모델 선택 - 연식 선택 - 엔진]을 선택한 후 원하는 회로를 선택하면 된다 (ex. 전장회로도 - 아반떼(AD) - 2017 - G 1.6 GDI) 참고할 사람을 위해 상세 메뉴를 표시해두겠다. 상세 메뉴는 차종에 따라 차이가 있을 수 있다.

커넥터

image-20201028135503667
커넥터(C100-AK) 단면도

실험에 사용되는 ECU(39110-2BAZA)는 2가지 종류의 커넥터가 필요하지만 이번에 사용할 핀들은 C100-AK 커넥터 하나에 모두 모여있다. 단자에 맞는 커넥터가 없는 경우에는 직접 납땜을 해야한다. 필자는 커넥터를 못 구했기 때문에 핀의 크기가 큰 1~6번 핀은 납땜으로 연결하고, 좌측 핀은 흔히 볼 수 있는 CH254(아두이노 등에 흔히 사용되는 소켓) 소켓 케이블로 연결했다.

image-20201028141435630
[커넥터 정보-컨트롤 하네스-회로도]

C-CAN, CCP-CAN 통신을 위한 High/Low 핀, 전원 및 접지 핀에 케이블을 연결한다. 여기서 주의할 점은 커넥터의 배선이기 때문에 좌우가 반대라는 것이다. 그림이 좌우로 뒤집어졌다고 생각하고 작업해야 올바른 위치에 연결할 수 있다

image-20201028143346349
‘연결만 되면 됐지’ 같은 마감 상태

전원 공급

필요한 모든 선을 ECU에 연결했다면 전원을 공급해야 한다. ECU에 필요한 전압은 GSW에서 확인할 수 있다.

image-20201028151400097
[정비지침서-아반떼(AD)-2017-G 1.6 GDI-엔진 제어/연료 시스템-엔진 컨트롤 모듈(ECM)-회로도]

전압은 시동 시 배터리 전압을 따른다고 나와있으므로 자동차 배터리 전압인 12V를 공급하면 된다. 구체적인 요구사항과 신호명 각 항목에 대한 자세한 내용을 알고 싶다면 회로도-엔진 전장-엔진 컨트롤 회로(A/T)-서비스 팁을 참고하면 된다.

12V를 공급하는 방법은 여러가지가 있지만, 쓰지 않는 컴퓨터 파워서플라이를 가져와서 전원 공급에 사용하는 방법도 있다.

image-20201028152046716
[파워 서플라이 전원 정보]

가지고 있는 파워서플라이를 확인해보니 12V/18A 전원을 지원하는 것을 확인할 수 있다. 연결해보니 동작하는 데 크게 이상은 없었다. 대강 요구사항에 맞으면 파워서플라이 케이블을 잘라내고 작업을 시작해보자. 작업 직전에 파워서플라이를 사용한 적이 있다면 캐패시터를 충분히 방전시키는 것을 잊지말자

image-20201028153014068
파워서플라이에는 고전압이 흐르고 있다. 작업에 유의하도록 하자
ATX power supply pinout 24 and 20 pin
출처 : https://www.smpspowersupply.com/connectors-pinouts.html

그림은 ATX 파워서플라이 단자의 배치도이다. ECU에 전원을 공급하기 위해 파워서플라이의 12V 핀, 그리고 PS_ON(16번), 15번 COM이 필요하다. 12V 직류 전원을 제공하는 포트는 노란색 중 하나를 사용하면 되고, 접지는 검은색을 사용하면 된다. PS_ON은 파워서플라이의 시작을 위해 사용되는 핀으로 15번 COM과 쇼트 시켜주면 된다. PS_ON을 쇼트시켜주지 않으면 파워서플라이가 켜지지 않는다.

Arduino + CAN Shield

CAN 데이터를 송/수신하기 위해 아두이노를 사용한다. 데이터가 많이 쌓이면 아두이노가 먹통이 되는 경우가 잦아 라즈베리 파이를 추천하지만 아두이노를 쓰는 편이 더 쉽기 때문에 이번 게시글에서는 아두이노를 이용한 방법을 소개한다.

image-20201028161216982
비싸서 못 사는 게 아니고 배송비 2,500원이 뼈 아프다

아두이노가 CAN 통신을 하도록 하기 위해서는 CAN 모듈이 필요하다. 많은 비싼 모듈이 있지만 이정도 제품이면 크게 문제되지 않는다. 아두이노와 MCP2515 모듈은 다음과 같이 연결한다.

MCP2515 Arduino
VCC 5V
GND GND
INT DIGITAL 2
CS DIGITAL 9
SI DIGITAL 11
SO DIGITAL 12
SCK DIGITAL 13

MCP2515를 사용하기 위해 라이브러리(https://github.com/Flori1989/MCP2515_lib)를 설치한다.

배선 작업 및 회로 구성

다시 한 번 강조하지만, 작업 전 파워서플라이의 전원을 제거하고 방전될 때까지 충분한 시간이 지난 후 작업해야한다.

IMG_8289
파워서플라이 DC 12V 열수축튜브 작업

안전하고 깔끔한 배선 작업을 위해 다이소에서 1000원에 구할 수 있는 열수축튜브를 사용했다. 브레드보드에서 작업하기 위해 전선을 자르고 CH254 소켓을 연결했다. 이후 CAN Shield, ECU 전원들을 브레드보드에 구성했다.

IMG_8304
브레드보드 구성 사진

구성에 대한 이해를 돕기 위해 그림을 준비했다.

image-20201029133438034.png
전체 회로도

파워서플라이에서 12V, GND, PS_ON 핀을 따오고, ECU와 이어지도록 작업한다. PS_ON은 GND와 따로 이어지도록 구성해줘야 한다. ECU 전원 및 접지는 파워서플라이의 전원, 접지에 바로 이어져도 상관없다. ECU와 CAN은 HIGH, LOW를 그대로 이어주고, 아두이노와 CAN Shield는 이전 단원에서 다뤘던 그대로 이어주면 된다.

전원부를 직접 연결하는 것이 부담된다면 안정적인 동작을 위해 회로의 퓨즈 용량에 맞게 전원부에 회로를 구성하는 것도 좋다. 회로의 퓨즈 용량은 GSW의 회로도 [회로도-엔진 전장-엔진 컨트롤 회로(A/T)-회로도]에서 확인할 수 있다. 다만 이번 글의 목표는 단순히 ECU에서 신호가 잘 출력되는지를 확인하는 것이므로 별도의 회로를 구성하지는 않았다. 이는 다음 편에서 다루겠다.

데이터 출력

#include <mcp_can.h>
#include <SPI.h>
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];

MCP_CAN CAN0(9);

void setup()
// Set CS to pin 9
{
  Serial.begin(115200);
  if(CAN0.begin(CAN_500KBPS, MCP_8MHz) == CAN_OK) Serial.print("can init ok!!\r\n"); 
  else Serial.print("Can init fail!!\r\n");
  pinMode(2, INPUT); // Setting pin 2 for /INT input 
  Serial.println("MCP2515 Library Receive Example...");
}
void loop()
{
  if(!digitalRead(2))
  {
    CAN0.readMsgBuf(&len, rxBuf);
    rxId = CAN0.getCanId();
    Serial.print("ID: ");
    Serial.print(rxId, HEX);
    Serial.print(" Data: ");
    for(int i = 0; i < len; i++)
    {
      if(rxBuf[i] < 0x10)
      {
        Serial.print("0");
      }
      Serial.print(rxBuf[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  }
}

MCP2515 라이브러리에 들어가있는 CAN 통신 읽기 예제 코드이다. 간단한 코드지만 ECU가 정상적으로 작동하는지 확인하는 데에는 충분하다.

IMG_8276
패킷이 너무 많이 나와서, 오래두면 아두이노 프로그램이 뻗는다

전원을 켜면 실시간으로 많은 CAN 패킷들이 쏟아져 나오는 것을 확인할 수 있다.

이제 분석을 시작하면 된다!

Epilogue

image-20201028163713843
테스트 환경 전체 모습

이번 게시글에서는 ECU와 PC용 파워서플라이, 아두이노 그리고 간단한 배선작업을 통해 자동차 해킹을 위한 테스트 환경을 구성해보았다. 다음편부터는 본격적으로 CAN통신 분석을 시작하겠다.

다음편에서는

CAN 패킷 내용 분석

이번 게시글에서는 ECU에 회로를 구성하여 CAN 패킷을 추출해보았다. ID와 데이터를 파싱하여 출력했지만 어떤 내용을 담은 패킷인지 분석해보지는 않았다. 다음 편에서는 내부 구성과 의미를 분석해볼 예정이다.

입력 - 악셀 페달 포지션 센서(APS)

자동차 게임에 쓰이는 레이싱 휠/페달은 내부 구조가 복잡할 것 같지만 사실은 간단한 가변저항들로 구성되어 있다.

GTEYE Progressive Brake Spring for Logitech G25 / G27 / G29 / G920 / GTEYE
출처 : https://images.app.goo.gl/FmNJ5N9BgUVdgd9T6

실제 자동차도 상당히 비슷한 구조로 센서들을 통해 악셀 페달의 위치를 감지한다. 이에 사용되는 악셀 페달 포지션 센서(APS)는 현재 가속페달이 어떤 위치에 있는지 감지하는 센서로, 사용자가 어느정도의 가속을 의도하고 있는지 파악할 수 있는 중요한 센서이다.

원리는 비슷하지만 게임에 사용되는 레이싱 휠/페달처럼 단순한 구조는 아니고, 오작동을 방지하기 위해 2개의 전압 값을 통해 입력 교차검증을 수행한다. GSW에서는 APS에 대하여 다음과 같이 설명하고 있다.

페달 위치 센서는 신뢰도가 중요한 센서로, 주 신호인 센서 1과 센서 1을 감지하는 센서 2로 구성되어있다. 센서 1과 2는 서로 독립된 전원과 접지로 구성되어 있으며, 센서2는 센서 1의 출력의 1/2 출력을 발생하여, 센서 1과 2의 전압 비율이 일정 이상 벗어날 경우 에러로 판정된다.

image-20201028165107310
악셀 페달 포지션 센서 출력 전압 그래프

C.T(스로틀 전폐), W.O.T(스로틀 전개) 상태에 따라 요구되는 출력 전압이 다르다. 이에 따라 악셀러레이터 페달의 저항값, 그리고 센서 2의 입력에 해당되는 곳의 저항값을 조절하는 회로를 구성하여 ECU가 요구하는 전압 값을 만족시킬 수 있다. 차후 연구에서는 악셀러레이터 페달 값을 임의로 주고 그에 따른 ECU의 반응을 살펴볼 계획이다.

서영일
RECENT POST
이예랑
Gnuboard <= 5.4.1.1 RCE
Gnuboard <= 5.4.1.1 RCE
김도현
Metasploit Community CTF Review
Metasploit Community CTF Review.