-
Notifications
You must be signed in to change notification settings - Fork 14
find_frames
Target: we want to find, which CAN frame do some chosen action. Let's say we want to control WINDOWS actions, like UP and DOWN.
First of all we need to find a CAN bus where those commands are flying. For 99% you will not find these frames on OBDII, since this used only for diagnostics. So maximum you can find there could be status frames (like information about currents status of WINDOW's). You need to find CAN bus where these messages can be found. In general CAN bus is a differential pair (but there also possible that in YOUR can there can be 1 wire's CAN BUS, not classical pair....). In the Interent you can find help - first, original documentation from the vendor. Yes, this is not so easy, but it is possible for some vendors and models. Second - custom-anti-thief solution often have documentation about how to install this system on each CAR, and in 99% cases there should be description of where are CAN buses, how to reach it and finally what colors those wires are. Anyway, most useful tool here is MULTIMETER. With help of multimeter you can try to detect if those wires are CAN or not, simply by checking resistance: it should be 60 or 120 ohm (depends on configuration and situation).
120 ohm example:
60 ohm:
When you have found needed CAN bus, you should connect device (USBtin, for example. For my opinion it is best USB2CAN device based on MCP2515). Be careful with HOW YOU connect to BUS. try do not CUT wires and etc. If possible use something like needles and connect them into sockets, like we doing.
Neeeeeedles:
Now we ready to use CANToolz. And the logic here is pretty simple. Just sniff tow sets of CAN traffic - with action and without, then do simple set difference and find needed frame. Sounds simple but there is some small details. Let's do it.
First step we need to prepare config. We need next modules: hw_USBTin for CAN bus I/O, then we need mod_stat for DIFF sets and collecting traffic. Additionally we might need gen_replayif we want to replay DIFF dumps back to BUS. Config file will look like that:
# Load needed modules
load_modules = {
'hw_USBtin': {'port':'auto', 'speed':500}, # IO hardware module
'gen_replay': {}, # Module for sniff and replay
'mod_stat': {} # Stats
}
# Now let's describe the logic of this test
actions = [
{'hw_USBtin': {'action': 'read','pipe': 1}}, # Read to PIPE 1
{'mod_stat':{}}, # Dump DIFF replay or replay from PIPE 1
{'gen_replay': {'pipe': 2, 'delay':0.06}}, # Load dumped and then replay to PIPE 2
{'hw_USBtin': {'action':'write','pipe': 2}} # Write generated packets (pings)
]
load_modules - just enumeration of modules that we will need and also initial configuration for them. As we said, we need just 3 modules. Interesting moment here is SPEED. If you do not know speed you can try to use oscilloscope, or just brute force values: high-speed bus normally is 500, low speed - 125, but there are a lot of exclusions 8)
actions - describes circuit of the test. Here we can see list of actions in order: from first to last. These action will be executed in the loop. Most important concept here is PIPE. It's kind of "parallelization" of action. I will describe how we can read this config as one iteration of the loop:
-
hw_USBtin will read one CANFrame from the BUS and put it into PIPE 1.
-
mod_stat will read and save in memory one CANFrame from PIPE 1
-
gen_replay is ready to send CANFrames when needed to PIPE 2
-
hw_USBtin will read CANFrame from PIPE 2, and if there is one - write to the BUS
That's all we need. Let's run this: python cantoolz.py -g w -c this_config.py Then you can use web-browser and follow this link: http://localhost:4444/
Here you can see WEB GUI and actions from config. You could click on each action, to see parameters and commands. You can change parameters and send commands. So first we need to collect simple set of traffic with no actions. We will use this set to make diffs with other traffic sets that have some actions inside we want to find. For that just turn on car, wait few seconds and press START. After one minute we will have enough data for doing diffs, so click on mod_stat and send STOP command to that module. After that we are ready for collection traffic with action. For that we need to create another buffer in mod_stat, just use command: "Switch sniffing to a new buffer". You can name that buffer, then later it will be easier to understand what is where:
Here you can see that in buffer with index 0 we have 43k frames. That is what we have sniffed on first stage. Than we have created another buffer (index 2) and named it "WINDOWS_ACTION". Now we ready to sniff this action and find control frame! Just Activate mod_stat and perfom this action - press button inside car that will down all windows. When event will be finished (or just started) stop mod_stat again. Now if you want to see "Current status" you will see that in our second buffer (index 1, "WINDOWS_ACTION") we have around 1k frames. Now we need to find only one we need! For that you can do many different strategies, like dump this buffer into file and replay half by half, but I think this is not efficient way. Let's do a diff between two buffers we have as we wanted. But even there we have different situation. Let me describe case number 1. In this case "command" frame used only when action happening. So if you pres button once, we will see this frame with uniq. arbitration ID once. Very simple. Then just press "Print Diff between two buffers (new ID only)". If so, you will see few or one CAN frames that was not found in buffer with index 0. You can dump it into a file and then load this dump and replay with gen_replay. But this is simple case. We also had another experience, when frame with needed Arbitration ID always exists in the traffic (index 0, index 1) so you can't find it by using previous command. It's works very close to "status" frames: when windows closed, we have one value, when they change status to "full open" then same ID already have different DATA. And we can do DIFF for that as well. But problem there that there are a LOT of frames that have changed their data in new set:
As you can see this is not helping. BUT, we know that if this "command" is here, then it's value should be changed in "binary" form. Because before WINDOWS were closed, now they are opened. So if we can set a filter on DIFF, like how many different uniq. values we are looking for each ID, then it should help. Let's do it!
So here is much less data to analyze. Now we can replay it and this replay will work as needed. Also we can check each ID from this list (or if you can SEE which frame is looks like command here) by using "Search ID in all buffers". It will help us to see how this frame was changed from one buffer to another. Anyway, one if these frames is exactly what we are looking for. To find it you need just use binary-search and for this small set it is easy and fast!