The CAN bus for most Honda models use a rolling counter and checksum. This allows missed frames to be accounted for as well as being a layer of security. The simplest and most direct way of manipulating the CAN bus, is a MITM device. This means you will have to physically place your MCU in-between the ECU you want to “emulate”. This sounds scary, and it certainly is. This isn’t something you should get into unless you intend on finishing it (or potentially end up with an unusable car until you do).
Now there are other ways that are more applicable to certain cars, more specifically ones with poor security (or none at all) on the OBD connector. Cars with a gateway will typically filter out signals from multiple lines, like B-CAN and F-CAN, which are usually only status bytes anyway. Some cars may not allow any CAN bus traffic from the OBD port at all, and are much more difficult to deal with. Getting even simple live broadcast data may require direct access to the CAN-H/CAN-L wires under your steering column or radio harness.
After digging into the Full Service Manual for the 9th gen 2013-2016 Accord, I discovered several things about the gateway. The gateway is the Gauge Control Module which is essentially just the entire instrument cluster. Every ECU is connected on the F-CAN and B-CAN line, which both connect to this gateway module. There are a few other physical inputs, like the VSA OFF switch, or maybe seatbelt status. Most of these are transmitted on the CAN lines though. Typically, the higher priority values come from actual ECUs transmitting vital vehicle data (such as VSA sending out individual wheel speeds) and the gateway will receive them, then output new frames combined with other data that is sent back out on the CAN lines for another ECU to receive.
Using the full service manual to see which ECU sends/receives what data (comm diagnostics make this a little easier, showing errors when certain data is missing) makes finding out which frames belong to which ECUs (or which ones are being outputted by the gateway module). This can also help you find out which data you are missing from a frame if you have most of it decoded.
Figuring out which frame is going to which ECU(s) will allow you to hijack them in 1 way- MITM. You will have to put a device in between the gateway module and the rest of the network. This allows you to easily filter out and create your own fake stream of CAN frames.
You can also sniff the traffic both ways, and find out exactly what frames come ONLY from the gauge cluster. These are typically the only frames you will be able hijack, as you’d have to intercept the ECU of whatever incoming frame it was you wanted to change. You could possibly effect something by changing what the gauge module sees if you attempt this anyway, as some frames sent from the gauge module are still used by other ECUs and not just as a status frame.
Another untested method that would only requiring tapping somewhere on the bus, would be overriding the frame by sending one before the ECU/gauge cluster does. Since Honda uses a counter/checksum system, as long as timing isn’t too tight (it most likely is) and missed/corrupt frames don’t cause the BUS to go haywire (it most definitely will) you could make the respective ECUs reject the real frame as its counter will no longer be correct. I doubt this will work, at least on this generation of cars.
Comma.AI uses this method (MITM) on the ADAS/LKAS module to fabricate their own steering wheel, gas, and brake commands. This is an example of them reverse engineering what frames were being received by the ECU (radar information) and what it outputted (vehicle control commands). This allowed them to create an entire custom control system, simply because the manufacturers had the ECUs setup to take frames from not just user input, but commands from other ECUs that were east to intercept. You could control the gas and brakes on a car without ADAS/LKAS (not steering because of mechanical reasons) with the right interception, but is much less forgiving
.
uint8_t hondaChecksum(uint32_t address, uint8_t *data, uint8_t len) {
int sum = 0;
bool extended = address > 0x7FF;
// Sum nibbles of address
while (address) {
sum += (address & 0xF);
address >>= 4;
}
// Sum nibbles of data
for (uint8_t i = 0; i < len; i++) {
uint8_t b = data[i];
// For last byte, only count upper nibble (skip checksum)
if (i == len - 1) {
b >>= 4;
sum += (b & 0xF);
} else {
sum += (b & 0xF) + (b >> 4);
}
}
if (extended) sum += 3;
return (8 - sum) & 0xF;
}