GithubHelp home page GithubHelp logo

caringcaribou / caringcaribou Goto Github PK

View Code? Open in Web Editor NEW
675.0 675.0 180.0 508 KB

A friendly car security exploration tool for the CAN bus

License: GNU General Public License v3.0

Python 100.00%
can-bus ecu fuzzing python security-scanner security-testing xcp

caringcaribou's Introduction

Caring Caribou

A friendly automotive security exploration tool.

Rationale

This work was initiated as part of the research project HEAVENS (HEAling Vulnerabilities to ENhance Software Security and Safety), but lives on as a stand-alone project. We were lacking a security testing tool for automotive; a zero-knowledge tool that can be dropped onto any CAN network and collect information regarding what services and vulnerabilities exist. This project is a start.

Documentation

Get started

Install the tool:

python setup.py install

The best way to understand how to use Caring Caribou is to look at the help screen:

caringcaribou --help

This will list all available modules at the bottom of the output. Help for specific modules works the same way. For example, the help screen for the send module is shown by running

caringcaribou send --help

The module help always includes some usage examples. If the module has multiple sub functions, these have similar help screens as well:

caringcaribou send message -h
caringcaribou send file -h

More detailed usage information is available in the documentation on usage.

Features and Architecture

Caring Caribou is based on a main entry point in caringcaribou.py which runs the show. This enables an easy drop-in architecture for new modules, which are located in the caringcaribou/modules folder.

The caringcaribou/utils folder contains various higher level CAN protocol implementations and shared functions, meant to be used by modules.

The caringcaribou/tests folder contains automated test suites and /documentation stores documentation files (modules are also documented here).

List of Modules

A clean installation of Caring Caribou includes the following modules:

uds - Universal Diagnostic Services

Discovers and utilizes various ISO 14229-1 services.

  • discovery - Scans for ECUs supporting diagnostics services
  • services - Scans for diagnostics services supported by an ECU
  • subservices - Subservice enumeration of supported diagnostics services by an ECU
  • ecu_reset - Reset an ECU
  • testerpresent - Force an elevated session against an ECU to stay active
  • dump_dids - Dumps values of Dynamic Data Identifiers (DIDs)
  • auto - Fully automated diagnostics scan, by using the already existing UDS submodules

Details here: uds module

xcp - Universal Measurement and Calibration Protocol (XCP)

  • discovery - Scans for ECUs supporting XCP
  • info - XCP Get Basic Information. Retrieves information about XCP abilities of an ECU
  • dump - XCP Upload. Used to dump ECU memory (such as SRAM, flash and bootloader) to file

Details here: xcp module

fuzzer - CAN fuzzer

  • random - sends random CAN messages
  • brute - brute forces all possible messages matching a given bit mask
  • mutate - mutate selected nibbles of a given message
  • replay - replay a log file from a previous fuzzing session
  • identify - replay a log file and identify message causing a specific event

Details here: fuzzer module

dump - Dump CAN traffic

Dumps incoming traffic to stdout (terminal output) or file

Details here: dump module

send - Send CAN packets

Raw message transmission module, used to send messages manually from command line or replay dump files

Details here: send module

listener - Listener

Lists all distinct arbitration IDs being used on the CAN bus

Details here: listener module

test - Run test suite

Runs automated Caring Caribou test suites

dcm - [deprecated] Diagnostics Control Module

Note: This module has been replaced by the UDS module. It is still supported by CC due to legacy reasons.

Details here: dcm module

uds_fuzz - Universal Diagnostic Services Fuzzer

Fuzzing module for UDS security seed randomness evaluation and testing.

  • seed_randomness_fuzzer - ECUReset method fuzzing for seed randomness evaluation
  • delay_fuzzer - delay fuzzing for targets with weak randomness implemented, to match acquired seed/key pair to the delay in which the seed can be requested

Details here: uds_fuzz module

doip - Diagnostic communication over Internet Protocol

Discovers and utilizes various ISO 13400-2 services.

  • discovery - Scans for ECUs supporting diagnostics services
  • services - Scans for diagnostics services supported by an ECU
  • ecu_reset - Reset an ECU
  • security_seed - Request security seeds from an ECU
  • testerpresent - Force an elevated session against an ECU to stay active
  • dump_dids - Dumps values of Dynamic Data Identifiers (DIDs)
  • seed_randomness_fuzzer - ECUReset method fuzzing for seed randomness evaluation

Details here: doip module

List of libraries/utilities

The caringcaribou/utils folder contains the following:

can_actions.py

Provides abstraction for access to the CAN bus, bruteforce engines etc.

common.py

Contains various common functions, type converters etc.

constants.py

Constant definitions

iso14229_1.py

Implementation of the ISO-14229-1 standard for Unified Diagnostic Services (UDS).

iso15765_2.py

Implementation of the ISO-15765-2 standard (ISO-TP). This is a transport protocol which enables sending of messages longer than 8 bytes over CAN by splitting them into multiple data frames.

Hardware requirements

Some sort of CAN bus interface (http://elinux.org/CAN_Bus#CAN_Support_in_Linux)

Software requirements

  • Python 2.7 or 3.x
  • python-can
  • a pretty modern linux kernel

Extending the project with new modules

  • A template for new modules is available in caringcaribou/modules/module_template.py
  • Create a python file with a function module_main(args) (or copy the template) in the caringcaribou/modules directory.
  • In setup.py, add an entry under caringcaribou.modules, referencing your new module like: my_module = caringcaribou.modules.my_module
  • Run python setup.py install
  • Verify that the module is available, it should be listed in the output of caringcaribou -h

If your new module is located in caringcaribou/modules/foo.py you will run it with the command caringcaribou foo. Additional arguments (if any) are passed as arguments to the module_main function.

The target

The target ECU used for the development setup is an STM32F107 based dev-board from ArcCore called Arctic EVK-M3, but the tool can be used against any ECU communicating over a CAN bus.

Contributors

  • The HEAVENS project, funded by VINNOVA
  • Christian Sandberg
  • Kasper Karlsson
  • Tobias Lans
  • Mattias Jidhage
  • Johannes Weschke
  • Filip Hesslund
  • Craig Smith (OpenGarages.org)
  • internot
  • Mathijs Hubrechtsen
  • Lear Corporation
  • sigttou
  • FearfulSpoon
  • Alex DeTrano
  • Thomas Sermpinis
  • Alexander Alasjö
  • Vincent de Chefdebien

caringcaribou's People

Contributors

alasjo avatar alexdetrano avatar bhass1 avatar cr0wtom avatar fearfulspoon avatar frosttusk avatar ggonzalez avatar internot avatar jackdunham avatar johbraun avatar kasperkarlsson avatar mjidhage avatar shutingrz avatar sigttou avatar superuserx avatar toblans avatar vdechef avatar zombiecraig avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

caringcaribou's Issues

Remove subfunction indicies #1 brute force

Using dcm subfunction source dest service 1 (with index = 1) actually bruteforces the service-field. Makes no sense since it is part of another argument. Either change the meaning of the index or make 0 and 1 illegal input

Incorrect information printed after successful xcp discovery

Ran ./cc.py xcp discovery -min 0x3 towards a target. The discovery got a response on one of the CONNECT attempts, decoded the response and continued searching for more. When the search reached 0x7ff the printout "XCP could not be found: Brute force of range 0x3-0x7ff completed", which indicates failure.

Well, apparently this repo is dead, soooooo

With all due respect, you guys built something amazing, and not maintaining it is simply disgraceful. I feel like I am just going to work off of my fork and not pass upstream, considering nobody here is paying attention. :/ Really sad.

Implement arbitration ID blacklisting in XCP discovery

Same as #7, but for XCP. We need a way to blacklist responses from individual arbitration IDs from command line. It would also be nice with a passive scan for automatic blacklisting before starting the discovery.

It would make sense to add a blacklisting engine to can_actions.py and use this for both DCM and XCP.

Add possibility to continue after successful diagnostic discovery

executing "./cc.py dcm discovery" searches for diagnostic services by sending TesterPresent to one ArbID at a time. After a successful hit, the module hit reports what arbid replied and what arbid was used in the reply.

The user can continue to search the rest of the adress space using -min flag but to make it even easier for the user a question to the user would be useful "Do you want to continue the search?". Another approach could be to automatically continue the search. If the user only is interested the first result he/she can interrupt the search with ctrl-c

ISO 15765-2 (ISO-TP) support

Implement support for ISO 15765-2, which makes it possible to send data packets of sizes up to 4095 bytes over CAN.

From https://en.wikipedia.org/wiki/ISO_15765-2:

ISO 15765-2, or ISO-TP (Transport Layer), is an international standard for sending data packets over a CAN-Bus. The protocol allows for the transport of messages that exceed the eight byte maximum payload of CAN frames. ISO-TP segments longer messages into multiple frames, adding metadata that allows the interpretation of individual frames and reassembly into a complete message packet by the recipient. It can carry up to 4095 bytes of payload per message packet.

Send list of messages from file

Add a replay feature for an existing CAN dump, so that pre-defined lists of messages can easily be sent without adding them as command line arguments. This would e.g. be useful for repeatable exploits and automated testing.

It would make sense to add this as a -f <filename> flag to /tool/modules/send.py

Some reasonable input formats are

  1. Default /tool/modules/send.py argument format
  2. python-can (default dump format for /tool/modules/dump.py)
  3. candump (as produced by /tool/modules/dump.py with -c flag).

Security access seed randomness analysis

Implement a module which analyses randomness of seeds for security access. Data can be gathered by sending a (large) number of Request Seed [0x27 0x01] messages.

What about ECUs which only renew their seed on boot? Maybe a renewal can be triggered by responding to the seed with an invalid key? Any other ideas?

Update RaspberryPi install instructions

Latest raspberry pi has switched to Device Tree making kernel module install much easier.

http://downloads.raspberrypi.org/raspbian/images/raspbian-2017-07-05/2017-07-05-raspbian-jessie.zip

sudo apt-get update
sudo apt-get upgrade
sudo reboot
Add the overlays by:
sudo nano /boot/config.txt
Add these 3 lines to the end of file:
dtparam=spi=on
dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=25
dtoverlay=spi-bcm2835-overlay

sudo /sbin/ip link set can0 up type can bitrate 500000

pip install

git clone

Wrong limit for auto-detecting base/extended arbitration ID in send function

Reported by Bill Hass (@bhass1) through a comment to 481fd94

This patch should check for arb_id > 0x7ff (11-bits) instead of 0xffff (16-bits). This will cause unexpected behavior when using CAN IDs between 0x7ff and 0xffff.

Current implementation: https://github.com/CaringCaribou/caringcaribou/blob/master/tool/can_actions.py

if not is_extended:
  is_extended = arb_id > 0xffff

The limit should be changed to ARBITRATION_ID_MAX (which is defined as 0x7FF)

DCM discovery issue

I just tested a car yesterday, run "python cc.py dcm discovery""

As the car I tested that it will generate periodic can message 0X12D, and msg.data[1]=50, I got almost every airID that support services.

It's normal response after checking the source in the below:

  def response_analyser(msg):
            # Catch both ok and negative response
            if msg.data[1] in [0x50, 0x7F]:
                print("\nFound diagnostics at arbitration ID 0x{0:04x}, "
                      "reply at 0x{1:04x}".format(arb_id, msg.arbitration_id))
                can_wrap.bruteforce_stop()
        return response_analyser

NotImplementedError: Invalid CAN Bus Type - None

pyhton vsersion: python-2.7

python-can vsersion: python-can (3.1.1)

example:
sudo python cc.py dcm discovery -min 0x700 ()


CARING CARIBOU v0.1

Loaded module 'dcm'

Traceback (most recent call last):
File "cc.py", line 114, in
main()
File "cc.py", line 106, in main
mod.module_main(args.module_args)
File "modules/dcm.py", line 417, in module_main
args.func(args)
File "modules/dcm.py", line 199, in dcm_discovery
with CanActions() as can_wrap:
File "/home/qili/Desktop/AAAAA/caringcaribou/tool/can_actions.py", line 64, in init
self.bus = can.interface.Bus()
File "build/bdist.linux-x86_64/egg/can/interface.py", line 108, in new
File "build/bdist.linux-x86_64/egg/can/util.py", line 197, in load_config
NotImplementedError: Invalid CAN Bus Type - None

I used all the modules, it all prompted NotImplementedError: Invalid CAN Bus Type - None

I tried to install the old version of the python-can module, but still can't solve my problem. Please help me answer, thank you very much. I am very anxious. Thank you!

TypeError: bruteforce_data_new() got an unexpected keyword argument 'callback_end'

Run dcm subfuc instruction as follows, and got an error:

python cc.py dcm subfunc 0x710 0x77a 0x24 2


CARING CARIBOU v0.1

Loaded module 'dcm'

Starting DCM sub-function discovery

No sub-functions were found

Traceback (most recent call last):
File "cc.py", line 114, in
main()
File "cc.py", line 106, in main
mod.module_main(args.module_args)
File "modules/dcm.py", line 367, in module_main
args.func(args)
File "modules/dcm.py", line 299, in subfunc_discovery
callback_end=finished)
TypeError: bruteforce_data_new() got an unexpected keyword argument 'callback_end'

How to read ECU EEROM via OBD/CAN?

I apologize in advance that this question isn't specific to this project.

How are tuning manufacturers able to download the EEPROM from the ECU via OBD-II, tune it, then reupload it? For example, do Bosch ECUs have a special proprietary command that is not documented anywhere to send the ECU into a boot mode?

Any information you can share would be helpful.

Update module template

The current template has an ineffective way of handling incoming messages through callbacks. Let's update it to a more intuitive, iterative approach.

Argument to automatically pad data length in send module

Some ECUs require messages to be padded to full length (typically 8 bytes), even though the actual payload within the message may be shorter. When performing manual testing against such targets, the user needs to add a bunch of .00 data bytes after the payload to pad the message to the correct length.

It would be nice to have an optional argument which enables automatic padding, so that e.g.
./cc.py send message -pad 0x123#67.89
would automatically be padded to correspond to
./cc.py send message 0x123#67.89.00.00.00.00.00.00
in order to simplify such use cases.

Delay between messages - UDS

I am testing a device (blackbox testing) and the result from the UDS service enumeration script is giving me 255/255 as the enabled services.

I know in fact that in the device not every service is open. So my guess is that there is some kind of security mechanism checking for the delay between the UDS messages sent consecutively.

Could this be the issue, and if yes, can the feature be implemented in a future update?

Add support for comments in files used by 'send files'

Usable when creating testfiles or traffic files used in training. Suggest using a standard/existing comment syntax, for instance the '#'. This change would also make it possible for 'dump -f' to add an informative header, if desired

Add global interface argument

Add a global interface argument to cc.py.

This would simplify global support for switching interfaces (can0, can1, vcan0 etc), without having to add this logic in every separate module.

Add DoS module

Add a module for performing various denial of service (DoS) attacks.

Useful features could include:

  • Spam messages with low arbitration ID
  • Spam error frames
  • Spam ECU reset messages to a certain ECU

Simplify bitmasks in fuzzer module

The brute force and mutate modes of the fuzzer module let the user specify initial payloads and bit masks for these as separate arguments. Indices with value 0 in the bit mask will be kept as-is from the initial payload, while 1 means the value can be overridden by the fuzzing algorithm.

It would be simpler if the initial payload and bit mask were combined in a single argument. Values in the initial payload that should be overridden could simply be replaced with e.g. a dot and the bit mask could be removed altogether.

That way, the command
./cc.py fuzzer mutate -d 12ab89ef -db 01001100 -i 7fff -ib 0111
would instead be written
./cc.py fuzzer mutate -d 1.ab..ef -i 7...

Add standalone mock ECU module

It would be nice to be able to simply start a mock ECU directly through a separate module for testing, e.g. ./cc.py -i vcan0 mock uds to start a UDS mock ECU on interface vcan0. This could prove useful when playing around, learning new protocols or developing new modules.

missed files

I'm trying to run DoiP module and it doen't work.
From the Doip.py, there is somes import (import DoipClient and import udsonscan) but the python file corresponding to these import weren't present in the repo.
Is it possible to push again theses files ?
King regards.

CAN fuzzing module

Implement a basic CAN fuzzing module. Preferably based on a PRNG which can be seeded via an optional command line argument for repeatability.

What kind of subfeatures could be useful? E.g. fuzzing message contents against certain arbitration IDs / fuzzing the arbitration IDs as well?

Also, can we analyze responses in a generic way?

Interface Agnostic Handling of Multiple Interface Devices (Remove SocketCAN specific interface flag '-i')

Currently the cc.py module takes a '-i' argument which is meant to specify the SocketCAN interface (e.g. can0 or vcan0). However, CaringCaribou uses python-can as its CAN abstraction layer enabling support for a variety of device interfaces and drivers.

I propose removing the '-i' flag altogether and let python-can handle whether can0, vcan0, or whatever interface along with its settings is used.

A help message pointing to the python-can docs (https://python-can.readthedocs.io/en/3.1.1/configuration.html) should be included when "cc.py -h" is ran.

Negative delays when saving dump to file

While I was sending a dump file I got a python exception that sleep requested negative delays.
When I searched the output file, I found that the difference between the timestamp of some lines was indeed negative.

For example:

Timestamp: 1541504408.838742        ID: 0191    S          DLC: 7    01 00 10 a1 41 00 1a
Timestamp: 1541504408.838750        ID: 0133    S          DLC: 5    00 00 00 00 b6
Timestamp: 1541504408.838748        ID: 0244    S          DLC: 5    00 00 00 01 44
Timestamp: 1541504408.838758        ID: 0136    S          DLC: 8    00 02 00 00 00 00 00 39
Timestamp: 1541504408.839845        ID: 013a    S          DLC: 8    00 00 00 00 00 00 00 37

Inconsistent use of padding in xcp module.

Is there a reason why the padding is omitted for xcp connect in line:

can_wrap.send_single_message_with_callback([0xff], handle_connect_reply)

but not for other xcp subfunctions like the command discovery:

def xcp_command_discovery(args):
"""Attempts to call all XCP commands and lists which ones are supported."""
global connect_reply, command_reply
send_arb_id = args.src
rcv_arb_id = args.dst
connect_message = [0xFF, 0, 0, 0, 0, 0, 0, 0]

Without padding the ECU receives frames that are not consistently 8 bytes which leads to problems parsing the frame.

Suggested fix: Consistent use of padding and change

can_wrap.send_single_message_with_callback([0xff], handle_connect_reply)

to

can_wrap.send_single_message_with_callback([0xff, 0, 0, 0, 0, 0, 0, 0], handle_connect_reply)

Per-session log file

I suggest adding an appended log recorder, like a blackbox with datetimed results and user actions, with an user-setting for "how big" the log should be and trim it if needed. So in case you need to review some data or behaviour not within the session but another day or week even..as far as the log file size is set, in plain human readable text. This might be helpful as it really comes in handy sometimes on my Dataman chip programmer to actually double check if I did program a chip in the past and what data was loaded into.

0x7ff erroneously detected as diagnostic service

While running dcm discovery a 0x733/0x633 combo appeared in the result screen. A new discovery started at 0x734 with nostop option detected a 0x7ff/0x633 combo. A bit suspicious since it is the last id before automatic stop of scan (assumption does not support extended id). Needs verification.

Bruteforce security access key and security levels

Hello,

I am currently getting familiar with car hacking and found your tool.

Since I am not an expert in the field I got two questions regarding possible additions to CC.

Would it be an appropriate use case for caringcaribou to add a function to bruteforce the security access key after the seed request?
I also wondered if it makes sense to try all possible values for the security level (related to cc.py uds security_seed) when checking an ECU.

Thanks!

Support for UDS over DoIP

Hello guys,

A lot of manufacturers start using this implementation. It will be good to see if first of all it is applicable and if we can implement it in the tool. It will be a nice addition.

Add start index argument to 'random' and 'mutate' fuzzer methods

The -index/-i flag in the brute fuzzing method makes it possible to start at a certain index. This lets the user jump to a certain range of interest and also makes it possible to resume a previous session.

Let's add support for this in the random and mutate methods as well!

Handle new python-can flag format in send module

python-can 2.1.0 introduces breaking changes of the flag format when a Message instance is casted to str. Both the old format (consecutive binary flags) and the new format (character flags separated by spaces) must be supported.

The previous commit c29e1f9 only takes care of the case where exactly one flag is set (quick non-breaking fix, but only covers one of multiple cases).

Dump not complete when using python3

When dumping the CAN bus using the dump module to either a file or just stdout some packets are missing when using python 3.
I tested using a virtual can bus and the ICSim application.

When changing the python interpreter to python 2 all packets are logged but when using python 3 some packets (such as the blinker controls for example) are missed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.