'하드웨어 해킹 및 임베디드'에 해당되는 글 20건

https://kr.analysisman.com/2021/04/bluetooth-attack.html

 

블루투스(Bluetooth) 공격 기법

블루투스 해킹,블루투스(Bluetooth) 공격 기법,블루투스 취약점 리스트,블루투스(Bluetooth) 취약점,블루투스(Bluetooth) 기술,블루재킹(Bluejacking) 블루스나핑(Bluesnarfing) 블루버깅(Bluebugging),블루투스 해

kr.analysisman.com

 

블루투스(Bluetooth) 공격 기법

 
 
  • 블루투스 기술

블루투스(Bluetooth)는 1994년에 에릭슨이 최초로 개발한 디지털 통신 기기를 위한 개인 근거리 무선 통신 산업 표준이다. 자세한 스펙과 설명은 위키 페이지를 참조하고, 이 블로그 글에서는 블루투스 기술에 대한 요약과 함께 블루투스를 이용한 해킹에 관해 설명한다.

✓ 클래스에 따라 도달 거리가 0.5m~100m 다르지만, 보통 10m(미터) 이내의 초단거리에서 저전력 무선 연결에 쓰인다.

✓ 주파수는 ISM 대역인 2.402~2.480 GHz, 총 79개 채널을 쓴다. 
ISM이란 산업, 과학, 의료용으로 할당된 주파수 대역으로, 아마추어 무선, 2.4GHz 무선랜, 블루투스가 이 ISM 대역을 사용한다.

✓ 여러 시스템과 같은 주파수 대역을 이용하기 때문에 시스템 간 전파 간섭이 생길 우려가 있는데, 이를 예방하기 위해 블루투스는 주파수 호핑(Frequency Hopping) 방식을 취한다.
주파수 호핑이란 많은 수의 채널을 특정 패턴에 따라 빠르게 이동하며 패킷(데이터)을 조금씩 전송하는 기법이다. 블루투스는 할당된 79개 채널을 1초당 1600번 호핑한다.

✓ 이 호핑 패턴이 블루투스 기기 간에 동기화되어야 통신이 이루어진다. 
블루투스는 기기 간 마스터(Master) 슬레이브(slave) 구성으로 연결되는데, 마스터 기기가 생성하는 주파수 호핑에 슬레이브 기기를 동기화시키지 못하면 두 기기 간 통신이 이루어지지 않는다. 이로 인해 다른 시스템의 전파 간섭을 피해 안정적으로 연결될 수 있게 된다. 참고로 하나의 마스터 기기에는 최대 7대의 슬레이브 기기를 연결할 수 있다.

✓ 블루투스 버전 별 최대 데이터 전송 속도는 아래와 같다.
버전연도최대 전송 속도
1.0, 1.0B + BR (Basic Rate) 1999 768 Kbps
1.1 2002 768 Kbps
1.2 2003 1 Mbps
2.0 (2.1) + EDR (Enhanced Data Rate) 2004 3 Mbps
3.0 + HS (High Speed) 2009 24 Mbps
4.0 + LE (Lower Power, aka Bluetooth Smart), 4.1 2010 24 Mbps
4.2 2014 24 Mbps
5.0 2016 48 Mbps


  • 블루투스 공격 기법
 

▶ 블루재킹(Bluejacking)

블루스패밍(Bluespamming)이라고도 하며, 스팸처럼 익명으로 블루투스 사용자에게 메시지를 보내는 기법이다. 귀찮은 존재긴 하지만 보안에 큰 위협을 가하지는 않는다.

▶ 블루스나핑(Bluesnarfing)

블루투스의 취약점을 이용하여 장비의 임의 파일에 접근하는 공격으로 모바일 기기에 저장된 일정표, 전화번호, 이메일, 문자메시지 등에 접근하는 방법이다.

▶ 블루버깅(Bluebugging)

블루투스 장비 간의 취약한 연결 관리를 악용한 공격으로 공격 장치와 공격 대상 장치를 연결하여 공격 대상 장치에서 임의의 동작을 실행하는 공격이다.

희생자의 휴대폰을 원격 조종해 통화내용을 엿듣는 해킹 방법으로 치명적인 피해를 야기할 수 있다. 이 기술을 이용하려면 타겟과 10m 이내에 있어야 가능하다.
 

  • 블루투스 공격 도구
 

▶ 레드팽(RedFang)

숨겨진 블루투스 기기를 찾아내는 PoC 애플리케이션으로 무차별 대입을 통해 피해자의 블루투스 MAC 주소를 추측한다.
 

▶ 블루스니프(BlueSniff)

검색 가능하고 숨겨진 블루투스 기능이 활성화된 장치를 찾는 간단한 유틸리티다.
 

▶ BT스캐너(BTScanner)

무차별 대입 스캔, 반경 내 블루투스 기기 식별, 스캔 결과 내보내기 및 결과 정렬을 수행할 수 있는 블루투스 스캔 프로그램이다.
 

▶ 블루버그(BlueBugger)

블루투스가 활성화된 모바일 기기의 보안 취약점을 이용하는 도구. 연락처와 통화 목록을 다운로드하고 공격자 모바일에서 SMS 메시지를 보내고 읽을 수 있게 해준다.
 
 

  • 블루투스 취약점
 

▶ BlueBorne (2017)

✓ 이 취약점은 안드로이드, iOS, 윈도우, 리눅스, 사물 인터넷 기기 등 약 53억대 이상의 기기에 영향을 미치는 것으로 나타났다.
✓ 블루본(BlueBorne)은 공격자가 블루투스가 활성화되어 있는 장치에 페어링하지 않아도 장치를 제어할 수 있는 공격 형태다.
✓ 공격자는 피해자의 장치 블루투스가 활성화된 상태로, 가까운 위치에 있기만 하면 된다.
✓ 아래와 같은 8개의 CVEs가 IoT 보안회사 아미스 랩(Armis Labs)에 의해 발견되었다.
 - 안드로이드: RCE (CVE-2017-0781, CVE-2017-0782), Information leak (CVE-2017-0785), MITM (CVE-2017-0783)
 - iOS: RCE (CVE-2017-14315)
 - 윈도우: MITM (CVE-2017-8628)
 - 리눅스: Information leak (CVE-2017-1000250), RCE (CVE-2017-1000251)
 
 
* 관련 기사

▶ KNOB (2019)

 CVE-2019-9506이라고 불리는 이 취약점은 '암호화 키 협상 프로토콜'이 두대의 장비에 보안 연결을 할때 두대의 블루투스 BR/EDR 디바이스가 암호화 키를 위한  앤트로피 값을 선택하는 방식에서 나타난다.
✓ KNOB(Key Negotiation of Bluetooth) 공격이라고 불리는 이 취약점은 원격 공격자가 가까운 거리에서 타깃 디바이스에 연결된 두 디바이스 사이에 암호화된 블루투스 트래픽을 조작하거나 감시하거나  가로채는 것이 가능하다.
✓ KNOB 공격을 완화하기 위해 Bluetooth 사양 관리자는 장치 제조업체와 소프트웨어 공급 업체가 BR/EDR 연결에 최소 7옥텟의 암호화 키 길이를 적용 할 것을 강력히 권장했다.
 
 
USENIX Security '19 - The KNOB is Broken: Exploiting Low Entropy in the Encryption Key
 
 
* 관련 기사

▶ BIAS (2020.3)

✓ 이 취약점(CVE-2020-10135)은 코드네임 BIAS(Bluetooth Impersonation AttackS)로 명명되었으며, Bluetooth BR/EDR, Bluetooth Classic 등으로 불리고 있는 블루투스 프로토콜의 클래식 버전에 영향을 준다.
✓ 암호화 연결을 생성하기 위해서는 두 개의 블루투스 기기를 페어링할 때 링크 키를 사용해야 하는데, 기기와 물리적으로 근접한 무단 공격자는 이전에 페어링(연결된) 기기를 위조하여 링크 키 없이도 인증할 수 있다.
✓ BIAS와 KNOB를 조합한다면 공격자가 블루투스 클래식 기기가 안전 인증 모드에서 동작한다고 하더라도 인증을 깰 수 있다.
 
* 관련 기사

▶ BLURtooth (2020.7)

✓ 이 취약점은 블러투스(BLURtooth)라고 불리며, CVE-2020-15802라는 번호가 붙었다.
✓ 이 취약점을 익스플로잇 할 경우 인증을 통과하지 못한 공격자들이 페어링 된 장비들 간 통신 내용을 바꾸거나 엿들을 수 있다.
✓ 블루투스 4.0~5.0 버전의 페어링 과정을 ‘교차 전송 키 파생(Cross-Transport Key Derivation, CTKD)’이라고 부르는데, 이것의 구현 방법과 취약점에 밀접한 관련이 있다.
 
※ 블러투스 취약점과 관련된 블루투스 프로토콜에는 두 가지 유형이 있다.
1) 블루투스 클래식(Bluetooth Classic) : 블루투스 Basic Rate / Enhanced Data Rate(BR/EDR)이라고도 불린다. 좀 더 오래된 유형이다.
2) 블루투스 로우 에너지(Bluetooth Low Energy) : 줄여서 BLE라고도 하며 클래식보다 새로운 유형의 프로토콜이다.
BR/EDR은 주로 오디오 관련 애플리케이션들에 사용되고, BLE는 웨어러블 장비들에서 보다 많이 나타난다.
 
* 관련 기사
 

▶ BLESA (2020.9)

✓ 블레사는 퍼듀대학의 연구원들이 블루투스 저전력(BLE)에서 취약점을 발견했다. (CVE-2020-9770)
✓ 블레사(BLESA)는 BLE 스푸핑 공격(BLE Spoofing Attacks)의 준말로, 블루투스 연결이 재차 성립되는 과정에서 발동된다.
✓ 전 세계 수십억 대의 사물인터넷 장비에 영향을 줄 만한 것이며, 안드로이드 장비들은 거의 대부분 이 취약점에 노출된 채 사용되고 있다.
✓ 공격자들은 재연결 시 필요한 인증 과정을 BLESA를 통해 우회해 표적으로 삼은 장비에 접근해서 가짜 데이터를 보낼 수 있다.
✓ 문제는 BLE가 애드버타이징 패킷(advertising packet)을 항상 평문으로 전송하고, 장비 간 재연결이 이뤄질 때 인증이 필수가 아닌 경우가 많은 것.
 
 
WOOT '20 - BLESA: Spoofing Attacks against Reconnections in Bluetooth Low Energy
 
 
* 관련 기사

▶ BleedingTooth (2020.10)

✓ 구글과 인텔이 리눅스 블루투스 프로토콜인 블루지(BlueZ)에서 고위험군에 속하는 취약점을 발견했다. 
✓ 블루지는 리눅스 기반 사물인터넷(IoT) 장비들에 탑재된 블루투스 기능을 구현하는 데 있어 핵심적인 요소 중 하나다.
✓ 구글에 의하면 리눅스 커널 5.9 이전 버전의 경우 블리딩투스(BleedingTooth) 취약점에 노출되어 있다고 한다.
✓ 블리딩투스 취약점의 가장 큰 특징은 피해자가 링크를 클릭하거나 파일을 열지 않아도 되는 ‘제로 클릭 공격’이 가능하다는 점이다.
 CVE-2020-12351 (high), CVE-2020-12352 (medium), CVE-2020-24490 (medium)
 
 
* PoC 익스플로잇 영상 - BleedingTooth: Linux Bluetooth Zero-Click Remote Code Execution
 
 
* 관련 기사
 
 
  • 블루투스 해킹 대응 방안
 
① 블루투스이 필요할 때만 연결하고 사용하지 않을때는 블루투스를 OFF 합니다.
패치가 나와 업데이트했더라도 평소에 필요할 때만 블루투스 기능을 켜는 것은 좋은 습관입니다.  보안 측면에서 공격 표면(Attack Surface)를 줄이고, 스마트폰은 배터리를 아낄 수 있는 추가 장점도 있습니다.
 
특히 리눅스의 경우, 커널 5.9 이전 버전의 경우 블리딩투스(BleedingTooth) 취약점에 노출되어 있습니다. 커널 패치가 어려운 경우가 많으니 블루투스를 사용하지 않는 경우 disable 하기를 권장합니다.
 
* 참고:
 
② 블루투스 연결 시 페어링 요청을 보내는 디바이스를 정확히 확인하고, 신뢰할 수 있는 경우에만 승인합니다.
 
③ 시스템이나 모바일 장치의 펌웨어나 소프트웨어를 항상 패치하여 최신 상태로 유지합니다.
최신 버전의 소프트웨어를 유지하는 것은 사이버보안에서 가장 중요합니다.
 
 
 함께 읽어보면 좋은 관련 글: 무선(Wi-Fi) 네트워크 보안 및 취약점
 

'하드웨어 해킹 및 임베디드' 카테고리의 다른 글

ISO 21434 CAL Level  (0) 2023.06.29
Chapter 7. Device control  (0) 2023.06.25
Car Hacking Training  (0) 2023.05.18
SecOC(Secure On-board. Communication)  (1) 2023.05.16
Embedded Recipes  (0) 2023.04.11
블로그 이미지

wtdsoul

,

https://www.autoelectronics.co.kr/article/articleView.asp?idx=4655 

 

ISO 21434 통한 실질적 사이버 보안 대응

Vector가 작성한 이 기사는 ISO 21434에 따른 체계적인 보안 엔지니어링에 대해 설명하고 있으며 ISO 21434의 효율적인 구현을 위한 글로벌 프로젝트의 실제 사례 소개한다.

www.autoelectronics.co.kr

ISO 21434를 통한 실질적인 보안 엔지니어링 

다음 사례는 ISO 21434가 실제로 어떻게 단계적으로 적용되는지 보여준다. 사례 연구는 첨단 운전자 지원 시스템 (Advanced Driver Assistance Systems, ADAS) 프로젝트에서 가져온 것으로 기사의 형식에 맞게 단순화하였다.

1단계: 아이템 정의 
아이템 정의는 구성 요소의 범위를 정의하기 위해 필요하다. 정의된 범위는 시스템의 자산을 식별하기 위한 참조로 사용된다. 이 예에서 아이템은 넓은 의미에서 전체 ADAS 시스템을 말한다. 최상위 네트워크 아키텍처는 그림 3과 같으며, CAN 프로토콜을 통해 모든 통신이 이루어진다고 가정한다. 외부 인터페이스는 기본 아키텍처를 기반으로 식별된다. 이 시스템은 4G 네트워크를 통해 OEM 클라우드 인프라와 통신할 수 있는 기능이 있으며 게이트웨이 모듈에 연결된 OBD 단자가 있다.




그림 3 | ADAS 네트워크 아키텍처의 예



2단계: 자산 식별 
다음 단계는 아이템 범위에 속한 모든 자산을 나열하는 것이다. 자산은 예를 들어 기능 안전 목표, 재정적 위험, 운영 비용 및 개인 정보 보호와 같이 손상될 때의 위험 또는 가치를 기반으로 선택된다. 다음은 ADAS 시스템의 자산(Asset, A) 예이다.

- A1: ADAS가 송수신하는 네트워크 메시지
- A2: 안전 메커니즘을 포함한 ADAS 소프트웨어
- A3: 보안 키
- A4: 운전 이력 및 기록 데이터

3단계: 위협 분석 및 위험 평가(Threat analysis and risk assessment, TARA) 
식별된 자산을 기반으로 다음 단계인 TARA를 수행한다. TARA는 자산이 위협에 의해 사이버 공격을 받았을 경우에 대해 피해 시나리오의 영향 등급과 공격 가능성 등급을 체계적으로 평가하여 위험 수준을 1(매우 낮음)에서 5(매우 높음)까지의 척도로 결정한다. 나아가 결정된 위험 수준에 따라 위험 처리 조치를 계획하고 실행할 수 있다. ISO 21434는 CAL1(낮음)에서 CAL4(높음)까지 모든 위협에 대해 사이버 보안 보증 수준(Cybersecurity assurance level, CAL) 적용을 선택적으로 제안한다. 다음은 피해 시나리오(Damage Scenario, DS)에 대한 몇 가지 예이다.

- A1-DS1: 추돌 상황에서 운전자가 브레이크 페달을 밟아도 차량이 멈추지 않음
- A2-DS2: 자율 주행에서 수동 전환 시 차선 변경이 안되어 차선 변경 실패로 인한 사고 발생

이를 기반으로 위협(Threat, T)을 식별하며 다음과 같다.

- A1-DS1-T1: 제동 메시지 송수신 서비스 거부(DOS) 로 인해 제동 제어기가 제동을 수행하지 않음.
- A2-DS2-T2: ADAS 조향 SW가 변경되어 오염된 SW로 인해 ADAS 수동 전환 기능이 동작하지 않음. 

표 1은 공격 가능성 등급과 영향 등급을 보여준다. 위에서 식별된 자산과 피해 시나리오를  기반으로 위협을 평가하여 위험 수준과 CAL을 산출하였다.




표 1  | TARA 분석의 예



4단계: 사이버 보안 목표 및 사이버 보안 요구 사항 
위험을 완화하기 위해 사이버 보안 목표를 식별하고 효과에 따라 평가한다. 사이버 보안 목표는 최상위 수준의 사이버 보안 요구 사항이다. 각 사이버 보안 목표로부터 하나 이상의 사이버 보안 요구사항들이 도출되고, 모든 사이버 보안 요구사항에 대해 하나 이상의 기술적 사이버 보안 요구사항이 도출된다. 이 예에서는 다음과 같다.

- 사이버 보안 목표(Cybersecurity Goal, SG) A1-T1-SG1 
   시스템은 운전자 지원 시스템에서 보낸 메시지가 조작되는 것을 방지해야 한다.
- 사이버 보안 요구 사항(Cybersecurity Req., SeR) SG1-SeR1 
   운전자 지원과 센서 간의 통신 무결성이 보장되어야 한다.
- 기술 사이버 보안 요구 사항(Technical Cybersecurity Req., TSeR) SG1-SeR1-TSeR1 
   메시지 인증 코드 (MAC)은 RSA2048 알고리즘을 사용하여 SHE(Secure Hardware Extension)와 호환되는 HTA(Hardware Trust Anchor)로 계  산되어야 한다.
- 기술 사이버 보안 요구 사항(Technical Cybersecurity Req., TSeR) SG1-SeR1-TSeR2
   MAC은 x바이트로 줄인 형태로 사용한다.

5단계: 추적성 
추적성은 일관성을 유지하고 위험부담을 완화하는 데 도움이 된다. 변경 사항이 발생하고 지속적인 빌드 활동 중에도 적용범위와 일관성을 보장하는 데 필수적이다.
그림 4는 요구사항을 설계와 테스트에 연결시키는 추상화 모델을 보여준다. 한 예로, 부정적인 요구 사항, 즉 해커가 공격하기 위해 필요한 내용을 분석하고, 이로부터 해당 공격의 실현 가능성을 낮추기 위한 솔루션을 도출한다. 이것은 초기 TARA 및 보안 요구 사항 정의에서 완전한 추적성을 보장한다.




그림 4 | 삼중 피크 추상화모델에서 사이버 보안의 추적성



6단계: 설계  
ADAS 시스템은 자산에 대해 TARA에서 발견된 위험 때문에 설계 변경을 필요로 한다. 사이버 보안 목표 SG1은 시스템이 네트워크 신호의 조작을 막기 위해 탐지 및 방지 메커니즘을 갖추고 있어야 한다는 점을 강조한다. 사이버 보안 개념을 기반으로 하여 탐지 및 방지 메커니즘을 설계할 수 있다.

이로 인해 하드웨어 설계도 변경해야 할 수 있다. 이 사례연구의 경우 HTA를 사용해야 한다. 소프트웨어의 경우MISRA 및 CERT 지침을 통한 보안 코딩은 보안 악용으로 이어질 수 있는 설계와 코드상의 오류를 방지하기 위해 적용한다. 대부분의 공격은 부적절한 설계로 인해 발생한다는 점을 항상 염두에 두어야 한다.

7단계: 통합 및 검증 
이 단계에서의 주된 목표는 통합 구현된 보안 메커니즘이 사이버 보안 목표 및 요구 사항을 충족하는지 확인하는 것이다. 다음은 일반적으로 사이버 보안 검증 및 확인을 위해 권장되는 방법들이다.

- 단위 수준 검증: 정적 및 동적 코드 품질 분석은 단위 수준에서의 강건성과 함께 MISRA 및 CERT와 같은 보안 코딩 지침에 중점을 둔다. 자동화 도구는 코드 품질 분석(Code Quality Analysis, CQA)을 수행하고 테스트 보고서를 생성하는 데 사용한다.

- 기능 테스트: 요구 사항을 기반으로 하는 테스트는 시스템 설계 및 아키텍처의 기본적 결함을 식별하는 데 도움이 될 수 있다. 이 예에서 아이템의 정의 부분에서 설명한 실제 기능은 추가적인 보안 조치로 인해 기능의 성능이 손상되지 않았음을 시스템 차원에서 테스트한다.
- 퍼지 테스트: 퍼지 테스트는 예상 범위와 영역을 넘어서는 다양한 차량 통신 프로토콜을 테스트하는 데 사용된다.
- 침투 테스트: 침투 테스트는 구성 요소 및 시스템 차원에서 독립적으로 수행되는 테스트 전략이다. Gray Box Penetration Test[5]라는 테스트방식이 높은 효율성과 효과를 보여 이에 적합함이 입증되었다.

8단계: 개발 후 단계 
유지보수 및 업데이트 관리는 제품 개발 과정 중에 준비되어야 한다. 여기에는 제품의 생산, 일반적인 운영 및 유지 관리, 그리고 마지막으로 폐기까지 포함된다. 사고 대응, 보안 경고 알림, 소프트웨어 패치와 배포 같은 활동을 위해 예산, 시간, 인력을 확보해야 한다. 이를 몇 가지 단계로 나누어 볼 수 있다.

- 생산: 제품을 제조하고 조립하는 동안 여러 사이버 보안 요구 사항을 준수해야 한다. 예를 들어, 최종 생산라인에서 HTA의 메모리에 공급업체 또는 OEM 관련 암호 키 재료를 투입하는 것을 계획하고 처리해야 한다.
- 운영 및 유지보수: 모든 조직은 지속적인 사이버 보안 활동의 일환으로 프로젝트와는 독립된 모니터링 조직을 운영할 필요가 있다. 조직은 사이버 보안 이벤트가 발생했을 때 미리 정의하고 합의한 사이버 보안 사고 대응 계획에 따라 보안 사고를 처리해야 한다.
- 폐기: 제품 폐기시에 사이버 보안과 관련된 정보가 여전이 포함되어 있을 수 있으므로 이를 위한 폐기 단계에서의 절차 등에 대해 고려가 필요하다. 


결론  

차량 내에 IT 제품의 개발과, 생산 및 운영 분야의 기업 IT가 융합되면서 자동차 사이버 보안은 큰 연계성을 얻게 되었다[1, 2, 3, 4]. 이는 자동차 기능 안전을 위한 전제 조건이며 이해하기 쉽고 체계적으로 구현되어야 한다. ISO 21434는 자동차 사이버 보안을 위한 기본적인 지침으로, 이를 위한 프레임워크를 제공한다. 그러나 이를 실제 개발 프로세스로 정의할 때 있는 그대로 가져다 쉽게 적용할 수 있는 것은 아니다. ISO 21434를 효과적이고 효율적으로 구현하기 위해서는 전문적인 경험과 가이드가 필요하다. 이는 특히 차량 법규(UNECE R.155 CSMS)와 관련하여 나중에 그 효과가 입증되어야 하는 경우에 더욱 그렇다.

사이버 보안은 단지 보안 관련 조직 뿐만 아니라 제품의 수명 주기와 관련된 모든 관련자들의 책임이다. 깊이 있는 시스템 엔지니어링부터 시작하여 전체 제품 수명 주기 동안 관리되고 추적할 수 있는 총체적인 접근 방식이 필요하다.

출처: AEM (https://www.autoelectronics.co.kr)

'하드웨어 해킹 및 임베디드' 카테고리의 다른 글

Bluetooth 공격 기법  (0) 2023.06.30
Chapter 7. Device control  (0) 2023.06.25
Car Hacking Training  (0) 2023.05.18
SecOC(Secure On-board. Communication)  (1) 2023.05.16
Embedded Recipes  (0) 2023.04.11
블로그 이미지

wtdsoul

,

https://velog.io/@embeddedjune/%EC%9E%84%EB%B2%A0%EB%94%94%EB%93%9C-%EB%A0%88%EC%8B%9C%ED%94%BC-%EC%9A%94%EC%95%BD-%EB%B0%8F-%EC%A0%95%EB%A6%AC-Chapter-7.-Device-control

 

[임베디드 레시피 요약 및 정리] Chapter 7. Device control

※ 이번 chapter에서는 지금까지 여러 차례 언급했던 각 device 및 HW를 어떻게 제어할 수 있는지에 대해 배워봅시다. ※ 작은 것부터 큰 것까지 순서대로 register → memory → memory controller —> LCD(periphe

velog.io

 

[※] 이번 chapter에서는 지금까지 여러 차례 언급했던 각 device 및 HW를 어떻게 제어할 수 있는지에 대해 배워봅시다.

1. Device control

[※] 작은 것부터 큰 것까지 순서대로 register → memory → memory controller —> LCD(peripheral device)를 제어하는 방법에 대해 알아봅시다.

Device는 MCU 외부에 달려있는 IP를 의미하며, 대략 아래와 같은 구성과 흐름으로 이뤄진다.

  • CS핀 (Chip select) : 이 device를 사용하겠다고 활성화시키는 역할을 하는 핀으로 CE(Chip Enable)핀이라고 표기되기도 한다. CS/로 표기되는데, 슬래시는 ‘low active’라는 뜻이다. 따라서 이 device를 사용할 때는 0을 입력해야 한다.
  • Data핀 : 양방향 핀으로 명령어 또는 데이터를 주고받는 용도로 사용하는 핀이다. 여러 개의 핀으로 구성될수도 있고, I2C/ SPI 등으로 한두가닥의 bus로 구현될 수도 있다.
  1. CS를 low로 만들어서 ‘널 쓸거야’ 라고 알려준다.
  2. Data핀으로 slave에게 command sequence를 보내서 명령한다.
  3. Data핀으로 device는 제대로 수신했고 ready 상태임을 master에게 알려준다.
  4. Data핀으로 데이터를 쓰거나 읽는다.
  5. CE를 high로 만들어서 사용을 종료한다.

1.1. Register

레지스터 설정은 1) 레지스터의 주소에 접근, 2) 값을 쓰거나 읽음 2가지로 구성돼있다.

  • SW적으로는 굉장히 간단하지만, 내부 과정에는 복잡한 HW 과정이 포함돼있다.
  • SW 개발자 입장에서는 내부 latch 제어 과정까지는 자세히 알지 못해도 괜찮다.
  • 하지만, 주의할 점은 레지스터는 부분 접근이 불가하다는 점이다.
    • 예를 들어, 0x12345678에 있는 32-bit 레지스터 A가 있다고 가정하자.
    • A의 12번째 bit인 A[11]에 접근하기 위해 1-byte 뒤인 0x12345678 + 0x1에 접근해서는 안 된다.
  • 왜냐하면, ‘memory mapped I/O’라는 개념에 의해 레지스터든, 메모리든, 외부 peripheral이든 모두 메모리에 접근하듯 align된 주소를 통해 접근 및 제어가 가능하기 때문이다. Memory mapped I/O란, 레지스터와 외부 I/O controller 등을 특정하는 주소를 메모리의 일부 영역에 할당해서 별다른 조치를 취하지 않고도 메모리를 제어하듯 레지스터와 외부 장치를 제어하는 기능을 말한다. 따라서 레지스터, 메모리, I/O peripheral 모두 특정 address에 접근하는 것으로 제어할 수 있다.

1.2. Memory & Memory controller

  • ARM core와 memory 사이에는 양방향 데이터 흐름을 제어하는 controller가 있다.
  • 메모리도 위에서 배운 device 동작과정과 거의 동일한 과정을 거쳐서 제어할 수 있다.
    1. CS를 low로 만들어 enable 한다.
    2. OE(Output Enable)을 low(read) 또는 high(write)로 만든다.
    3. Address line에 읽거나 쓰기를 원하는 주소를 지정한다.
      • ([※] 보통 여기에 ALE (Address Latch Enable) 이라는 핀이 있어서, OE와 address가 준비되면 권총 트리거를 당겨서 쏘듯 slave에게 정보를 보내는 역할을 하는 핀이 추가로 있습니다.)
    4. Data line에 read할 데이터가 뜨거나, write할 데이터를 보낸다.
    5. CS를 high로 만들어 종료한다.
  • 위 그림의 메모리는 address line이 26개이므로 2^24 == 64MB이고 data line은 8개이므로 주소당 1-byte를 저장할 수 있는 메모리다.
    • 하지만, ARM core는 address line은 32개, data line도 32개를 가지고 있기 때문에 이런 메모리를 사용하기 위해서는 address line을 24개로, data line은 8개로 바꿔주는 회로가 필요하다.
    • 바로 이 역할을 memory controller가 해준다.
    • Memory controller는 ARM core의 address line의 LSB 24-bit만 사용하고, data line의 LSB 8-bit만 사용해서 메모리에 접근할 수 있도록 도와준다.
    • 만일 메모리를 하나 더 추가하거나 기존 메모리를 변경해서 128MB 구성이 된다면, controller 속의 bus sizer 레지스터를 제어해서 address line의 bit를 1개만 더 사용하도록 만들면 된다.

1.3. LCD

  • 지금까지 배운 내용을 토대로 LCD 인터페이스를 제어하는 방법에 응용해보자.
  • 어떤 MCP의 datasheet 속 memory map을 확인해보니 address 0x2000_0000부터 3MB 크기가 LCD_CS_N이라는 이름으로 선언돼있었다.
    • _N이라는 접미사가 붙은 것으로 보아 이 device의 CS핀은 low active임을 예측할 수 있다.
    • 3MB이므로 0x2000_0000 ~ 0x202F_FFFF영역이 LCD를 위한 영역임을 알 수 있다.

  • 이제 datasheet를 넘겨서 LCD controller에 대한 회로를 설명하는 부분으로 넘어가보자.
    • 이 controller는 특이하게도 address line의 7번 bit를 통해 command/ data 여부를 결정한다.
    • CS와 WD 그리고 RD는 모두 low active이고, 16개의 data line을 주고받는다.
  • 위 정보들을 습득했으면 이제 SW개발자는 LCD를 제어할 수 있는 최소한의 정보를 얻은 것이다.
; Command Issue
LDR     R0, #0x20000080 ; A[7] = HIGH
LDR     R1, #0xABCD     ; 명령을 보냄
STR     R1, [R0]

; Data Issue
; Command Issue
LDR     R0, #0x20000000 ; A[7] = LOW
LDR     R1, #0x1234     ; 데이터를 보냄
STR     R1, [R0]
  • 어셈블리로 작성하면 위와 같다.
  • Address line의 7번 bit를 통해 command를 보낼지, data를 보낼지 결정한다.
  • 위 어셈블리를 C언어로 작성하면 아래와 같다. ([※] #define 문 MACRO 테크닉은 3.2절에서 다룹니다.)
#define Main_LCD_Write_cmd (cmd)   (*(volatile word *)(0x200000080) = cmd
#define Main_LCD_Write_data (data)   (*(volatile word *)(0x200000000) = data
 
Main_LCD_Write_cmd (0xABCD);
Main_LCD_Write_data (0x1234);

 

 

 

'하드웨어 해킹 및 임베디드' 카테고리의 다른 글

Bluetooth 공격 기법  (0) 2023.06.30
ISO 21434 CAL Level  (0) 2023.06.29
Car Hacking Training  (0) 2023.05.18
SecOC(Secure On-board. Communication)  (1) 2023.05.16
Embedded Recipes  (0) 2023.04.11
블로그 이미지

wtdsoul

,

https://grayhash.com/html/Training_Desc.html?subject=CarHacking 

 

Offensive Security Research Center 그레이해쉬 홈페이지에 오신 것을 환영합니다.

    * 이**정리할 내용이 많아서 정리하느라 인제야 후기를 올리네요. ㅜ 결론부터 말하면 다년간 자동차 해킹을 연구하신 강사님의 노하우를 들을 수 있는 정말 좋은 강의라 강력히 추천해 드

grayhash.com

 

 

https://koreascience.kr/article/JAKO202006763002831.pdf

https://repository.pknu.ac.kr:8443/bitstream/2021.oak/13803/2/%EC%BB%A4%EB%84%A5%ED%8B%B0%EB%93%9C%20%EC%B9%B4%EB%A5%BC%20%EC%9C%84%ED%95%9C%20CAN%20%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%20%EC%B9%A8%EC%9E%85%20%ED%83%90%EC%A7%80%20%EA%B2%80%EC%B6%9C%20%EB%B0%A9%EB%B2%95%EC%97%90%20%EA%B4%80%ED%95%9C%20%EC%97%B0%EA%B5%AC.pdf

'하드웨어 해킹 및 임베디드' 카테고리의 다른 글

ISO 21434 CAL Level  (0) 2023.06.29
Chapter 7. Device control  (0) 2023.06.25
SecOC(Secure On-board. Communication)  (1) 2023.05.16
Embedded Recipes  (0) 2023.04.11
ELF format Object File에 관한 진실  (1) 2023.03.14
블로그 이미지

wtdsoul

,

Key 보안 없는 사이버 보안 없다 (autoelectronics.co.kr)

 

Key 보안 없는 사이버 보안 없다

사이버어택으로부터 차를 보호하기 위해 해당 키 자료에 기초한 암호화 방식이 사용되고 있다. 하지만 키 관리를 통해 해결해야 할 문제는 무엇인가? AUTOSAR 표준화를 통해 어떤 이점을 실현할

www.autoelectronics.co.kr

 

최근 몇 년 동안 보안 관련 기능이 차량에 탑재돼 왔다. 예를 들어 자동차 도난방지 장치와 ECU의 보안 프로그래밍에 암호화 및 서명 확인 등과 같은 암호화 방식이 활용되고 있다. 커넥티비티에 관한 지속적인 트렌드는 차량이 지원하는 기능의 범위를 확장하는 것이다. 예를 들어 무선(OTA) 소프트웨어 업데이트, 원격 기능 활성화 및 차량과 인프라 간 통신(V2X) 등이 있다. 이러한 유스케이스를 통해 자동차 업계에는 흥미롭고, 매우 유망한 비즈니스 모델이 탄생한다. 하지만 연결 수가 증가할수록 차량에 대한 잠재적인 사이버 공격수 또한 증가한다.

키: 사이버 보안의 기초
사이버 공격 위험에 대응하기 위해 자동차 업계는 자동차 업계 고유의 보안조치를 구현하며 기존의 IT 보안 분야의 프로토콜을 배포하고 있다. 예를 들어 AUTOSAR의 표준화된 SecOC(보안 온보드 통신)[1]은 ECU와 차량 네트워크 내 ECU 간 통신을 보호한다. 버스 기술과 특정 애플리케이션, 예를 들어 IT 분야에서 자주 언급되는 TLS(전송 계층 보안)와 IPSec(인터넷 프로토콜 보안) 프로토콜이 사용될 수 있다. 모든 최신 보안 메커니즘에서 공유돼야 할 한 가지 특징은 사용된 암호화 알고리즘 세부사항의 기밀성이 아니라 사용된 키의 기밀성에 기초한다. 보안을 더 많이 개선하기 위해 주어진 키는 한 개의 보안 메커니즘에만 사용될 수 있다.

사이버 보안 애플리케이션 수가 점점 증가함에 따라 많은 ECU에서 비밀 키, 개인/공용 키 페어 및 인증서 같은 대량의 암호화 자료가 안전하게 저장돼야 할 필요성이 대두되고 있다. 이러한 맥락에서 키 저장과 차량 키 관리에 대한 개념이 종종 사용된다. 키 저장과 차량 키 관리 개념 간 차이점은 아래에서 설명한다.


암호화 키를 안전하게 저장하기
최근 몇 년 동안 사이버 보안에 대한 표준화가 발전했다. 마이크로컨트롤러의 특수 하드웨어 장치인 HSM(하드웨어 보안 모듈)을 사용하면 키를 안전하게 저장하고, 암호화 계산 속도를 높일 수 있다.
AUTOSAR 컨소시엄은 키를 모델링하고, 암호화 스택을 사용하기 위해 베이직 소프트웨어 내의 암호화 스택을 표준화했다[2](그림 1). 그리고 소프트웨어 기반 라이브러리 또는 HSM에서 제공하는 보안 기능 액세스용의 표준화된 인터페이스를 제공한다(그림 2). 이러한 소프트웨어와 하드웨어의 조합을 통해 ECU에 키 자료를 효율적이고, 안전하게 저장할 수 있다.


그림 1|AUTOSAR 암호화 스택의 목적은 키를 모델링해 암호화 서비스를 사용하는 것이다.


그림 2|하드웨어 보안 모듈(HSM)의 아키텍처



암호화 키의 라이프 사이클
차량에서 키의 사용은 일반적인 일상 작동 모드로 제한되지 않는다. 키 관리에 대한 주제 또한 다음의 차량 라이프 사이클 단계에서 고려돼야 한다(그림 3).

1. ECU 개발: ECU에 초기 키를 저장한다.
2. 차량 통합: 초기 키를 개발 키로 대체한다.
3. 차량 생산: 초기 또는 개발 키를 생산 키로 대체한다. 그리고 종종 외부 소스의 다른 키 자료를 설치하거나 해당 차량에 존재하는 키로부터 다른 키 자료를 얻어야 한다. ECU 간에 비밀 키가 공유될 경우 이러한 키의 기밀성과 무결성은 항상 보장돼야 한다. 예를 들어, 비밀키는 버스를 통해 일반 텍스트로 결코 전송되서는 안 된다.
4. A/S와 서비스 해제: 추가 키 자료 업데이트 또는 설치는 원격 기능 활성화에도 적합한 새 키가 필요할 때에 요구될 수 있다. 또한, 결함이 있는 ECU를 교체할 경우 결함이 있는 ECU에서 어떠한 방법으로도 중요한 키 자료를 읽거나 조작할 수 없도록 조치를 취해야 한다. 그리고 기능이 실행될 수 있도록 새 ECU에 적합한 키 자료가 제공돼야 한다.



그림 3|전체 차량 라이프 사이클 동안 키를 관리한다.



키 관리 전략
다양한 키 관리 전략을 잘 보여주는 적용사례는 SecOC이다. SecOC은 ECU 간 차량 내 통신을 검증하는 데 사용된다. SecOC는 메시지 수신자에게 기록된 메시지의 재생을 감지하고, 메시지 발송자의 신뢰성을 확인하고, 전송된 데이터의 무결성을 평가하는 기능을 제공한다. 이를 위해 수신자는 MAC(메세지 인증 코드)라고 알려진 암호화 체크섬을 확인한다. MAC은 기본적으로 발송자가 생성하고 수신자가 유효성을 확인하는 데 사용된다. MAC 확인이 실패하면 수신자는 메시지를 거부한다. 성능상의 이유로 대칭 암호화 알고리즘을 MAC를 계산하는 데 사용한다.

이러한 방법에서 메시지 발송자와 모든 수신자는 MAC를 생성 및 확인을 위해 같은 키를 사용한다. 이 키는 전체 라이프 사이클 동안 기밀이 유지돼야 한다. 따라서 내부 차량 네트워크 또는 차량 외부의 네트워크를 통해 보호되지 않는 상태로 메시지가 전송되서는 안 된다.
다음 예제의 핵심은 생산하는 동안 키 생성 및 설치이다. 이러한 다른 전략은 본 문서에는 평가되지 않지만 유스케이스가 같을 경우에도 실제로는 키 관리에 대한 다른 많은 솔루션이 있음을 알 수 있다. 이 예제에서는 키 자료는 SecOC를 위해 생성 및 배포된다.


오프보드에서 생성된 키
한 가지 전략은 SecOC에 필요한 키를 생성하는 오프보드 키 관리 서버를 보유하는 것이다. 오프보드 키 관리 서버에는 차량에 설치된 ECU에 대한 정보와 SecOC 키에 대한 요구사항이 포함돼 있어야 한다. ECU는 차량이 생산되는 동안 필요한 키를 가져온다. 이들 키는 기밀이므로 전송하는 동안 암호화를 통해 보호돼야 한다. 수신 ECU에서는 키를 저장하기 전에 키의 신뢰성과 무결성을 확인한다.


코디네이터가 있는 상태에서
온보드에서 생성된 키

이 전략의 경우 생산 과정 동안 테스터에서 SecOC 키가 생성될 수 있도록 인증된 요청을 만들어 생성하고, 조정을 담당하는 ECU에 전송한다. 첫 번째 단계에서 조정 담당 ECU는 일반적인 자동차별 키를 생성한다. 그리고 이 ECU는 각 대상 ECU에 임시 보안 연결을 설정하기 위해 키 계약 프로토콜을 사용하고, 미리 생성된 키를 전송한다. 이 키와 키 파생 규격에 기초하여 각 대상 ECU는 적합한 SecOC 키를 생성한다. 키 계약 프로토콜은 다소 긴 실행 시간이 필요하므로 키를 생성 및 배포하는 데에만 사용된다. 모든 대상 ECU는 방금 생성된 키를 사용하여 SecOC를 통해 서로 안전하고, 효율적으로 통신한다. 그리고 모든 대상 ECU는 새 키를 배포하지 않고 이러한 작업을 수행한다.


코디네이터 없이 온보드에서 생성된 키
또한 여기에서 SecOC의 주요 자료가 온보드에서 생성된다. 하지만 키 생성 요청은 조정 기능 담당 ECU에 전송되지 않고, ECU 그룹에 직접 전송된다. 개별 ECU는 그룹의 구성원을 인지하고, 여러 단계의 키 계약 프로토콜을 시작한다. 그룹 구성원은 버스를 통해 이 키를 실제로 전송하지 않고 공유된 키가 생성되도록 메시지를 교환한다. 그룹의 모든 ECU가 공유된 키를 계산하자마자 각 그룹 구성원은 키 파생 규격에 기초하여 필요한 SecOC 키를 생성한다.


표준화 상태
이전에는 키 관리에 대한 표준이 없었지만 솔루션이 필요했으므로 자동차 OEM은 개별 접근 방식을 따랐다. 같은 유형의 문제를 해결하기 위해 이러한 다른 접근 방식을 개발 및 유지관리하면 관련된 모든 이해 당사자에게 추가 비용이 발생한다. 또 다른 고려사항은 키 관리가 일반적으로 경쟁적이고, 차별화된 제품 특성이 아니라는 점이다. 이러한 최적화의 가능성은 AUTOSAR 4.4 Security Extensions에서 인식돼 활용됐다. 키 관리 전용 모듈 KeyM[3]이 지정되었다(그림 4). 이 모듈은 두 개의 하위 모듈인 암호화 키와 인증서로 구성돼 있다.

암호화 키 하위 모듈은 협상 키에 필요한 기능을 제공한다. 이러한 프로세스는 다른 단계로 세분화된다. 마지막 단계에서 키 자료는 ECU의 HSM에서 암호화 스택을 통해 파생 및/또는 저장될 수 있다. 위에서 설명한 문제로 인해 자동차 OEM에서 정의하는 논리가 KeyM 모듈에 구현되지 않는다. 대신 키 Key Handler(키 처리기)라는 소프트웨어 구성요소에 구현된다(그림 4).
인증서 하위 모듈은 인증서 구문 분석, 확인 및 설치 기능을 제공한다. 애플리케이션에서 추가 처리를 위해 인증서의 정의된 요소 값을 읽을 수 있다. 마지막 단계에서 인증서는 ECU의 NVM(비휘 발성 메모리) 또는 HSM에 저장된다.



그림 4|AUTOSTAR에서 키 관리는 두 개의 하위 모듈 암호화 키와 인증서가 포함돼 있는 KeyM 모듈에서 구현된다.


표준화의 문제
키 관리는 OEM과 공급업체의 개발, 생산 및 A/S 프로세스와 밀접하게 연관돼 있다. 몇몇 기능에 대한 키 자료가 최근 몇 년 동안 이미 사용돼 왔고, 공개 키 인프라(PKI) 및 키 서버 같은 일부 IT 인프라가 이미 존재한다. OEM은 기존 인프라를 재사용하는 경향이 있으므로 표준화 가능성은 제한된다. 기존의 또는 계획된 인프라 또한 암호화 키를 생성하기 위해 온보드 또는 오프보드 방법을 선택할지 여부에 영향을 미친다. 그리고 키 관리 또한 자동차 OEM이 정의하는 보안 목표의 영향을 받는다. 이러한 목표는 개발, 생산 및 서비스 환경의 보안에 대한 가정 같은 다양한 요소에 기초한다. 예를 들어 사내 생산 환경이 안전하다고 가정할 수 있는지에 대한 의견차가 발생한다. 이러한 가정은 생산하는 동안 그리고 A/S 시 보호 조치에 직접적인 영향을 미친다.

생산력 요구사항 또한 키 관리에 영향을 미친다. 예를 들어 모든 차량의 ECU의 키를 전송하는 데 몇 초만 사용할 수 있을 경우 키 관리 전략을 새로 설계해야 한다.
표준화 시 발생한 변형의 수 감소
암호화 알고리즘과 관련 키 자료는 차량의 최신 보안 메커니즘의 기초를 형성한다. 이러한 알고리즘은 사이버 공격에 대비하여 혁신적인 기능과 기존의 비즈니스 모델을 보호하는 데 사용된다.
표준화를 향한 초기 단계는 AUTOSAR 4.4에 도입된 KeyM 모듈이다. KeyM 모듈은 특정 키 관리 전략을 표준화하지 않고, 다양한 전략 구현에 필요한 일반적인 인터페이스를 제공한다. 자동차 커뮤니티는 키 관리 전략을 조화시키는 데 더욱 집중해야 한다. 이를 통해 관련 전략의 키 처리기를 표준화해 실질적으로 변형의 수를 감소시킬 수 있다. 그리고 높은 수준의 표준화로 비용과

 

참고문헌
[1] AUTOSAR 4.3 WP-X-SEC (2016), Requirements on Module Secure Onboard Communication
[2] AUTOSAR 4.3 WP-X-SEC (2016), Requirements on Crypto Stack
[3] AUTOSAR 4.4 WP-X-SEC (2018), Specification of Key Manager


에두아르드 메츠커(Eduard Metzker)  벡터의 사이버 보안 솔루션의 프로덕프 매니저. MICROSAR 베이직 소프트웨어의 보안 메커니즘을 정의했다. AUTOSAR의 수많은 보안 메커니즘을 정의한 AUTOSAR 4.4 Security Extensions 컨셉 그룹을 이끌고 있다.
팔코 K. 바프(Falco K. Bapp)  벡터의 하드웨어 보안 모듈용 소프트웨어인 vHSM의 프로덕트 매니저. vHSM의 아키텍처와 기능 범위를 정의했다.
안토니오 알메이다(Antonio Almeida)  보안 거버넌스 영역의 프로덕트 매니저. 자동차 보안 표준의 개발 프로세스 적합성을 관리한다.

 

출처: AEM (https://www.autoelectronics.co.kr)

'하드웨어 해킹 및 임베디드' 카테고리의 다른 글

Chapter 7. Device control  (0) 2023.06.25
Car Hacking Training  (0) 2023.05.18
Embedded Recipes  (0) 2023.04.11
ELF format Object File에 관한 진실  (1) 2023.03.14
STM32 보드 임베디드 진행 전  (0) 2023.02.19
블로그 이미지

wtdsoul

,

3. software 6-10

page : 175

http://download.savannah.gnu.org/releases/tinycc/

 

Index of /releases/tinycc/

 

download.savannah.gnu.org

https://velog.io/@embeddedjune/%EC%9E%84%EB%B2%A0%EB%94%94%EB%93%9C-%EB%A0%88%EC%8B%9C%ED%94%BC-%EC%9A%94%EC%95%BD-%EB%B0%8F-%EC%A0%95%EB%A6%AC-Chapter-3.-SW-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%A1%9C%EB%93%9C

 

[임베디드 레시피 요약 및 정리] Chapter 3. SW ① :: 컴파일~로드

Endian을 이해하지 못하면, 디버깅 시에 오류에 빠질 수 있으니 꼭 이해해야 한다.(※ 정말 endian 중요합니다. 설령 배웠더라도 정말 햇갈리기 쉬운 개념이라 꼭 10분~20분 시간내서 정확하게 뇌에서

velog.io

 

 

https://rasino.tistory.com/307#google_vignette

 

【 C 환경설정 】 VS code에서 C/C++ 코딩환경 구축하기

【 C 환경설정 】 VS code에서 C/C++ 코딩 환경 구축하기 요즘 파이썬(python)이나 자바(JAVA), javascript C# 등등 하이레벨 언어를 학습하던 사람들이 프로그래밍의 근간을 튼튼히 한다거나? 여러 가지 이

rasino.tistory.com

ADS는 ARM사에서 파는 ARM Developer's Suit 이다.

1. Little Endian과 Big Endian

  • Endian을 이해하지 못하면, 디버깅 시에 오류에 빠질 수 있으니 꼭 이해해야 한다.
    ([※] 정말 endian 중요합니다. 설령 배웠더라도 정말 햇갈리기 쉬운 개념이라 꼭 10분~20분 시간내서 정확하게 뇌에서 재정립하고 진행하시는게 좋습니다.)
  • 0x12345678이라는 dword 데이터를 저장한다면,
    • Little endian은 MSB가 상위주소에 저장된다. [0] = 0x78, [1] = 0x56, [2] = 0x34, [3] = 0x12
    • Big endian은 MSB가 하위 주소에 저장된다. [0] = 0x12, [1] = 0x34, [2] = 0x56, [3] = 0x78
  • Big endian은 사람이 읽기 쉬운 형태고, little endian은 ARM processor가 읽기 쉬운 형태다.
    ([※] 개인적으로는 저 [0], [1], [2], [3]을 어떻게 배열하냐에 따라(내림차순, 오름차순, 위로 쌓기, 아래로 쌓기 등) 인상이 확확 달라져서 MSB가 이름의 반대로 저장(little은 상위주소, big은 하위주소)된다고 외웁니다.)
  • 따라서 ARM processor는 default로 little endian을 사용한다. 하지만, co-processor 15번 CP15의 CR 레지스터를 설정해서 big endian으로 동작하도록 설정 가능하며 컴파일 할 때도 설정할 수도 있다.

2. 컴파일 (Compile)

2.1. 컴파일이란?

  • 우리는 chapter 1에서 CPU는 단순히 약속된 bit pattern을 약속된 절차에 따라 수행할 뿐이라고 배웠다.
  • 단, 이 bit pattern(native code, 기계어)은 사람이 읽기에 너무 불편하기 때문에 사람이 그나마 읽을만한 1:1 매칭이 되는 표기법을 만든게 어셈블리(assembly, mnemonic)다.
  • 그리고 이 1:1매칭을 자동으로 해주는 ‘어셈블러’를 만들었다.
  • 하지만, 프로세서마다 약속된 bit patten이 달라서 프로그램을 만들어도 프로세서 A에서는 동작하지만, B에서는 동작하지 않는 문제가 발생했다.
  • 서로 다른 프로세서에 맞는 어셈블리를 만들어주는 편리한 존재에 대한 수요가 증가했고, 그렇게 개발된게 컴파일러다.
  • 컴파일러는 C/C++같은 high level language로 코드를 만들면, 각 프로세서에 약속된 bit pattern으로 매칭될 수 있는 어셈블리를 만들었고, 어셈블러는 1:1 매칭을 수행해 적절한 기계어를 만들 수 있게 됐다.
  • 결국 사람은 프로세서의 동작 원리나 약속같은건 신경쓰지 않고 그냥 C/C++로 프로그램을 개발하면 됐다.
  • 크로스컴파일(Cross-compile)은 타겟보드의 프로세서(ARM)와 우리가 사용하는 host PC의 프로세서(x86-64)가 다르기 때문에 타겟보드에서 동작할 수 있는 바이너리를 host PC에서 생성하는 일련의 과정을 말한다.

2.2. 컴파일 과정

  • 위 그림은 전체 컴파일 과정을 나타내며 간략하게 설명하면 다음과 같다.
    1. 전처리기(Preprocessor)가 컴파일을 쉽게 할 수 있도록 헤더파일과 매크로를 소스파일에 옮기는 최적화 작업을 수행하고 결과물로 .i파일을 만든다.
    2. 컴파일러 .i 파일을 컴파일 해 .s 어셈블리를 만든다.
    3. 어셈블러 .s 어셈블리를 .obj 목적파일(object file)로 만든다.
    4. 링커가 여러 .obj 파일과 라이브러리(.lib)을 묶고 엮어 하나의 실행 가능한 ELF(Executable & Loadable File)형식의 .elf 파일로 만든다. 이때 scatter loading 파일.scl또는 링커 스크립트(Linker script) .ld 를 통해 개발자가 원하는 메모리 구성을 가지도록 링커에게 정보를 줄 수도 있다.
    5. fromelf 또는 objcopy 같은 유틸리티를 사용해 최종 실행 바이너리 .bin 파일을 만든다.

2.3. 컴파일 실습 ①

[※] 본문에서는 ADS를 이용해 armcc 명령어와 tcc 명령어 등을 사용해서 컴파일 및 링크를 합니다. 하지만, 저를 포함해서 많은 분께서는 GNU의 ARM GCC 밖에 구할 수 없기 때문에 저도 GNU의 ARM GCC를 이용해서 실습했습니다.

#define TRUE 1
typedef struct {
  char memberBool;
  int memberInt;
  char memberWord;
} memberType;

extern int add(int a, int b);
#include "spaghetti.h"

int zi = 0;
int rw = 3;
extern int relocate = 3;
extern structure recipes[3];
int add(int a, int b);

int main() {
    int stack;
    volatile int local1, local2, local3;
    
    local1 = 3;
    local2 = 4;
    local3 = add(local1, local2);
    stack += local3;
    
    return stack;
}

int add(int a, int b) {
    return (a + b);
}

[※] 위와 같이 본문의 코드를 입력한 뒤 각각 spaguetti.c와 spaghetti.h로 저장했습니다. (아참, 본문 코드랑 다르게 #define EQUAL = 안 하고 그냥 = 쓴 이유는, 그렇게 하면 이상하게 컴파일이 안 되서 불가피했습니다.)

  • arm-none-eabi-gcc -E 옵션을 통해 전처리를 수행한 결과입니다. 헤더파일 및 define 했던 것들이 코드에 들어가 적용된 모습을 볼 수 있습니다. 이렇게 단일 소스파일에 합쳐져 컴파일을 수월하게 해주는 게 전처리기의 역할입니다.
  • -S 옵션을 통해 컴파일 후 어셈블리 파일만 뽑아낼 수 있습니다.
  • R2에 3을, R3에 4를 집어넣는 모습을 보아 코드의 local1이 R2에, local2가 R3에 저장된 것을 알 수 있습니다.
  • 스택이 0x16만큼 감소합니다 (상위주소 → 하위주소). 현재 main()에 지역변수가 4개있고 int형이므로 각각 4-byte씩 총 16-byte를 차지하기 때문입니다. STR 명령어를 통해 값을 저장합니다.
  • LDR 명령어로 불러온 뒤 두 값을 더하고 최종결과를 AAPCS에 따라 R0에 저장합니다. 이제 스택에 저장된 값들은 필요없으므로 다시 0x16을 더한 뒤 return 합니다.
  • Return 할 때는 LR이 가리키는 주소로 갑니다.
  • 이 컴파일은 O2옵션을 줬기 때문에 add() 함수에 대한 최적화가 자동으로 이뤄졌습니다. 함수 호출 부분에서 최적화가 발생했음을 알 수 있습니다.

3. 링커(Linker)와 ELF

3.1. 변수의 생애주기

  • auto
    • 지역변수에 해당하며 블록 또는 함수 범위 내에서 선언돼 실행흐름이 범위를 벗어날 때 사라진다.
  • extern
    • Global변수에 해당하며 선언 이후 파일 끝까지 전체에서 사용할 수 있다.
    • 프로그램 전체에서 사용 가능할 뿐만 아니라 다른 파일에서도 불러다 사용할 수 있다.
  • static
    • 위 auto, extern 변수 모두 static 선언이 가능하며 다른 의미를 가지게 된다.
    • static auto의 경우 범위를 벗어나도 그 값을 유지한다. 단, 범위를 벗어난 경우에는 사용할 수 없다.
    • static extern의 경우 프로그램 전체에서 사용 가능한 건 변함 없지만, 다른 파일에서는 불러서 사용할 수 없다.
    • 따라서 static 선언은 값은 유지하되 범위는 국한시키는 속성을 부여해 C++의 protected와 비슷하다.
  • volatile
    • 컴파일러는 옵션에 따라 자동으로 연산을 최소화하는 방향으로 최적화를 수행한다.
    • 이러한 최적화가 되려 개발자의 의도에 맞지 않게 실행흐름을 변경시키는 결과를 초래하기도 한다.
    • 예를 들어, 같은 주소에 대한 연속적인 data write을 하는 burst transfer 중인 device가 있다고 할 때, 컴파일러가 최종값만 write 하도록 최적화 해버리면 중간과정의 data들이 유실되는 사고가 발생한다.
    • 이런 경우를 방지하기 위해 volatile 선언을 통해 컴파일러로 하여금 '이 변수에 대해서는 최적화를 하지 말고 코딩된 그대로 실행하라'라고 명령한다.

3.2. Symbol과 영역

3.2.1. Symbol이란?

  • Symbol이란, 메모리에 자신만의 고유 주소를 갖게 되는 단위를 말하며 링커가 인식할 수 있는 기본 단위다.
    • Symbol == global 이라는 뜻을 가진다고 이해해도 된다. 함수, 전역변수, static 변수는 고유 주소를 갖기 때문에 소스파일 내 어디에서도 참조가 가능한 것을 떠올리면 쉽게 납득할 수 있다.
    • 반면, 지역변수는 고유 주소를 갖고 있지 못하기 때문에 루틴이 종료됨에 따라 사라진다.
  • 링커는 각 symbol과 symbol의 시작주소를 table에 저장하고 관리한다. 이 table은 컴파일 후 결과물로 나오는 .o 오브젝트 파일에서 확인할 수 있다.

3.2.2. 영역 구분 (RO, RW, ZI) (.text, .data, .bss)

  • Symbol은 내부적으로 3가지 종류로 나뉘는데, 각 종류에 따라 메모리에 올라가는 영역도 달라진다.
    • Read only (RO, .text)
      • 읽기만 가능하고 수정할 수 없는 symbol을 의미한다.
      • 대표적으로 const형으로 선언된 전역변수라던지, 소스코드 자체를 의미한다.
      • 이 종류에 속하는 symbol은 메모리의 RO영역 또는 .text라고 부르는 영역에 속한다.
    • Read Write (RW, .data)
      • 읽기와 쓰기가 가능해 수정할 수 있는 symbol을 의미한다.
      • 대표적으로 초기화 된, 초기화 값이 있는 전역변수가 여기에 속한다.
      • 이 종류에 속하는 symbol은 메모리의 RW영역 또는 .data라고 부르는 영역에 속한다.
    • Zero Initialized (ZI, .bss)
      • 이름 그대로 0으로 초기화되는 symbol을 의미하며 대표적으로 초기값이 없는 전역변수가 여기 속한다.
      • 이 종류에 속하는 symbol은 메모리의 ZI영역 또는 .bss라고 부르는 영역에 속한다.
      • [※] C/C++로 코딩테스트 준비해보신 분들은 아시겠지만, 전역변수로 초기값 안 주고 코딩하는 경우가 많으실 겁니다. 자동으로 0으로 초기화해주기 때문에 편하게 사용하셨을 탠데요, 이런 변수들이 다 ZI 영역(.bss)입니다.
  • 어떤 영역에 속하냐에 따라 저장되는 위치도 달라진다.
    • RO영역은 항상 그 값을 유지하고 있어야 하고 수정될 일도 없으므로 ROM(Flash memory)에 저장된다.
    • RW영역은 초기값을 가지고 있어야 하므로 ROM에 저장된다. 또한, 명령어에 따라 수시로 수정이 이뤄져야 하므로 RAM에도 있어야 한다.
    • ZI영역은 메모리에서 0으로 초기화 될 것이므로 ROM에 저장할 필요가 없고 RAM에 저장된다.
  • 개발자는 각 영역의 시작주소와 길이에 대한 정보를 링커에게 전달해서 원하는 주소에 영역을 위치시킬 수 있다.
  • 이 정보를 담고있는 파일을 Scatter loading 파일 또는 linker script(링커스크립트)라고 부른다.

3.3. ELF format object file

  • 컴파일 후 결과물인 .obj 오브젝트 파일은 ELF 형식을 따른다.
  • 오브젝트 파일은 relocatable object file executable object file로 나뉜다.
    • 여러 소스파일이 있을 때,각 소스파일을 컴파일 하면 각각에 대한 오브젝트 파일이 나올 것이다.
    • 각 소스파일이 다른 소스파일에 있는 extern변수 또는 함수를 가져와서 사용한다고 가정하자. 그러면, 현재 컴파일 된 소스파일에는 해당 변수나 함수에 대한 정보가 없기 때문에 컴파일러는 구멍을 뚫어놓고 ‘링커야, 나중에 다른 파일에서 대응하는 symbol을 찾아서 구멍을 매꿔줘’라고 표시한다.
    • 이렇게 구멍이 뚫려있는 상태인, 나중에 링커를 통해 재배치가 가능한 오브젝트 파일을 relocatable 오브젝트 파일이라고 부른다.
    • 만일, 오브젝트 파일이 2개 이상이고 링크 과정을 거쳐야 한다면 -c 옵션을 통해 링커가 link 하지 못하게끔 해서 relocatable object file을 만들어야 한다.
  • 오브젝트 파일은 크게 다음과 같은 4가지 section으로 구성된다.
    1. ELF Header
    2. Code section (RO, .text, .rodata)
    3. Data section (RW, ZI, .data, .bss)
    4. Debug section (.debug, .line, .strtab, .symtab 등)
      • .symtab이 바로 symbol table이며 링크와 디버깅할 때 꼭 필요한 부분이다.
  • [※] objdump 유틸리티를 사용해서 relocatable object file 내부를 덤프한 모습입니다.
  • [※] 각 섹션의 .text 부분을 확인할 수 있습니다.
  • [※] 상대주소와 opcode 그리고 어셈블리 명령어를 한 눈에 보기 좋게 확인할 수 있습니다.
  • [※] readelf 유틸리티를 사용해서 relocatable object file의 가장 첫 부분인 'ELF 헤더'를 덤프한 모습입니다.
  • [※] 현재 object file의 종류가 REL(Relocatable file)이라는 점, ARM mode로 컴파일 된 점, 헤더 크기가 52Byte인 점 등을 확인할 수 있습니다. 본문 내용과 같네요!
  • [※] 본문에서 설명한 section들이 똑같이 들어있음을 확인할 수 있습니다.
  • Object file 속 symbol table의 모습이다.
    • Num은 링커를 위한 symbol의 번호다.
    • Value는 해당 symbol의 시작 offset 주소다.
    • Size는 symbol의 크기다. Function(함수), object(전역변수)가 아닌 경우는 0이다.
    • Type은 해당 symbol의 종류 (함수, 전역변수, section 등)를 나타낸다.
    • Bind는 해당 symbol의 scope를 의미함 Global, Local, Weak를 나타낸다.
    • Ndx는
      • UND: 현재 file에서 사용되고 있지만 define은 없는 symbol
      • ABS: Relocate 돼서는 안 되는 symbol
      • 1은 .text, 2는 .data, 3은 .bss를 의미한다.
  • [※] objdump로 확인해본 opcode가 little endian 형태로 .text에 저장돼있네요.
  • [※] 본문 내용대로 Header 이후 opcode가 나오는 것을 확인할 수 있었습니다.

3.4. 링커(Linker)

  • 우리는 앞서 symbol과 relocatable 오브젝트 파일의 내부 구조를 배웠다.
  • 이제 링커의 역할과 executable 오브젝트 파일까지 배워보며 마무리를 해보자.
  • 링커가 하는 역할은 다음 2가지로 요약할 수 있다.
    1. 여러 relocatable 오브젝트 파일들을 같은 section끼리 모아서 순서대로 정렬해 합친다.
    2. Symbol reference resolving을 수행한다.
      • 앞서 relocatable 오브젝트 파일에는 ‘구멍’이 뚫려 있을 수 있다고 표현했다.
        • 어떤 파일에 선언만 돼있고 사용하진 않은 변수라던가,
        • 어떤 변수나 함수를 불렀는데 그 파일에 없고 다른 파일에 extern으로 선언돼 있다던가
      • 이런 구멍들을 하나하나 찾아서 서로 연결해 매꿔주는 작업을 링커가 수행한다.
  • 이런 복잡한 작업을 수행하기 때문에 link 때 메모리와 시간을 많이 잡아먹는 것이다.

3.5. Scatter loading (Linker script)

  • 위 2.2절에서 링커에 대한 설명을 할 때 scatter loading(또는 linker script)를 통해 개발자가 ㅡ원하는 메모리 구성을 가지도록 링커에게 정보를 줄 수도 있다고 설명했다.
    • ADS에서는 sctter loading file이라고 부르고, GNU에서는 linker script라고 부른다.
  • 메모리를 개발자가 원하는 대로 구성할 때는 두 가지 관점에서 봐야 한다.
    • Load view : SW가 실행되기 전에 저장매체(ROM, Flash)에 저장돼 있을 때의 모습이다.
    • Execution view : SW가 실행되기 위해 메모리(SDRAM)에 로드됐을 떄의 모습이다.
  • 먼저, 앞서 RO, RW는 ROM에, RW, ZI는 RAM에 저장된다고 배웠는데, 프로그램이 실행되기 위해서는,
    • NOR Flash의 경우 XIP를 지원하므로 RW만 RAM에 로드하고 ZI를 할당해야 한다.
    • NAND Flash의 경우 XIP가 불가능하므로 RO, RW를 모두 RAM에 로드하고 ZI를 할당해야 한다.
  • 따라서 로드하는 과정이 들어가기 때문에 load view와 execution view는 메모리 구조가 달라지게 된다.
  • 그럼 위 개념을 가지고 scatter loading file을 작성해보자.
LOAD_REGION 0x0
{
  EXEC_REGION1 0x0
  {
    spaghettil.o (+RO)
  }
  EXEC_REGION2 0x8000
  {
    spaghettil.o (+RW)
  }
  EXEC_REGION3 0xA000
  {
    spaghettil.o (+ZI)
  }
}
  • 가장 바깥쪽 LOAD_REGION은 load view의 시작주소를 의미한다.
    • Load view에서는 시작주소부터 RO, RW를 차곡차곡 차례대로 저장한다.
  • 안쪽 EXEC_REGION1, 2, 3은 execution view이며 각각 RO, RW, ZI 영역의 시작주소를 의미한다.
    • 0x0번지부터 RO영역이, 0x8000번지부터 RW영역이, 0xA000부터 ZI영역이 시작됨을 링커에게 알린다.
    • 이때 RO영역과 Load view의 시작주소가 같다. 이를 Root region이라고 하는데, loading view와 execution view의 주소가 같은 영역을 말하며 scatter loading 파일에 꼭 하나씩은 있어야 한다.
블로그 이미지

wtdsoul

,

http://recipes.egloos.com/5010841

 

ELF format Object File에 관한 진실. -c option (기계어 세상)

ELF 하면, 요정 엘프가 생각이 납니다. 제가 난생처음 ELF format이라는 걸 알게 되었을 때, ELF format이 도대체 무엇일까 하고 몇 개의 검색 포털에서 ELF를 무작정 찾아본 적이 있었습니다. 정말 '아연

recipes.egloos.com

ELF format Object File에 관한 진실. -c option (기계어 세상)


ELF 하면, 요정 엘프가 생각이 납니다. 제가 난생처음 ELF format이라는 걸 알게 되었을 때, ELF format이 도대체 무엇일까 하고 몇 개의 검색 포털에서 ELF를 무작정 찾아본 적이 있었습니다. 정말 '아연하게도' 요정 엘프에 관한 것들이 왜 그리도 많이 나오던지, 원하는 것을 찾기가 힘들었습니다. 지금은 ELF format이라는 것이 검색로봇에 많이 검색되어 검색엔진에서 적당한 자료를 찾을 수 있는 것인지는 잘은 모르겠습니다. 그 당시에는 과연 ELF는 숭고한 요정과 같이 나랑은 거리가 먼 것일까 하고 결론 내어 버린 적이 있었습니다만... 검색엔진이란 참으로 편리하면서도 때로는 어이없다는 생각이 들고 말았습니다.
 
ELF는 Executable and Linking Format을 의미하며, 말 그대로 실행 가능한 그리고 링크를 하는 형식을 말합니다. 상당히 고무적인 표현이랄까 - 뭔가를 한다는 의미에서 - 하지만, 막연한 느낌이 드는 건 사실이지요. 그래서 말인데, 이번에는 compile 후에 나오는 ELF 형식을 따르는 .o (object file)을 분석해 보겠습니다. - 사실은 Assembler의 output임을 잊지 맙시다 -
 
spaghetti.c 를 object file로 만들려면 다음과 같이 합니다. (-c option은 tcc에게 linker로 하여금 link를 하지 말라는 의미 입니다. 그렇게 하면 최종 실행 가능한 file이 아니라, link가 가능한 object file로 만들겠지요. 이런 file을 relocatable file이라고 부르는데, 나중에 link를 통해서 재배치가 가능하다는 의미 입니다. 너무 뜬 구름 잡기 식인데, 쉽게 얘기하면,  relocatable이란, spaghetti.c만 컴파일 한 것이지, 아직 실행 가능하게 만든 건 아니라는 의미이지요. 결국 spaghetti.c를 Assembler에 통과시키고, 그것을 link가능하게 table형태로 만들어 놓은 것입니다) 다시 말해, ELF format Object file은 Assembler의 output 이지요.
 
tcc -c spaghetti.c
 
이렇게 하여 나온 output은 spaghetti.o 라는 파일인데, 이 파일은 인간이 알아볼 수 있는 형식으로 되어 있지 않습니다. 한번 열어 보도록 하겠습니다.
 
00000000h: 7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 ; ELF............
00000010h: 01 00 28 00 01 00 00 00 00 00 00 00 00 00 00 00 ; ..(.............
00000020h: 5C 03 00 00 00 00 00 02 34 00 20 00 00 00 28 00 ; \.......4. ...(.
00000030h: 0B 00 01 00 03 20 04 21 40 18 10 18 70 47 00 00 ; ..... 
.!@...pG..
00000040h: 03 00 00 00 03 00 00 00 28 00 00 00 FF FF FF FF ; ........(...
00000050h: 01 00 02 7C 0E 0C 0D 00 07 00 07 01 07 02 07 03 ; ...|............
00000060h: 08 04 08 05 08 06 08 07 08 08 08 09 08 0A 08 0B ; ................
00000070h: 07 0C 08 0E 0C 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000080h: 0A 00 00 00 54 68 75 6D 62 20 43 20 43 6F 6D 70 ; ....Thumb C Comp
00000090h: 69 6C 65 72 2C 20 41 44 53 31 2E 32 20 5B 42 75 ; iler, ADS1.2 [Bu
000000a0h: 69 6C 64 20 38 30 35 5D 00 00 00 00 2D 4F 32 20 ; ild 805]....-O2
000000b0h: 2D 49 43 3A 5C 61 70 70 73 5C 61 64 73 31 32 5C ; -IC:\apps\ads12\
000000c0h: 49 4E 43 4C 55 44 45 00 00 00 00 00 00 00 00 00 ; INCLUDE.........
000000d0h: 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ; ................
000000e0h: 00 00 00 00 02 00 05 00 04 00 00 00 0A 00 00 00 ; ................
000000f0h: 00 00 00 00 02 00 05 00 07 00 00 00 00 00 00 00 ; ................
00000100h: 00 00 00 00 04 00 F1 FF 11 00 00 00 00 00 00 00 ; ......?........
00000110h: 00 00 00 00 01 00 06 00 18 00 00 00 00 00 00 00 ; ................
00000120h: 00 00 00 00 03 00 06 00 1D 00 00 00 00 00 00 00 ; ................
00000130h: 00 00 00 00 01 00 07 00 26 00 00 00 00 00 00 00 ; ........&.......
00000140h: 00 00 00 00 03 00 07 00 2C 00 00 00 00 00 00 00 ; ........,.......
00000150h: 00 00 00 00 01 00 08 00 35 00 00 00 00 00 00 00 ; ........5.......
00000160h: 00 00 00 00 03 00 08 00 3B 00 00 00 00 00 00 00 ; ........;.......
00000170h: 00 00 00 00 03 00 05 00 41 00 00 00 00 00 00 00 ; ........A.......
00000180h: 00 00 00 00 01 00 09 00 50 00 00 00 00 00 00 00 ; ........P.......
00000190h: 00 00 00 00 00 00 F1 FF A0 00 00 00 00 00 00 00 ; ......??......
000001a0h: 00 00 00 00 22 00 00 00 B5 00 00 00 00 00 00 00 ; ...."...?......
000001b0h: 04 00 00 00 11 00 06 00 B8 00 00 00 00 00 00 00 ; ........?......
000001c0h: 04 00 00 00 11 00 07 00 BB 00 00 00 00 00 00 00 ; ........?......
000001d0h: 04 00 00 00 11 00 08 00 C4 00 00 00 00 00 00 00 ; ........?......
000001e0h: 0A 00 00 00 12 00 05 00 C9 00 00 00 00 00 00 00 ; ........?......
000001f0h: 00 00 00 00 12 00 00 00 D0 00 00 00 00 00 00 00 ; ........?......
00000200h: 00 00 00 00 12 00 00 00 00 24 74 00 24 64 00 72 ; .........$t.$d.r
00000210h: 65 63 69 70 65 73 2E 63 00 2E 62 73 73 24 37 00 ; ecipes.c..bss$7.
00000220h: 2E 62 73 73 00 2E 64 61 74 61 24 31 30 00 2E 64 ; .bss..data$10..d
00000230h: 61 74 61 00 2E 64 61 74 61 24 31 35 00 2E 64 61 ; ata..data$15..da
00000240h: 74 61 00 2E 74 65 78 74 00 43 24 64 65 62 75 67 ; ta..text.C$debug
00000250h: 5F 66 72 61 6D 65 31 00 42 75 69 6C 64 41 74 74 ; _frame1.BuildAtt
00000260h: 72 69 62 75 74 65 73 24 24 54 48 55 4D 42 5F 49 ; ributes$$THUMB_I
00000270h: 53 41 76 31 24 4D 24 50 45 24 41 3A 4C 32 32 24 ; SAv1$M$PE$A:L22$
00000280h: 58 3A 4C 31 31 24 53 32 32 24 7E 49 57 24 7E 53 ; X:L11$S22$~IW$~S
00000290h: 54 4B 43 4B 44 24 7E 53 48 4C 24 4F 53 50 41 43 ; TKCKD$~SHL$OSPAC
000002a0h: 45 24 50 52 45 53 38 00 4C 69 62 24 24 52 65 71 ; E$PRES8.Lib$$Req
000002b0h: 75 65 73 74 24 24 61 72 6D 6C 69 62 00 7A 69 00 ; uest$$armlib.zi.
000002c0h: 72 77 00 72 65 6C 6F 63 61 74 65 00 6D 61 69 6E ; rw.relocate.main
000002d0h: 00 5F 5F 6D 61 69 6E 00 5F 6D 61 69 6E 00 00 00 ; .__main._main...
000002e0h: 30 00 00 00 02 0B 00 00 34 00 00 00 02 0A 00 00 ; 0.......4.......
000002f0h: 00 2E 73 68 73 74 72 74 61 62 00 2E 73 79 6D 74 ; ..shstrtab..symt
00000300h: 61 62 00 2E 73 74 72 74 61 62 00 2E 63 6F 6D 6D ; ab..strtab..comm
00000310h: 65 6E 74 00 2E 74 65 78 74 00 2E 62 73 73 00 2E ; ent..text..bss..
00000320h: 64 61 74 61 00 2E 64 61 74 61 00 2E 64 65 62 75 ; data..data..debu
00000330h: 67 5F 66 72 61 6D 65 24 24 24 2E 74 65 78 74 00 ; g_frame$$$.text.
00000340h: 2E 72 65 6C 2E 64 65 62 75 67 5F 66 72 61 6D 65 ; .rel.debug_frame
00000350h: 24 24 24 2E 74 65 78 74 00 00 00 00 00 00 00 00 ; $$$.text........
00000360h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000370h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000380h: 00 00 00 00 01 00 00 00 03 00 00 00 00 00 00 00 ; ................
00000390h: 00 00 00 00 F0 02 00 00 69 00 00 00 00 00 00 00 ; ....?..i.......
000003a0h: 00 00 00 00 00 00 00 00 00 00 00 00 0B 00 00 00 ; ................
000003b0h: 02 00 00 00 00 00 00 00 00 00 00 00 C8 00 00 00 ; ............?..
000003c0h: 40 01 00 00 03 00 00 00 0D 00 00 00 00 00 00 00 ; @...............
000003d0h: 10 00 00 00 13 00 00 00 03 00 00 00 00 00 00 00 ; ................
000003e0h: 00 00 00 00 08 02 00 00 D6 00 00 00 00 00 00 00 ; ........?......
000003f0h: 00 00 00 00 00 00 00 00 00 00 00 00 1B 00 00 00 ; ................
00000400h: 01 00 00 00 00 00 00 00 00 00 00 00 84 00 00 00 ; ............?..
00000410h: 44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; D...............
00000420h: 00 00 00 00 24 00 00 00 01 00 00 00 06 00 00 00 ; ....$...........
00000430h: 00 00 00 00 34 00 00 00 0C 00 00 00 00 00 00 00 ; ....4...........
00000440h: 00 00 00 00 04 00 00 00 00 00 00 00 2A 00 00 00 ; ............*...
00000450h: 08 00 00 00 03 00 00 00 00 00 00 00 40 00 00 00 ; ............@...
00000460h: 04 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 ; ................
00000470h: 00 00 00 00 2F 00 00 00 01 00 00 00 03 00 00 00 ; ..../...........
00000480h: 00 00 00 00 40 00 00 00 04 00 00 00 00 00 00 00 ; ....@...........
00000490h: 00 00 00 00 04 00 00 00 00 00 00 00 35 00 00 00 ; ............5...
000004a0h: 01 00 00 00 03 00 00 00 00 00 00 00 44 00 00 00 ; ............D...
000004b0h: 04 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 ; ................
000004c0h: 00 00 00 00 3B 00 00 00 01 00 00 00 00 00 00 00 ; ....;...........
000004d0h: 00 00 00 00 48 00 00 00 3C 00 00 00 00 00 00 00 ; ....H...<.......
000004e0h: 00 00 00 00 00 00 00 00 00 00 00 00 50 00 00 00 ; ............P...
000004f0h: 09 00 00 00 00 00 00 00 00 00 00 00 E0 02 00 00 ; ............?..
00000500h: 10 00 00 00 02 00 00 00 09 00 00 00 00 00 00 00 ; ................
00000510h: 08 00 00 00                                     ; ....
 
음.................................... 음.. 상당히 뭔가 있어 보입니다만, 머리 속이 복잡해 지는군요. 인간의 눈으로는 모르는 것이 당연합니다. 이제부터는 기계어 세상이 되어 버렸으니까요. (ELF 규격을 따른) 이 숫자들의 연속인 것을 알아보려면, 앞에서 말한 ELF format에 대하여, 조금 알아야 합니다.
 
ELF에 대하여, 조금 알아보도록 하지요. ARM ELF specification을 인터넷에서 찾아보시면, (참고로 문서번호는 SWS ESPC 0003 B-02, 8 June, 2001 복잡하다 흡) 그 안에서 다음과 같은 그림을 찾으실 수 있으실 것입니다
.
 
  
두 가지의 view가 그려져 있는데, 별건 아니고, Linking View가 relocatable file의 형식입니다. 쉽게 말해서 Link하기전의 object file (.o)은 Linking View이고요, Link가 끝난 후에 완전한 실행 가능한 형태가 된 ELF 형식을 Execution View라고 부릅니다. (Link 하려고 보니까, 다른 object file하고 연결 하려고 여러 가지 정보들을 심어 놓은 것 뿐입죠. ) 위에서 만들어 낸 spaghetti.o는 위의 object file format중 Linking View를 따르고 있다고 봐야 합니다. 오, 별거 아닐 거 같다는 생각이 듭니다. 좀 더 파고 들어가자면, 예를 들어, ELF Header중 한 개만 분석해 보면 감이 팍팍 올 것입니다. 아래는 ELF Header가 어떻게 구성되어 있는가를 구체적으로 볼 수 있는 구조체 입니다. ELF Header에는 ELF file의 특징을 결정 짓는 Endian, 운영체제, CPU 정보들 더하기 내부의 각 Section의 시작 위치 (offset)과 크기 정보가 들어 있습니다. 많은 양의 member들이 있습니다만, 겁부터 집어먹으면 안됩니다. 딱 한 개만 해보면 다른 것도 다 똑같은 원리로 분석이 가능하니, 걱정은 전혀 붙들어 매시라니까요.
 
 
#define EI_NIDENT 16
typedef struct {
        unsigned char e_ident[EI_NIDENT];
        Elf32_Half e_type;
        Elf32_Half e_machine;
        Elf32_Word e_version;
        Elf32_Addr e_entry;
        Elf32_Off e_phoff;
        Elf32_Off e_shoff;
        Elf32_Word e_flags;
        Elf32_Half e_ehsize;
        Elf32_Half e_phentsize;
        Elf32_Half e_phnum;
        Elf32_Half e_shentsize;
        Elf32_Half e_shnum;
        Elf32_Half e_shstrndx;
} Elf32_Ehdr;
 
이중에서 가장 만만해 보이는 걸 하나 잡아 봅시다. 맨 앞에 e_ident는 (IDENTIFICATION)은 재미 없어 보이니까, 그 다음에 보이는 e_type을 분석해 보기로 마음먹고 자자 레츠고. Object file이 시작하게 되면, 16 byte의 e_ident를 지나 Elf32_Half e_type을 만나게 됩니다. Elf32_Half는 눈치 채신 바와 같이 32 bit의 반, 16 bit이며, 이는 2 byte를 의미합니다. 그리고, ARM Elf specification을 찾아보니, e_type은 다음과 같은 값들을 가질 수 있습니다.
 

- e_type :  
 ===============================================
   Name         Value           Meaning
===============================================
  ET_NONE        0            No file type
  ET_REL         1          Relocatable file
  ET_EXEC        2          Executable file
  ET_DYN         3          Shared object file
  ET_CORE        4             Core file
  ET_LOPROC    0xff00       Processor-specific
  ET_HIPROC    0xffff       Processor-specific

 
어허 가만히 보니까, e_type이라는건 file의 종류가 어떤 거냐는 것을 표기해 놓은 것이네요. 1이면 Relocatable file 2면 Executalbe file등이네요. 그러면, 지금 살펴보던 file은 -c option을 이용하여 relocatable file을 만들었으니까, 값은 1을 가져야 하겠습니다. 진짜로 그런가 확인해 봅시다.
 
 
00000000h: 7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 ; ELF............
00000010h: 01 00 28 00 01 00 00 00 00 00 00 00 00 00 00 00 ; ..(.............
 
자, 앞에 16byte를 빼고서 (e_ident를 건너 띄우고), 2 byte를 읽어 보면 01 00 입니다. 이것을 Little Endian으로 해석해 보면, 00 01 이네요. 결국 1이라는 뜻이죠. 오오, 의외로 간단하네요. 내친 김에 하나 더? 라고 생각해 봤지만, 그다지 쓸모 있는 과정은 아닌 것 같습니다. 정말 그런가만 확인 했고요, 이제 와서 이런걸 자동으로 해주는 tool이 있다고 말하면 너무 무책임한 건가 - 뭐 어쩔 수 없잖아 - 라고 생각합니다. 죄송.
GCC bin utility를 보면, readelf라는 utility가 있는데, 이 녀석을 이용하면, 상당히 편하게 ELF file의 내용물을 들여다 볼 수 있습니다. (위와 같은 수고로움은 readelf가 없을 때, 해야 합니다.) 한번 들여다 봅시다. readelf는 다음과 같이 사용합니다.
 
readelf -h spaghetti.o     (-h 는 header 이라는 option이며, readelf에는 그 외에도 여러가지 option들이 있습니다. )
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              
REL (Relocatable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          860 (bytes into file)
  Flags:                             0x2000000, Version2 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         11
  Section header string table index: 1

 

헙, ELF header에는 위와 같은 내용들이 들어 있네요. 보시면, Type은 Relocatable이고, Machine은 ARM 이고,  뭐 이러니 저러니 떠들어 놓았습니다. 멍하니 두 눈의 근육을 풀어놓고 보고 있자니, 정말 편한 세상입니다. 
 
자, 이제 link를 해 보기 전에, 이 object file이 link를 하기 위해서 어떤 것들을 해 두었는지를 "연구"해 볼 까요. 우리가 살펴 보았던 ELF header의 크기를 환산해 보면 (다 더해보면), 52 byte입니다. (뭐, readelf를 통해서 알아낸 header의 정보 중 size of this header도 52 (bytes)라고 나와 있군요.) 그렇다면, 52 byte 이후에는 “도대체” 무엇이 있을 까요?
 
뭐 별거 있겠습니까 - 라고 말했지만 막막하기만 하죠 - 하지만, 길은 무조건 있기 마련이니까 걱정 마시고, 아마도 실제 코드 부분이 있을 거라 가정하고, 진짜 코드가 오지 않을까 확인해 보는 것은 어떨까요? spaghetti.c가 compile된 후에 기계어 (op code)으로는 어떻게 되었을까 확인하는 방법으로는, 실제 object code를 disassemble 해 보는 방법이 있습니다. Utility이름 처럼 fromelf - ELF로 부터 - 뭐든 할 수 있는가 봅니다.
 
fromelf -c spaghetti.o
 
결과를 보시면 많은 정보가 나와있는데, 나머지 정보는 천천히 심심할 때 훑어보시고, disassemble된 부분만 살펴 봐야죠.
 
 
 
** Section '.text' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
    Size   : 12 bytes (alignment 4)
    main
    $t
    .text
        0x00000000:    2003        .       MOV      r0,#3
        0x00000002:    2104        .!      MOV      r1,#4
        0x00000004:    1840        @.      ADD      r0,r0,r1
        0x00000006:    1810        ..      ADD      r0,r2,r0
        0x00000008:    4770        pG      BX       r14
    $d
        0x0000000a:    0000        ..      DCW    0
 
 
오오, main이라는 것이 Section #5 text 에 자리잡고 있네요. 오른쪽을 보면, 'Assembly로 만드는 방법 편'에서 보았던 Assembly가 보입니다 (완전 똑같네요 - 별로 놀라운 일은 아닌가 하는 생각이 문득 드네요.)
자 그러면, 정말 코드 영역은 왼쪽에 늘어선 숫자들인 2003 2104 1840 1810 4770 이겠네요. 16 bit Little Endian으로 다시 늘어 써 보면 0320 0421 4018 1018 7040 이고, 실제 이 값이 object file의 52byte이후에 적혀 있는지 확인해 보시도록 하시죠. (자 이 부분이 compiler 즉, machine에 따라 틀린 값이 되겠지요. ARM과 Intel은 서로 다른 Opcode로 동작 할 테니까요.) 
 
 
00000000h: 7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 ; ELF............
00000010h: 01 00 28 00 01 00 00 00 00 00 00 00 00 00 00 00 ; ..(.............
00000020h: 5C 03 00 00 00 00 00 02 34 00 20 00 00 00 28 00 ; \.......4. ...(.
00000030h: 0B 00 01 00 03 20 04 21 40 18 10 18 70 47 00 00 ; ..... 
.!@...pG..
00000040h: 03 00 00 00 03 00 00 00 28 00 00 00 FF FF FF FF ; ........(...
 
헉 정말 쓰여져 있네요. main() 함수를 처리하기 위한 op code는 보시는 바와 같이 얼마 되지 않습니다만, 그 외 linker를 통하여, 하나의 executable ELF로 만들기 위하여 만들어 두는 다른 section들이 있으니까, spaghetti.o 는 상당히 큰 file 이 됩니다. 다른 section들 중 몇 개만 readelf를 이용해서 확인한다면, spaghetti.o가 가지고 있는 symbol table과 relocation table입니다.
 
Symbol의 정의는 앞에 나왔으니까 잘 찾아보세요.
 
먼저, symbol table은 아래와 같이 형성되는데, 이 내용 중 눈 여겨 볼 것은 main()함수와 zi, rw, relocate 전역변수가 어디에 낑겨 있는지를 확인하는 것이 급선무 이지요.
 
 
Symbol table '.symtab' contains 20 entries
 Num:    Value       Size         Type      Bind  Vis      Ndx
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FUNC    LOCAL  DEFAULT    5 $t
     2: 0000000a     0 FUNC    LOCAL  DEFAULT    5 $d
     3: 00000000     0 FILE    LOCAL  DEFAULT  ABS spaghetti.c
     4: 00000000     0 OBJECT  LOCAL  DEFAULT    6 .bss$7
     5: 00000000     0 SECTION LOCAL  DEFAULT    6 .bss
     6: 00000000     0 OBJECT  LOCAL  DEFAULT    7 .data$10
     7: 00000000     0 SECTION LOCAL  DEFAULT    7 .data
     8: 00000000     0 OBJECT  LOCAL  DEFAULT    8 .data$15
     9: 00000000     0 SECTION LOCAL  DEFAULT    8 .data
    10: 00000000     0 SECTION LOCAL  DEFAULT    5 .text
    11: 00000000     0 OBJECT  LOCAL  DEFAULT    9 C$debug_frame1
    12: 00000000     0 NOTYPE  LOCAL  DEFAULT  ABS BuildAttributes$$THUMB_IS
    13: 00000000     0 FUNC    WEAK   DEFAULT  UND Lib$$Request$$armlib
    14: 00000000     4 OBJECT  GLOBAL DEFAULT    6 zi
    15: 00000000     4 OBJECT  GLOBAL DEFAULT    7 rw
    16: 00000000     4 OBJECT  GLOBAL DEFAULT    8 relocate
    17: 00000000    10 FUNC    GLOBAL DEFAULT    5 main
    18: 00000000     0 FUNC    GLOBAL DEFAULT  UND __main
    19: 00000000     0 FUNC    GLOBAL DEFAULT  UND _main
 
 
Symbol table의 내용 중 Name은 Linker를 위한 symbol 이름이고, Value는 각 section에서의 해당 symbol의 시작 offset 주소를, Size는 Symbol의 크기 (Symbol이 function이나 object가 아닌 경우에는 0), Type은 Function, Object, Section 등을 나타내며, Bind는 Symbol의 scope를 한정 (Local, Global, Weak) 합니다.
 
약간의 참고로, Ndx에 보시면, UND는 현재 file에서 사용되고 있지만, 실제 함수의 define이 없는 경우를 의미하며, ABS는 relocate 되어서는 안 되는 것을 의미해요 그리고, Ndx= 1이면,.text section을 의미하고요, Ndx=3이면, .data를 의미하는 거죠. Symbol의 scope를 한정하는 것 중 WEAK의 경우는 LOCAL로만 쓰일 가능성이 큰 symbol을 의미하지요.
 
자세히 보시면, main()은 FUNC (function)이며, GLOBAL로 처리 되고, zi, rw, relocate 역시, GLOBAL variable로 처리가 되어 있음을 확인할 수 있습니다. 다른 file의 함수 등에서 이 global 변수나, 함수를 만지거나, 호출하게 되는 경우 linker가 바로 이 table을 이용하여, 서로를 엮어주는 역할을 하게 됩니다. compile된 file이 수천 개가 될 경우, 이에 대한 table들을 서로 전부다 엮어야 되니까, linker는 해야 하는 일이 엄청 많겠죠? 
이런 식으로 따져 가다 보면, - ELF specification을 전부다 분석하다가 진짜로 무엇을 하려고 했는지,  잊어버릴 수도 있으니까, 실제 분석은 ELF specification을 보시는 것이 도움이 되겠습니다. 덜덜덜 - 실제적인 ELF의 형식을 다음 그림과 같이 표현할 수 있겠습니다.
 
 
 
 
실제 spaghetti.o 구조를 위의 ELF 구조에 맞추어서 다시 그려보면, spaghetti.o 구조가 어떤 것인지, 확연하게 알아보실  있으리라 생각하고 있습니다. 진짜 spaghetti처럼 그림이 엉켜 버렸네요.

 
 
이런 식으로 object file을 만들어 두면, Linker가 이것들을 보고서 막 연결할 수 있겠다는 자신감이 들기 시작합니다. 이런 식의 자세한 분석에 너무 심각하게 되진 말아주세요. -그리 자세하지도 않지만-
 
마지막으로 기타 Section들까지 모두 자세히 들여다 본다면
 
 
 
뭐 이런 식이고요
 
위의 .text는 code,  .rodata, .data, .bss는 Data영역에 속하니까 잘 아시겠고 다른 section들의 의미는 뒤에 더 자세히 다루니까 걱정 말고 넘어가 주세요. 
 
 ELF format에 대하여 한가지 더 덧붙이자면, section은 서로 관련이 있는 녀석들끼리 묶이게 마련인데, 이런 관련성이라는 것이 3가지 정도로 나뉘게 되지요. 코드들은 text라는 section, 초기화 된 전역변수는 data라는 section, 그리고, 마지막 초기화 되지 않은 전역 변수들은 bss 라는 section에 같이 묶이게 됩니다. symbol table에도 보면, 오른쪽에 bss, data, text등이 있는 것을 보실 수 있습니다.  그런데, data, text는 무슨 뜻인지 알겠는데, bss는 도대체 어디서 온 말일까? 라는 의문이 제 머리를 사로 잡은 적이 있습니다. bss의 의미는 1950년대 IBM704 assembly에서부터 나온 것으로서 Block Started By Symbol인데 소프트웨어 공학으로 유명한 카네기 멜론대학교의 어떤 사람은 "Better Save Space"라고도 하던데요. 과연 저도 말장난 하나 더 하자면, "Better Save ROM Space" 라고 부르면 혼날까요? 진정한 bss의 의미는 Scatter Loading을 알게 되면 확실하게 감 오실 거에요.
Block Started By Symbol의 의미도 Scatter Loading에서 더 자세히 알게 되실 거에요
 
 Link에서 ELF 형식에 대해서 더 자세히 볼 것이니 이번 판에 너무 기대 많이 했다면, 다음 판을 기대하세요.
블로그 이미지

wtdsoul

,

https://smartstore.naver.com/mhivestore/products/4953744659

https://github.com/ChrisWonyeobPark/M-HIVE_STM32_tutorial_course

 

GitHub - ChrisWonyeobPark/M-HIVE_STM32_tutorial_course: Source code for M-HIVE STM32 tutorial course (TrueSTUDIO and STM32CubeID

Source code for M-HIVE STM32 tutorial course (TrueSTUDIO and STM32CubeIDE) - GitHub - ChrisWonyeobPark/M-HIVE_STM32_tutorial_course: Source code for M-HIVE STM32 tutorial course (TrueSTUDIO and STM...

github.com

 

'하드웨어 해킹 및 임베디드' 카테고리의 다른 글

Embedded Recipes  (0) 2023.04.11
ELF format Object File에 관한 진실  (1) 2023.03.14
TELECHIPS社 TCC8925 안드로이드용  (0) 2023.02.15
자동차 관련 교육 과정  (0) 2023.01.17
Car Hack Github 경로  (0) 2023.01.13
블로그 이미지

wtdsoul

,

TELECHIPS社 TCC8925 안드로이드용 : 네이버 블로그 (naver.com)

 

TELECHIPS社 TCC8925 안드로이드용

2012년도 출시한 TELECHIPS社 TCC8925 안드로이드용 CPU 입니다.   텔레칩스는 데이터...

blog.naver.com

 

TCC 8925

'하드웨어 해킹 및 임베디드' 카테고리의 다른 글

ELF format Object File에 관한 진실  (1) 2023.03.14
STM32 보드 임베디드 진행 전  (0) 2023.02.19
자동차 관련 교육 과정  (0) 2023.01.17
Car Hack Github 경로  (0) 2023.01.13
CVE-2022-38766 AUTOCRYPT  (0) 2023.01.12
블로그 이미지

wtdsoul

,

 

한컴아카데미 IT융합 전문교육센터 (hancomacademy.com)

 

한컴아카데미 IT융합 전문교육센터

 

hancomacademy.com

 

 

 

 

 

 

 

'하드웨어 해킹 및 임베디드' 카테고리의 다른 글

STM32 보드 임베디드 진행 전  (0) 2023.02.19
TELECHIPS社 TCC8925 안드로이드용  (0) 2023.02.15
Car Hack Github 경로  (0) 2023.01.13
CVE-2022-38766 AUTOCRYPT  (0) 2023.01.12
How I Hack my car 경로 참고  (0) 2023.01.11
블로그 이미지

wtdsoul

,